~brian-thomason/+junk/bouncycastle

« back to all changes in this revision

Viewing changes to src/org/bouncycastle/crypto/agreement/srp/SRP6Util.java

  • Committer: Brian Thomason
  • Date: 2011-12-20 17:20:32 UTC
  • Revision ID: brian.thomason@canonical.com-20111220172032-rdtm13jgdxtksacr
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package org.bouncycastle.crypto.agreement.srp;
 
2
 
 
3
import java.math.BigInteger;
 
4
import java.security.SecureRandom;
 
5
 
 
6
import org.bouncycastle.crypto.CryptoException;
 
7
import org.bouncycastle.crypto.Digest;
 
8
import org.bouncycastle.util.BigIntegers;
 
9
 
 
10
public class SRP6Util
 
11
{
 
12
    private static BigInteger ZERO = BigInteger.valueOf(0);
 
13
    private static BigInteger ONE = BigInteger.valueOf(1);
 
14
 
 
15
    public static BigInteger calculateK(Digest digest, BigInteger N, BigInteger g)
 
16
    {
 
17
        return hashPaddedPair(digest, N, N, g);
 
18
    }
 
19
 
 
20
    public static BigInteger calculateU(Digest digest, BigInteger N, BigInteger A, BigInteger B)
 
21
    {
 
22
        return hashPaddedPair(digest, N, A, B);
 
23
    }
 
24
 
 
25
    public static BigInteger calculateX(Digest digest, BigInteger N, byte[] salt, byte[] identity, byte[] password)
 
26
    {
 
27
        byte[] output = new byte[digest.getDigestSize()];
 
28
 
 
29
        digest.update(identity, 0, identity.length);
 
30
        digest.update((byte)':');
 
31
        digest.update(password, 0, password.length);
 
32
        digest.doFinal(output, 0);
 
33
 
 
34
        digest.update(salt, 0, salt.length);
 
35
        digest.update(output, 0, output.length);
 
36
        digest.doFinal(output, 0);
 
37
 
 
38
        return new BigInteger(1, output).mod(N);
 
39
    }
 
40
 
 
41
    public static BigInteger generatePrivateValue(Digest digest, BigInteger N, BigInteger g, SecureRandom random)
 
42
    {
 
43
        int minBits = Math.min(256, N.bitLength() / 2);
 
44
        BigInteger min = ONE.shiftLeft(minBits - 1);
 
45
        BigInteger max = N.subtract(ONE);
 
46
 
 
47
        return BigIntegers.createRandomInRange(min, max, random);
 
48
    }
 
49
 
 
50
    public static BigInteger validatePublicValue(BigInteger N, BigInteger val)
 
51
        throws CryptoException
 
52
    {
 
53
        val = val.mod(N);
 
54
 
 
55
        // Check that val % N != 0
 
56
        if (val.equals(ZERO))
 
57
        {
 
58
            throw new CryptoException("Invalid public value: 0");
 
59
        }
 
60
 
 
61
        return val;
 
62
    }
 
63
 
 
64
    private static BigInteger hashPaddedPair(Digest digest, BigInteger N, BigInteger n1, BigInteger n2)
 
65
    {
 
66
        int padLength = (N.bitLength() + 7) / 8;
 
67
 
 
68
        byte[] n1_bytes = getPadded(n1, padLength);
 
69
        byte[] n2_bytes = getPadded(n2, padLength);
 
70
 
 
71
        digest.update(n1_bytes, 0, n1_bytes.length);
 
72
        digest.update(n2_bytes, 0, n2_bytes.length);
 
73
 
 
74
        byte[] output = new byte[digest.getDigestSize()];
 
75
        digest.doFinal(output, 0);
 
76
 
 
77
        return new BigInteger(1, output).mod(N);
 
78
    }
 
79
 
 
80
    private static byte[] getPadded(BigInteger n, int length)
 
81
    {
 
82
        byte[] bs = BigIntegers.asUnsignedByteArray(n);
 
83
        if (bs.length < length)
 
84
        {
 
85
            byte[] tmp = new byte[length];
 
86
            System.arraycopy(bs, 0, tmp, length - bs.length, bs.length);
 
87
            bs = tmp;
 
88
        }
 
89
        return bs;
 
90
    }
 
91
}