rsakeygen.java

来自「RSA加解密算法」· Java 代码 · 共 201 行

JAVA
201
字号
/* * Copyright (C) 1995, 1996 Systemics Ltd (http://www.systemics.com/) * All rights reserved. * * This library and applications are FREE FOR COMMERCIAL AND NON-COMMERCIAL USE * as long as the conditions within the COPYRIGHT file are adhered to. * */package cryptix.security.rsa;import cryptix.math.BigNum;import cryptix.math.BigInteger;import cryptix.math.RandomStream;import cryptix.math.TestPrime;/** * This class is an RSA key pair generator. * * <p>Copyright (C) 1995, 1996 Systemics Ltd (http://www.systemics.com/) * All rights reserved. */public class RSAKeyGen {	protected RandomStream rand;		/**	 * @param rand0 the source of random numbers for the prime number	 * generation.	 */	public RSAKeyGen( RandomStream rand0 )	{		rand = rand0;	}		/**	 * An observer class is used to monitor progress.<p>	 * @ param bitlen the bit length of the final n	 * @ param obsrv the callback interface.	 * @ return a random prime number.	 */	public BigInteger	randomPrime( int bitlen, RSAKeyGenObserver obsrv )	{		BigInteger ret = new BigInteger();		int bytelen = 1 + ( bitlen / 8 ), offset = bitlen % 8;		byte buf[] = new byte[bytelen];				while ( true )		{		// make big endian random number.			if ( rand.read( buf ) != bytelen )				throw new Error( "Not using a java.math.RandomStream !!!" );			buf[bytelen-1] |= 0x01; // make it odd.		// set top bit, and clear the others.			if ( offset == 0 )			{				buf[0] = 0;				buf[1] |= (byte)0x80;			}			else			{				buf[0] &= (byte)( 0xFF >>> ( 8 - offset ) );				buf[0] |= (byte)( 1 << ( offset - 1 ) );			}			ret.fromByteArray( buf );			if ( TestPrime.isPrime( ret, obsrv ) )				return ret;		}	}	/**	 * This function creates a Secret Key	 * <p>	 *<b>N.B.</b> this can take a LONG time.	 * @ param rand the source of random data for the prime number generation.	 * @ param bitlen the bit length of the final n	 * @ return a random RSA Secret Ket.	 */	public static final SecretKey	createKey( RandomStream rand, int bitlen )	{		return createKey( rand, bitlen, null );	}	/**	 * An observer class is used to monitor progress.<p>	 * @ param rand the source of random data for the prime number generation.	 * @ param bitlen The bit length of the final n	 * @ param obsrv The callback interface.	 * @ return a random RSA Secret key.	 */	public static final SecretKey	createKey( RandomStream rand, int bitlen, RSAKeyGenObserver obsrv )	{		return new RSAKeyGen( rand ).createKey( bitlen, obsrv );	}	/**	 * This function creates a Secret Key	 * <p>	 *<b>N.B.</b> this can take a LONG time.	 * @ param bitlen the bit length of the final n	 * @ return a random RSA Secret key.	 */	public SecretKey	createKey( int bitlen )	{		return createKey( bitlen, null );	}		/**	 * An observer class is used to monitor progress.<p>	 * @ param bitlen The bit length of the final n	 * @ param obsrv The callback interface.	 * @ return a random RSA Secret key.	 */	public SecretKey	createKey( int bitlen, RSAKeyGenObserver obsrv )	{		int plen = bitlen/2; // PGP requires that p and q are the same length.		int qlen = bitlen-plen;		signalObserver( obsrv, RSAKeyGenObserver.FINDING_P );		BigInteger p = randomPrime( plen, obsrv );		signalObserver( obsrv, RSAKeyGenObserver.FINDING_Q );		BigInteger q = randomPrime( qlen, obsrv );		BigInteger e = new BigInteger( 17 );		signalObserver( obsrv, RSAKeyGenObserver.KEY_RESOLVING );		SecretKey ret = deriveKeys( p, q, e );		signalObserver( obsrv, RSAKeyGenObserver.KEY_GEN_DONE );		return ret;	}	/**	 * An observer class is used to monitor progress.<p>	 * @ p is the largest factor of n	 * @ q is the other factor of n	 * @ e is the initial public exponent (must be odd).	 * @ return a random RSA Secret key.	 */	protected final SecretKey	deriveKeys( BigInteger p, BigInteger q, BigInteger e )	{		// Ensure p <= q		if ( p.cmp( q ) > 0 )		{			BigInteger t = p;			p = q;			q = t;		}		BigInteger t1 = new BigInteger().sub( p, BigInteger.one );		BigInteger t2 = new BigInteger().sub( q, BigInteger.one );		// phi(n) = (p-1)*(q-1)		BigInteger phi = new BigInteger().mul( t1, t2 );		// G(n) = gcd(p-1,q-1)		BigInteger gcdphi = new BigInteger().gcd( t1, t2 );		// F(n) = phi(n)/G(n)		t1.div( phi, gcdphi );		if ( e == null ) // if no e start at 3 e must be odd.			e = new BigInteger( 3 );		while( true )		{			t2.gcd( e, phi );			if ( t2.cmp( BigInteger.one ) == 0 )				break;			e.add( 2 );		}		// Compute d so that (e*d) mod F(n) = 1		BigInteger d = new BigInteger();		BigNum.inverseModN( d, e, t1 );		// Compute u so that (p*u) mod q = 1		BigInteger u = new BigInteger();		BigNum.inverseModN( u, p, q );		// n = p * q		BigInteger n = new BigInteger().mul( p, q );		SecretKey ret = new  SecretKey( n, e, d, p, q, u );		String test = ret.test();		if ( test != null )			throw new Error ( "RSA Key generation failed reason :\n" + test );		return ret;	} 			/**	 * this informs any observer of the current status	 * @param obsrv the obect to call, null if none.	 * @param signalValue status	 */	private static final void	signalObserver( RSAKeyGenObserver obsrv, int signalValue )	{		if ( obsrv != null )			obsrv.handleEvent( signalValue );	}}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?