From da6b027a42d980cd918e299b2b0a1e9f7f0c9caa Mon Sep 17 00:00:00 2001 From: Tarun Gupta Date: Tue, 2 Jun 2015 21:27:26 +0530 Subject: Add support for Crypto-functions. Completes the JavaCryptoProvider providing functionalities for SHA-1 Hash, MD5 Hash and HMACSHA1 Hash. Also updates reference for JavaCryptoProvider in JavaNetworkFactories. License: This patch is BSD-licensed, see Documentation/Licenses/BSD-simplified.txt for details. Test-Information: Tests are added for JavaCryptoProvider, which passes. Change-Id: I2439e5fd76a23e9b5c4e9132a9856543a7ca53fd diff --git a/src/com/isode/stroke/base/SafeByteArray.java b/src/com/isode/stroke/base/SafeByteArray.java index 9f91afb..e35ef35 100644 --- a/src/com/isode/stroke/base/SafeByteArray.java +++ b/src/com/isode/stroke/base/SafeByteArray.java @@ -4,6 +4,12 @@ */ package com.isode.stroke.base; -public class SafeByteArray { +import com.isode.stroke.base.ByteArray; -} +/** +* It's currently not actually secure, +* and that we might consider if http://developer.android.com/reference/java/nio/ByteBuffer.html#allocateDirect(int) could help us in the future. +*/ +public class SafeByteArray extends ByteArray { + +} \ No newline at end of file diff --git a/src/com/isode/stroke/crypto/JavaCryptoProvider.java b/src/com/isode/stroke/crypto/JavaCryptoProvider.java new file mode 100644 index 0000000..1353225 --- /dev/null +++ b/src/com/isode/stroke/crypto/JavaCryptoProvider.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2011-2015 Isode Limited, London, England. + * All rights reserved. + */ +/* + * Copyright (c) 2015 Tarun Gupta. + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +package com.isode.stroke.crypto; + +import com.isode.stroke.crypto.CryptoProvider; +import com.isode.stroke.crypto.Hash; +import com.isode.stroke.base.ByteArray; +import com.isode.stroke.base.SafeByteArray; +import com.isode.stroke.base.NotNull; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.SignatureException; +import java.security.InvalidKeyException; +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.lang.IllegalStateException; + +public class JavaCryptoProvider extends CryptoProvider { + + private static class HashProvider implements Hash { + + private final MessageDigest digest; + + /** + * Constructor, MessageDigest object that implements MD5 / SHA1. + */ + public HashProvider(String algorithm) { + try { + digest = MessageDigest.getInstance(algorithm); + } + catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e.getMessage()); + } + } + + /** + * Updates the digest using the ByteArray. + * @param data, NotNull. + * @return Hash updated with data. + */ + @Override + public Hash update(ByteArray data) { + NotNull.exceptIfNull(data, "data"); + digest.update(data.getData()); + return this; + } + + /** + * Updates the digest using the SafeByteArray. + * @param data, NotNull. + * @return Hash updated with data. + */ + @Override + public Hash update(SafeByteArray data) { + NotNull.exceptIfNull(data, "data"); + digest.update(data.getData()); + return this; + } + + /** + * Completes the MD5/SHA1 hash computation. + * @return ByteArray containing the MD5/SHA1 Hash. + */ + @Override + public ByteArray getHash() { + return new ByteArray(digest.digest()); + } + + } + + /** + * Computes the HMACSHA1 hash computation. + * @param key NotNull. Key is used for initializing MAC object. + * @param data NotNull. + * @return ByteArray containing the HMACSHA1 Hash. + */ + public ByteArray getHMACSHA1Internal(final ByteArray key, final ByteArray data) { + NotNull.exceptIfNull(key, "key"); + NotNull.exceptIfNull(data, "data"); + try { + SecretKeySpec signingKey = new SecretKeySpec(key.getData(), "HmacSHA1"); + Mac mac = Mac.getInstance("HmacSHA1"); + mac.init(signingKey); + mac.update(data.getData()); + byte[] Hmac = mac.doFinal(); + return (new ByteArray(Hmac)); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e.getMessage()); + } catch (InvalidKeyException e) { + throw new RuntimeException(e.getMessage()); + } + } + + /** + * Creates the SHA1Hash object for performing hash computations. + * @return SHA1Hash object. + */ + @Override + public Hash createSHA1() { + return new HashProvider("SHA-1"); + } + + /** + * Creates the SHA1Hash object for performing hash computations. + * @return MD5Hash object. + */ + @Override + public Hash createMD5() { + return new HashProvider("MD5"); + } + + /** + * @param key, NotNull. + * @param data, NotNull. + * @return ByteArray containing the HMACSHA1 Hash. + */ + @Override + public ByteArray getHMACSHA1(final SafeByteArray key, final ByteArray data) { + return getHMACSHA1Internal(key, data); + } + + /** + * @param key, NotNull. + * @param data, NotNull. + * @return ByteArray containing the HMACSHA1 Hash. + */ + @Override + public ByteArray getHMACSHA1(final ByteArray key, final ByteArray data) { + return getHMACSHA1Internal(key, data); + } + + @Override + public boolean isMD5AllowedForCrypto() { + return false; + } +} \ No newline at end of file diff --git a/src/com/isode/stroke/network/JavaCryptoProvider.java b/src/com/isode/stroke/network/JavaCryptoProvider.java deleted file mode 100644 index b7dff5d..0000000 --- a/src/com/isode/stroke/network/JavaCryptoProvider.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2011-2015 Isode Limited, London, England. - * All rights reserved. - */ -package com.isode.stroke.network; - -import java.security.InvalidKeyException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; - -import com.isode.stroke.base.ByteArray; -import com.isode.stroke.crypto.CryptoProvider; -import com.isode.stroke.crypto.Hash; -import com.isode.stroke.base.SafeByteArray; - -public class JavaCryptoProvider extends CryptoProvider { - - private static class HashProvider implements Hash { - private final MessageDigest digest; - - HashProvider(String algorithm) throws NoSuchAlgorithmException { - digest = MessageDigest.getInstance("SHA-1"); - } - - @Override - public Hash update(ByteArray data) { - digest.update(data.getData()); - return this; - } - - @Override - public Hash update(SafeByteArray data) { -// digest.update(data.getData()); - return this; - } - - @Override - public ByteArray getHash() { - return new ByteArray(digest.digest()); - } - - } - - @Override - public Hash createSHA1() { - try { - return new HashProvider("SHA-1"); - } catch (NoSuchAlgorithmException e) { - return null; - } - } - - @Override - public Hash createMD5() { - try { - return new HashProvider("MD5"); - } catch (NoSuchAlgorithmException e) { - return null; - } - } - -// @Override - public ByteArray getHMACSHA1(SafeByteArray key, ByteArray data) { - // TODO Auto-generated method stub - return null; - } - - @Override - public ByteArray getHMACSHA1(ByteArray key, ByteArray data) { - Mac mac; - try { - mac = Mac.getInstance("HmacSHA1"); - mac.init(new SecretKeySpec(key.getData(), mac.getAlgorithm())); - return new ByteArray(mac.doFinal(data.getData())); - } catch (NoSuchAlgorithmException e) { - return null; - } catch (InvalidKeyException e) { - return null; - } - } - - @Override - public boolean isMD5AllowedForCrypto() { - return false; - } - -} diff --git a/src/com/isode/stroke/network/JavaNetworkFactories.java b/src/com/isode/stroke/network/JavaNetworkFactories.java index 2276a2a..15860e0 100644 --- a/src/com/isode/stroke/network/JavaNetworkFactories.java +++ b/src/com/isode/stroke/network/JavaNetworkFactories.java @@ -5,6 +5,7 @@ package com.isode.stroke.network; import com.isode.stroke.crypto.CryptoProvider; +import com.isode.stroke.crypto.JavaCryptoProvider; import com.isode.stroke.eventloop.EventLoop; import com.isode.stroke.tls.PlatformTLSFactories; import com.isode.stroke.tls.TLSContextFactory; diff --git a/test/com/isode/stroke/crypto/JavaCryptoProviderTest.java b/test/com/isode/stroke/crypto/JavaCryptoProviderTest.java new file mode 100644 index 0000000..9e704d1 --- /dev/null +++ b/test/com/isode/stroke/crypto/JavaCryptoProviderTest.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2010-2013 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ +/* + * Copyright (c) 2015 Tarun Gupta. + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +package com.isode.stroke.crypto; + +import com.isode.stroke.base.ByteArray; +import com.isode.stroke.base.SafeByteArray; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import org.junit.Before; +import org.junit.Test; +import com.isode.stroke.stringcodecs.Hexify; + +public class JavaCryptoProviderTest { + + private CryptoProvider provider; + + @Before + public void setUp() { + provider = new JavaCryptoProvider(); + } + + //////////////////////////////////////////////////////////// + // SHA-1 + //////////////////////////////////////////////////////////// + + @Test + public void testGetSHA1Hash() { + Hash shaHash = provider.createSHA1(); + shaHash = shaHash.update(new ByteArray("client/pc//Exodus 0.9.1