1
package org.bouncycastle.crypto.agreement.srp;
3
import java.math.BigInteger;
4
import java.security.SecureRandom;
6
import org.bouncycastle.crypto.CryptoException;
7
import org.bouncycastle.crypto.Digest;
8
import org.bouncycastle.util.BigIntegers;
12
private static BigInteger ZERO = BigInteger.valueOf(0);
13
private static BigInteger ONE = BigInteger.valueOf(1);
15
public static BigInteger calculateK(Digest digest, BigInteger N, BigInteger g)
17
return hashPaddedPair(digest, N, N, g);
20
public static BigInteger calculateU(Digest digest, BigInteger N, BigInteger A, BigInteger B)
22
return hashPaddedPair(digest, N, A, B);
25
public static BigInteger calculateX(Digest digest, BigInteger N, byte[] salt, byte[] identity, byte[] password)
27
byte[] output = new byte[digest.getDigestSize()];
29
digest.update(identity, 0, identity.length);
30
digest.update((byte)':');
31
digest.update(password, 0, password.length);
32
digest.doFinal(output, 0);
34
digest.update(salt, 0, salt.length);
35
digest.update(output, 0, output.length);
36
digest.doFinal(output, 0);
38
return new BigInteger(1, output).mod(N);
41
public static BigInteger generatePrivateValue(Digest digest, BigInteger N, BigInteger g, SecureRandom random)
43
int minBits = Math.min(256, N.bitLength() / 2);
44
BigInteger min = ONE.shiftLeft(minBits - 1);
45
BigInteger max = N.subtract(ONE);
47
return BigIntegers.createRandomInRange(min, max, random);
50
public static BigInteger validatePublicValue(BigInteger N, BigInteger val)
51
throws CryptoException
55
// Check that val % N != 0
58
throw new CryptoException("Invalid public value: 0");
64
private static BigInteger hashPaddedPair(Digest digest, BigInteger N, BigInteger n1, BigInteger n2)
66
int padLength = (N.bitLength() + 7) / 8;
68
byte[] n1_bytes = getPadded(n1, padLength);
69
byte[] n2_bytes = getPadded(n2, padLength);
71
digest.update(n1_bytes, 0, n1_bytes.length);
72
digest.update(n2_bytes, 0, n2_bytes.length);
74
byte[] output = new byte[digest.getDigestSize()];
75
digest.doFinal(output, 0);
77
return new BigInteger(1, output).mod(N);
80
private static byte[] getPadded(BigInteger n, int length)
82
byte[] bs = BigIntegers.asUnsignedByteArray(n);
83
if (bs.length < length)
85
byte[] tmp = new byte[length];
86
System.arraycopy(bs, 0, tmp, length - bs.length, bs.length);