Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/quite/humla-spongycastle.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2014-06-21 08:17:01 +0400
committerPeter Dettman <peter.dettman@bouncycastle.org>2014-06-21 08:17:01 +0400
commit861abad2b0c99498b6170fe64fb1a731fa73cd8d (patch)
tree413c9fffa03c12bb7413cb6b62d2fe818e318610 /core/src/main/java/org/bouncycastle/crypto
parent98dddf1380e0118cbb5969773d9fe884fda9af79 (diff)
parentb30d7be83296317b9479049899218f69b5a5341a (diff)
Merge branch 'master' of https://github.com/dangrasso/bc-java
Diffstat (limited to 'core/src/main/java/org/bouncycastle/crypto')
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6Client.java59
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6Server.java60
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6Util.java63
3 files changed, 180 insertions, 2 deletions
diff --git a/core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6Client.java b/core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6Client.java
index 4df90236..a34baf35 100644
--- a/core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6Client.java
+++ b/core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6Client.java
@@ -25,6 +25,10 @@ public class SRP6Client
protected BigInteger u;
protected BigInteger S;
+ protected BigInteger M1;
+ protected BigInteger M2;
+ protected BigInteger Key;
+
protected Digest digest;
protected SecureRandom random;
@@ -64,7 +68,7 @@ public class SRP6Client
}
/**
- * Generates client's verification message given the server's credentials
+ * Generates the secret S given the server's credentials
* @param serverB The server's credentials
* @return Client's verification message for the server
* @throws CryptoException If server's credentials are invalid
@@ -90,4 +94,57 @@ public class SRP6Client
BigInteger tmp = g.modPow(x, N).multiply(k).mod(N);
return B.subtract(tmp).mod(N).modPow(exp, N);
}
+
+ /**
+ * Computes the client evidence message M1 using the previously received values.
+ * To be called after calculating the secret S.
+ * @return M1: the client side generated evidence message
+ * @throws CryptoException
+ */
+ public BigInteger calculateClientEvidenceMessage() throws CryptoException{
+ // verify pre-requirements
+ if ((this.A==null)||(this.B==null)||(this.S==null)){
+ throw new CryptoException("Impossible to compute M1: " +
+ "some data are missing from the previous operations (A,B,S)");
+ }
+ // compute the client evidence message 'M1'
+ this.M1 = SRP6UtilCustom.calculateM1(digest, N, A, B, S);
+ return M1;
+ }
+
+ /** Authenticates the server evidence message M2 received and saves it only if correct.
+ * @param M2: the server side generated evidence message
+ * @return A boolean indicating if the server message M2 was the expected one.
+ * @throws CryptoException
+ */
+ public boolean verifyServerEvidenceMessage(BigInteger serverM2) throws CryptoException{
+ //verify pre-requirements
+ if ((this.A==null)||(this.M1==null)||(this.S==null)){
+ throw new CryptoException("Impossible to compute and verify M2: " +
+ "some data are missing from the previous operations (A,M1,S)");
+ }
+ // Compute the own server evidence message 'M2'
+ BigInteger computedM2 = SRP6UtilCustom.calculateM2(digest, N, A, M1, S);
+ if (computedM2.equals(serverM2)){
+ this.M2 = serverM2;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Computes the final session key as a result of the SRP successful mutual authentication
+ * To be called after verifying the server evidence message M2.
+ * @return Key: the mutually authenticated symmetric session key
+ * @throws CryptoException
+ */
+ public BigInteger calculateSessionKey() throws CryptoException{
+ //verify pre-requirements (here we enforce a previous calculation of M1 and M2)
+ if ((this.S==null)||(this.M1==null)||(this.M2==null)){
+ throw new CryptoException("Impossible to compute Key: " +
+ "some data are missing from the previous operations (S,M1,M2)");
+ }
+ this.Key = SRP6UtilCustom.calculateKey(digest, N, S);
+ return Key;
+ }
}
diff --git a/core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6Server.java b/core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6Server.java
index fb208388..e8f1711f 100644
--- a/core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6Server.java
+++ b/core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6Server.java
@@ -27,7 +27,10 @@ public class SRP6Server
protected BigInteger u;
protected BigInteger S;
-
+ protected BigInteger M1;
+ protected BigInteger M2;
+ protected BigInteger Key;
+
public SRP6Server()
{
}
@@ -87,4 +90,59 @@ public class SRP6Server
{
return v.modPow(u, N).multiply(A).mod(N).modPow(b, N);
}
+
+ /**
+ * Authenticates the received client evidence message M1 and saves it only if correct.
+ * To be called after calculating the secret S.
+ * @param M1: the client side generated evidence message
+ * @return A boolean indicating if the client message M1 was the expected one.
+ * @throws CryptoException
+ */
+ public boolean verifyClientEvidenceMessage(BigInteger clientM1) throws CryptoException{
+ //verify pre-requirements
+ if ((this.A==null)||(this.B==null)||(this.S==null)){
+ throw new CryptoException("Impossible to compute and verify M1: " +
+ "some data are missing from the previous operations (A,B,S)");
+ }
+ // Compute the own client evidence message 'M1'
+ BigInteger computedM1 = SRP6UtilCustom.calculateM1(digest, N, A, B, S);
+ if (computedM1.equals(clientM1)){
+ this.M1 = clientM1;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Computes the server evidence message M2 using the previously verified values.
+ * To be called after successfully verifying the client evidence message M1.
+ * @return M2: the server side generated evidence message
+ * @throws CryptoException
+ */
+ public BigInteger calculateServerEvidenceMessage() throws CryptoException{
+ //verify pre-requirements
+ if ((this.A==null)||(this.M1==null)||(this.S==null)){
+ throw new CryptoException("Impossible to compute M2: " +
+ "some data are missing from the previous operations (A,M1,S)");
+ }
+ // Compute the server evidence message 'M2'
+ this.M2 = SRP6UtilCustom.calculateM2(digest, N, A, M1, S);
+ return M2;
+ }
+
+ /**
+ * Computes the final session key as a result of the SRP successful mutual authentication
+ * To be called after calculating the server evidence message M2.
+ * @return Key: the mutual authenticated symmetric session key
+ * @throws CryptoException
+ */
+ public BigInteger calculateSessionKey() throws CryptoException{
+ //verify pre-requirements
+ if ((this.S==null)||(this.M1==null)||(this.M2==null)){
+ throw new CryptoException("Impossible to compute Key: " +
+ "some data are missing from the previous operations (S,M1,M2)");
+ }
+ this.Key = SRP6UtilCustom.calculateKey(digest, N, S);
+ return Key;
+ }
}
diff --git a/core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6Util.java b/core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6Util.java
index ad5ceac8..6bcf0183 100644
--- a/core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6Util.java
+++ b/core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6Util.java
@@ -60,6 +60,69 @@ public class SRP6Util
return val;
}
+ /**
+ * Computes the client evidence message (M1) according to the standard routine:
+ * M1 = H( A | B | S )
+ * @param digest The Digest used as the hashing function H
+ * @param N Modulus used to get the pad length
+ * @param A The public client value
+ * @param B The public server value
+ * @param S The secret calculated by both sides
+ * @return M1 The calculated client evidence message
+ */
+ public static BigInteger calculateM1(Digest digest, BigInteger N, BigInteger A, BigInteger B, BigInteger S) {
+ BigInteger M1 = hashPaddedTriplet(digest,N,A,B,S);
+ return M1;
+ }
+
+ /**
+ * Computes the server evidence message (M2) according to the standard routine:
+ * M2 = H( A | M1 | S )
+ * @param digest The Digest used as the hashing function H
+ * @param N Modulus used to get the pad length
+ * @param A The public client value
+ * @param M1 The client evidence message
+ * @param S The secret calculated by both sides
+ * @return M2 The calculated server evidence message
+ */
+ public static BigInteger calculateM2(Digest digest, BigInteger N, BigInteger A, BigInteger M1, BigInteger S){
+ BigInteger M2 = hashPaddedTriplet(digest,N,A,M1,S);
+ return M2;
+ }
+
+ /**
+ * Computes the final Key according to the standard routine: Key = H(S)
+ * @param digest The Digest used as the hashing function H
+ * @param N Modulus used to get the pad length
+ * @param S The secret calculated by both sides
+ * @return
+ */
+ public static BigInteger calculateKey(Digest digest, BigInteger N, BigInteger S) {
+ int padLength = (N.bitLength() + 7) / 8;
+ byte[] _S = getPadded(S,padLength);
+ digest.update(_S, 0, _S.length);
+
+ byte[] output = new byte[digest.getDigestSize()];
+ digest.doFinal(output, 0);
+ return new BigInteger(1, output);
+ }
+
+ private static BigInteger hashPaddedTriplet(Digest digest, BigInteger N, BigInteger n1, BigInteger n2, BigInteger n3){
+ int padLength = (N.bitLength() + 7) / 8;
+
+ byte[] n1_bytes = getPadded(n1, padLength);
+ byte[] n2_bytes = getPadded(n2, padLength);
+ byte[] n3_bytes = getPadded(n3, padLength);
+
+ digest.update(n1_bytes, 0, n1_bytes.length);
+ digest.update(n2_bytes, 0, n2_bytes.length);
+ digest.update(n3_bytes, 0, n3_bytes.length);
+
+ byte[] output = new byte[digest.getDigestSize()];
+ digest.doFinal(output, 0);
+
+ return new BigInteger(1, output);
+ }
private static BigInteger hashPaddedPair(Digest digest, BigInteger N, BigInteger n1, BigInteger n2)
{