📄 rfc2631.java
字号:
/* RFC2631.java -- Copyright (C) 2003, 2006 Free Software Foundation, Inc.This file is a part of GNU Classpath.GNU Classpath is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or (atyour option) any later version.GNU Classpath is distributed in the hope that it will be useful, butWITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNUGeneral Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU Classpath; if not, write to the Free SoftwareFoundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301USALinking this library statically or dynamically with other modules ismaking a combined work based on this library. Thus, the terms andconditions of the GNU General Public License cover the wholecombination.As a special exception, the copyright holders of this library give youpermission to link this library with independent modules to produce anexecutable, regardless of the license terms of these independentmodules, and to copy and distribute the resulting executable underterms of your choice, provided that you also meet, for each linkedindependent module, the terms and conditions of the license of thatmodule. An independent module is a module which is not derived fromor based on this library. If you modify this library, you may extendthis exception to your version of the library, but you are notobligated to do so. If you do not wish to do so, delete thisexception statement from your version. */package gnu.javax.crypto.key.dh;import gnu.java.security.hash.Sha160;import gnu.java.security.util.PRNG;import gnu.java.security.util.Prime2;import java.math.BigInteger;import java.security.SecureRandom;/** * <p>An implementation of the Diffie-Hellman parameter generation as defined in * RFC-2631.</p> * * <p>Reference:</p> * <ol> * <li><a href="http://www.ietf.org/rfc/rfc2631.txt">Diffie-Hellman Key * Agreement Method</a><br> * Eric Rescorla.</li> * </ol> */public class RFC2631{ // Constants and variables // ------------------------------------------------------------------------- public static final int DH_PARAMS_SEED = 0; public static final int DH_PARAMS_COUNTER = 1; public static final int DH_PARAMS_Q = 2; public static final int DH_PARAMS_P = 3; public static final int DH_PARAMS_J = 4; public static final int DH_PARAMS_G = 5; private static final BigInteger TWO = BigInteger.valueOf(2L); /** The SHA instance to use. */ private Sha160 sha = new Sha160(); /** Length of private modulus and of q. */ private int m; /** Length of public modulus p. */ private int L; /** The optional {@link SecureRandom} instance to use. */ private SecureRandom rnd = null; /** Our default source of randomness. */ private PRNG prng = null; // Constructor(s) // ------------------------------------------------------------------------- public RFC2631(int m, int L, SecureRandom rnd) { super(); this.m = m; this.L = L; this.rnd = rnd; } // Class methods // ------------------------------------------------------------------------- // Instance methods // ------------------------------------------------------------------------- public BigInteger[] generateParameters() { int i, j, counter; byte[] u1, u2, v; byte[] seedBytes = new byte[m / 8]; BigInteger SEED, U, q, R, V, W, X, p, g; // start by genrating p and q, where q is of length m and p is of length L // 1. Set m' = m/160 where / represents integer division with rounding // upwards. I.e. 200/160 = 2. int m_ = (m + 159) / 160; // 2. Set L'= L/160 int L_ = (L + 159) / 160; // 3. Set N'= L/1024 int N_ = (L + 1023) / 1024; algorithm: while (true) { step4: while (true) { // 4. Select an arbitrary bit string SEED such that length of SEED >= m nextRandomBytes(seedBytes); SEED = new BigInteger(1, seedBytes).setBit(m - 1).setBit(0); // 5. Set U = 0 U = BigInteger.ZERO; // 6. For i = 0 to m' - 1 // U = U + (SHA1[SEED + i] XOR SHA1[(SEED + m' + i)) * 2^(160 * i) // Note that for m=160, this reduces to the algorithm of [FIPS-186] // U = SHA1[SEED] XOR SHA1[(SEED+1) mod 2^160 ]. for (i = 0; i < m_; i++) { u1 = SEED.add(BigInteger.valueOf(i)).toByteArray(); u2 = SEED.add(BigInteger.valueOf(m_ + i)).toByteArray(); sha.update(u1, 0, u1.length); u1 = sha.digest(); sha.update(u2, 0, u2.length); u2 = sha.digest(); for (j = 0; j < u1.length; j++) { u1[j] ^= u2[j]; } U = U.add(new BigInteger(1, u1).multiply(TWO.pow(160 * i))); } // 5. Form q from U by computing U mod (2^m) and setting the most // significant bit (the 2^(m-1) bit) and the least significant bit to // 1. In terms of boolean operations, q = U OR 2^(m-1) OR 1. Note // that 2^(m-1) < q < 2^m q = U.setBit(m - 1).setBit(0); // 6. Use a robust primality algorithm to test whether q is prime. // 7. If q is not prime then go to 4. if (Prime2.isProbablePrime(q)) { break step4; } } // 8. Let counter = 0 counter = 0; step9: while (true) { // 9. Set R = seed + 2*m' + (L' * counter) R = SEED.add(BigInteger.valueOf(2 * m_)).add( BigInteger.valueOf(L_ * counter)); // 10. Set V = 0 V = BigInteger.ZERO; // 12. For i = 0 to L'-1 do: V = V + SHA1(R + i) * 2^(160 * i) for (i = 0; i < L_; i++) { v = R.toByteArray(); sha.update(v, 0, v.length); v = sha.digest(); V = V.add(new BigInteger(1, v).multiply(TWO.pow(160 * i))); } // 13. Set W = V mod 2^L W = V.mod(TWO.pow(L)); // 14. Set X = W OR 2^(L-1) // Note that 0 <= W < 2^(L-1) and hence X >= 2^(L-1) X = W.setBit(L - 1); // 15. Set p = X - (X mod (2*q)) + 1 p = X.add(BigInteger.ONE).subtract(X.mod(TWO.multiply(q))); // 16. If p > 2^(L-1) use a robust primality test to test whether p is // prime. Else go to 18. //17. If p is prime output p, q, seed, counter and stop. if (Prime2.isProbablePrime(p)) { break algorithm; } // 18. Set counter = counter + 1 counter++; // 19. If counter < (4096 * N) then go to 8. // 20. Output "failure" if (counter >= 4096 * N_) { continue algorithm; } } } // compute g. from FIPS-186, Appendix 4: // 1. Generate p and q as specified in Appendix 2. // 2. Let e = (p - 1) / q BigInteger e = p.subtract(BigInteger.ONE).divide(q); BigInteger h = TWO; BigInteger p_minus_1 = p.subtract(BigInteger.ONE); g = TWO; // 3. Set h = any integer, where 1 < h < p - 1 and h differs from any // value previously tried for (; h.compareTo(p_minus_1) < 0; h = h.add(BigInteger.ONE)) { // 4. Set g = h**e mod p g = h.modPow(e, p); // 5. If g = 1, go to step 3 if (!g.equals(BigInteger.ONE)) { break; } } return new BigInteger[] { SEED, BigInteger.valueOf(counter), q, p, e, g }; } // helper methods ---------------------------------------------------------- /** * <p>Fills the designated byte array with random data.</p> * * @param buffer the byte array to fill with random data. */ private void nextRandomBytes(byte[] buffer) { if (rnd != null) { rnd.nextBytes(buffer); } else getDefaultPRNG().nextBytes(buffer); } private PRNG getDefaultPRNG() { if (prng == null) prng = PRNG.getInstance(); return prng; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -