diff --git a/jre_emul/Classes/com/google/j2objc/security/IosSHAMessageDigest.java b/jre_emul/Classes/com/google/j2objc/security/IosSHAMessageDigest.java index 80d2e834f1..6767cf13ee 100644 --- a/jre_emul/Classes/com/google/j2objc/security/IosSHAMessageDigest.java +++ b/jre_emul/Classes/com/google/j2objc/security/IosSHAMessageDigest.java @@ -18,6 +18,7 @@ package com.google.j2objc.security; import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.security.MessageDigest; /*-[ @@ -54,6 +55,21 @@ protected void engineReset() { buffer.reset(); } + public Object clone() throws CloneNotSupportedException { + IosSHAMessageDigest obj = (IosSHAMessageDigest) super.clone(); + // ByteArrayOutputStreams are not cloneable, so copy it. + obj.buffer = new ByteArrayOutputStream(); + if (buffer.size() > 0) { + try { + obj.buffer.write(buffer.toByteArray()); + } catch (IOException e) { + // Should never happen. + throw new AssertionError(e); + } + } + return obj; + } + public static class SHA1 extends IosSHAMessageDigest { public SHA1() { diff --git a/jre_emul/Tests/com/google/j2objc/security/IosSHAMessageDigestTest.java b/jre_emul/Tests/com/google/j2objc/security/IosSHAMessageDigestTest.java new file mode 100644 index 0000000000..3d9fa0840a --- /dev/null +++ b/jre_emul/Tests/com/google/j2objc/security/IosSHAMessageDigestTest.java @@ -0,0 +1,48 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.j2objc.security; + +import java.security.MessageDigest; +import junit.framework.TestCase; + + +/** + * Unit tests for {@link IosSHAMessageDigest}. + * + * @author Tom Ball + */ +public class IosSHAMessageDigestTest extends TestCase { + + // Issue #797: cloned digests returned different hash values. + public void testDigestCloning() throws Exception { + MessageDigest digest = MessageDigest.getInstance("SHA-1"); + String hash1 = hash("foo", (MessageDigest) digest.clone()); + String hash2 = hash("foo", (MessageDigest) digest.clone()); + assertEquals(hash1, hash2); + } + + private String hash(String input, MessageDigest digest) throws Exception { + byte[] bytes = input.getBytes("UTF-8"); + digest.update(bytes); + byte[] hash = digest.digest(); + StringBuilder sb = new StringBuilder(2 * bytes.length); + for (byte b : hash) { + sb.append(hexDigits[(b >> 4) & 0xf]).append(hexDigits[b & 0xf]); + } + return sb.toString(); + } + + private static final char[] hexDigits = "0123456789abcdef".toCharArray(); +} diff --git a/jre_emul/test_sources.mk b/jre_emul/test_sources.mk index 62d91559a8..a70e27b94a 100644 --- a/jre_emul/test_sources.mk +++ b/jre_emul/test_sources.mk @@ -213,6 +213,7 @@ TEST_SOURCES := \ com/google/j2objc/ThrowableTest.java \ com/google/j2objc/net/NSErrorExceptionTest.java \ com/google/j2objc/security/IosSecureRandomImplTest.java \ + com/google/j2objc/security/IosSHAMessageDigestTest.java \ com/google/j2objc/util/NativeTimeZoneTest.java \ dalvik/system/JniTest.java \ java/lang/SystemTest.java \