1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage org.bouncycastle.crypto.generators; 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.math.BigInteger; 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.SecureRandom; 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.digests.SHA1Digest; 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.params.DSAParameters; 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.params.DSAValidationParameters; 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * generate suitable parameters for DSA, in line with FIPS 186-2. 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class DSAParametersGenerator 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private int size; 16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private int certainty; 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private SecureRandom random; 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static BigInteger ONE = BigInteger.valueOf(1); 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static BigInteger TWO = BigInteger.valueOf(2); 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * initialise the key generator. 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param size size of the key (range 2^512 -> 2^1024 - 64 bit increments) 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param certainty measure of robustness of prime (for FIPS 186-2 compliance this should be at least 80). 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param random random byte source. 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void init( 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int size, 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int certainty, 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project SecureRandom random) 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.size = size; 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.certainty = certainty; 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.random = random; 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * add value to b, returning the result in a. The a value is treated 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * as a BigInteger of length (a.length * 8) bits. The result is 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * modulo 2^a.length in case of overflow. 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void add( 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] a, 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] b, 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int value) 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int x = (b[b.length - 1] & 0xff) + value; 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project a[b.length - 1] = (byte)x; 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project x >>>= 8; 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = b.length - 2; i >= 0; i--) 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project x += (b[i] & 0xff); 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project a[i] = (byte)x; 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project x >>>= 8; 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * which generates the p and g values from the given parameters, 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * returning the DSAParameters object. 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <p> 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note: can take a while... 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public DSAParameters generateParameters() 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] seed = new byte[20]; 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] part1 = new byte[20]; 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] part2 = new byte[20]; 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] u = new byte[20]; 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project SHA1Digest sha1 = new SHA1Digest(); 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int n = (size - 1) / 160; 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] w = new byte[size / 8]; 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project BigInteger q = null, p = null, g = null; 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int counter = 0; 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project boolean primesFound = false; 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (!primesFound) 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project do 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project random.nextBytes(seed); 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sha1.update(seed, 0, seed.length); 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sha1.doFinal(part1, 0); 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.arraycopy(seed, 0, part2, 0, seed.length); 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project add(part2, seed, 1); 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sha1.update(part2, 0, part2.length); 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sha1.doFinal(part2, 0); 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i != u.length; i++) 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u[i] = (byte)(part1[i] ^ part2[i]); 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u[0] |= (byte)0x80; 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u[19] |= (byte)0x01; 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project q = new BigInteger(1, u); 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (!q.isProbablePrime(certainty)); 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project counter = 0; 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int offset = 2; 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (counter < 4096) 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int k = 0; k < n; k++) 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project add(part1, seed, offset + k); 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sha1.update(part1, 0, part1.length); 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sha1.doFinal(part1, 0); 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.arraycopy(part1, 0, w, w.length - (k + 1) * part1.length, part1.length); 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project add(part1, seed, offset + n); 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sha1.update(part1, 0, part1.length); 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sha1.doFinal(part1, 0); 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.arraycopy(part1, part1.length - ((w.length - (n) * part1.length)), w, 0, w.length - n * part1.length); 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project w[0] |= (byte)0x80; 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project BigInteger x = new BigInteger(1, w); 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project BigInteger c = x.mod(q.multiply(TWO)); 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project p = x.subtract(c.subtract(ONE)); 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (p.testBit(size - 1)) 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (p.isProbablePrime(certainty)) 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project primesFound = true; 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project counter += 1; 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project offset += n + 1; 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // calculate the generator g 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project BigInteger pMinusOneOverQ = p.subtract(ONE).divide(q); 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (;;) 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project BigInteger h = new BigInteger(size, random); 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (h.compareTo(ONE) <= 0 || h.compareTo(p.subtract(ONE)) >= 0) 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project continue; 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project g = h.modPow(pMinusOneOverQ, p); 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (g.compareTo(ONE) <= 0) 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project continue; 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return new DSAParameters(p, q, g, new DSAValidationParameters(seed, counter)); 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 179