summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTarun Gupta <tarun1995gupta@gmail.com>2015-06-02 15:57:26 (GMT)
committerTarun Gupta <tarun1995gupta@gmail.com>2015-06-14 13:25:54 (GMT)
commitda6b027a42d980cd918e299b2b0a1e9f7f0c9caa (patch)
tree5c222d48ade235766c72be909e46ca5366784e16
parentd90c2cadb3d1bb2b849a448d3482b504bc4706bb (diff)
downloadstroke-da6b027a42d980cd918e299b2b0a1e9f7f0c9caa.zip
stroke-da6b027a42d980cd918e299b2b0a1e9f7f0c9caa.tar.bz2
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
-rw-r--r--src/com/isode/stroke/base/SafeByteArray.java10
-rw-r--r--src/com/isode/stroke/crypto/JavaCryptoProvider.java144
-rw-r--r--src/com/isode/stroke/network/JavaCryptoProvider.java90
-rw-r--r--src/com/isode/stroke/network/JavaNetworkFactories.java1
-rw-r--r--test/com/isode/stroke/crypto/JavaCryptoProviderTest.java117
5 files changed, 270 insertions, 92 deletions
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<http://jabber.org/protocol/caps<http://jabber.org/protocol/disco#info<http://jabber.org/protocol/disco#items<http://jabber.org/protocol/muc<"));
+ assertEquals("4206b23ca6b0a643d20d89b04ff58cf78b8096ed", Hexify.hexify(shaHash.getHash()));
+ }
+
+ @Test
+ public void testGetSHA1Hash_TwoUpdates() {
+ Hash shaHash = provider.createSHA1();
+ shaHash.update(new ByteArray("client/pc//Exodus 0.9.1<http://jabber.org/protocol/caps<"));
+ shaHash.update(new ByteArray("http://jabber.org/protocol/disco#info<http://jabber.org/protocol/disco#items<http://jabber.org/protocol/muc<"));
+ assertEquals("4206b23ca6b0a643d20d89b04ff58cf78b8096ed", Hexify.hexify(shaHash.getHash()));
+ }
+
+ @Test
+ public void testGetSHA1Hash_NoData() {
+ Hash shaHash = provider.createSHA1();
+ shaHash.update(new ByteArray());
+ assertEquals("da39a3ee5e6b4b0d3255bfef95601890afd80709", Hexify.hexify(shaHash.getHash()));
+ }
+
+ @Test
+ public void testGetSHA1HashStatic() {
+ ByteArray returned = provider.getSHA1Hash(new ByteArray("client/pc//Exodus 0.9.1<http://jabber.org/protocol/caps<http://jabber.org/protocol/disco#info<http://jabber.org/protocol/disco#items<http://jabber.org/protocol/muc<"));
+ assertEquals("4206b23ca6b0a643d20d89b04ff58cf78b8096ed", Hexify.hexify(returned));
+ }
+
+ @Test
+ public void testGetSHA1HashStatic_Twice() {
+ ByteArray byteArray = new ByteArray("client/pc//Exodus 0.9.1<http://jabber.org/protocol/caps<http://jabber.org/protocol/disco#info<http://jabber.org/protocol/disco#items<http://jabber.org/protocol/muc<");
+ ByteArray returned = provider.getSHA1Hash(byteArray);
+ assertEquals("4206b23ca6b0a643d20d89b04ff58cf78b8096ed", Hexify.hexify(returned));
+ }
+
+ @Test
+ public void testGetSHA1HashStatic_NoData() {
+ ByteArray returned = provider.getSHA1Hash(new ByteArray());
+ assertEquals("da39a3ee5e6b4b0d3255bfef95601890afd80709", Hexify.hexify(returned));
+ }
+
+ ////////////////////////////////////////////////////////////
+ // MD5
+ ////////////////////////////////////////////////////////////
+
+ @Test
+ public void testGetMD5Hash_Empty() {
+ Hash md5Hash = provider.createMD5();
+ md5Hash = md5Hash.update(new ByteArray(""));
+ assertEquals("d41d8cd98f00b204e9800998ecf8427e", Hexify.hexify(md5Hash.getHash()));
+ }
+
+ @Test
+ public void testGetMD5Hash_Alphabet() {
+ Hash md5Hash = provider.createMD5();
+ md5Hash = md5Hash.update(new ByteArray("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"));
+ assertEquals("d174ab98d277d9f5a5611c2c9f419d9f", Hexify.hexify(md5Hash.getHash()));
+ }
+
+ @Test
+ public void testMD5Incremental() {
+ Hash md5Hash = provider.createMD5();
+ md5Hash = md5Hash.update(new ByteArray("ABCDEFGHIJKLMNOPQRSTUVWXYZ"));
+ md5Hash = md5Hash.update(new ByteArray("abcdefghijklmnopqrstuvwxyz0123456789"));
+ assertEquals("d174ab98d277d9f5a5611c2c9f419d9f", Hexify.hexify(md5Hash.getHash()));
+ }
+
+ ////////////////////////////////////////////////////////////
+ // HMAC-SHA1
+ ////////////////////////////////////////////////////////////
+
+ @Test
+ public void testGetHMACSHA1() {
+ ByteArray returned = provider.getHMACSHA1(new ByteArray("foo"), new ByteArray("foobar"));
+ assertEquals("a4eeba8e633d778869f568d05a1b3dc72bfd04dd", Hexify.hexify(returned));
+ }
+
+ @Test
+ public void testGetHMACSHA1_KeyLongerThanBlockSize() {
+ ByteArray returned = provider.getHMACSHA1(new ByteArray("---------|---------|---------|---------|---------|----------|---------|"), new ByteArray("foobar"));
+ assertEquals("d66e8f507c31d32c0620b9e367678ecf205d2b0a", Hexify.hexify(returned));
+ }
+}