RSA 密钥生成的 BigInteger 实现
BigInteger implementation of RSA's key generation
我在使模数的大小始终为 128 字节大时遇到了一些麻烦。有时模数的字节数组大小为129甚至130。我在网上搜索了实现,我的实现非常接近link:http://introcs.cs.princeton.edu/java/78crypto/RSA.java.html
这是我的实现:
public static void genKey() throws NoSuchAlgorithmException, NoSuchProviderException {
int bitLength = 512;
SecureRandom srand = new SecureRandom();
BigInteger one = new BigInteger("1");
BigInteger p = BigInteger.probablePrime(bitLength, srand);
BigInteger q = BigInteger.probablePrime(bitLength, srand);
BigInteger phi = (p.subtract(one)).multiply(q.subtract(one));
BigInteger modulus = p.multiply(q); //Varies here
BigInteger publicKey = new BigInteger("65537");
BigInteger privateKey = publicKey.modInverse(phi);
byte[] modulusArray = modulus.toByteArray();
byte[] publicKeyArray = publicKey.toByteArray();
byte[] privateKeyArray = privateKey.toByteArray();
byte[] tmpArray = new byte[128];
for (int i = 0; i < publicKeyArray.length; i++) {
tmpArray[i] = publicKeyArray[i];
}
publicKeyArray = tmpArray;
byte[] publicKeyAndModulus = concat(modulusArray, publicKeyArray);
byte[] privateKeyAndModulus = concat(modulusArray, privateKeyArray);
}
此外,privateKey 的长度也会有所不同。我可以使用 java.Security 库使大小更加一致吗?或者这是不可能实现的?
我建议你使用BouncyCastle and create an AsymmetricCipherKeyPair
; here is an example I adapted from RSA using BouncyCastle
public static AsymmetricCipherKeyPair generateKeys(int keySizeInBits) {
RSAKeyPairGenerator kpg = new RSAKeyPairGenerator();
kpg.init(new KeyGenerationParameters(new SecureRandom(), keySizeInBits));
return kpg.generateKeyPair();
}
BigInteger#bitLength()
函数有必要的文档:
Returns the number of bits in the minimal two's-complement representation of this BigInteger, excluding a sign bit.
当您使用 bitLength
512 生成一个 BigInteger 时,最高有效位将是 0 ~50% 的时间,在这种情况下,符号位将取代它的位置并且它将适合 64 个字节,但是在其他情况下,最高有效位将为 1,这意味着符号位将被放入一个新字节中。
这意味着使用 511 作为 bitLength
总是会产生 64 字节的 BigIntegers 和 128 字节的模数。
您不应该真正自己生成 p
、q
、模数和所有其他值。最好使用现有的 API,例如 Java 的 Cipher class,它还提供适当的填充以与 OAEP 等 RSA 一起使用(PKCS#1 v1.5 不再适用): "RSA/ECB/OAEPWithSHA-256AndMGF1Padding".
我在使模数的大小始终为 128 字节大时遇到了一些麻烦。有时模数的字节数组大小为129甚至130。我在网上搜索了实现,我的实现非常接近link:http://introcs.cs.princeton.edu/java/78crypto/RSA.java.html
这是我的实现:
public static void genKey() throws NoSuchAlgorithmException, NoSuchProviderException {
int bitLength = 512;
SecureRandom srand = new SecureRandom();
BigInteger one = new BigInteger("1");
BigInteger p = BigInteger.probablePrime(bitLength, srand);
BigInteger q = BigInteger.probablePrime(bitLength, srand);
BigInteger phi = (p.subtract(one)).multiply(q.subtract(one));
BigInteger modulus = p.multiply(q); //Varies here
BigInteger publicKey = new BigInteger("65537");
BigInteger privateKey = publicKey.modInverse(phi);
byte[] modulusArray = modulus.toByteArray();
byte[] publicKeyArray = publicKey.toByteArray();
byte[] privateKeyArray = privateKey.toByteArray();
byte[] tmpArray = new byte[128];
for (int i = 0; i < publicKeyArray.length; i++) {
tmpArray[i] = publicKeyArray[i];
}
publicKeyArray = tmpArray;
byte[] publicKeyAndModulus = concat(modulusArray, publicKeyArray);
byte[] privateKeyAndModulus = concat(modulusArray, privateKeyArray);
}
此外,privateKey 的长度也会有所不同。我可以使用 java.Security 库使大小更加一致吗?或者这是不可能实现的?
我建议你使用BouncyCastle and create an AsymmetricCipherKeyPair
; here is an example I adapted from RSA using BouncyCastle
public static AsymmetricCipherKeyPair generateKeys(int keySizeInBits) {
RSAKeyPairGenerator kpg = new RSAKeyPairGenerator();
kpg.init(new KeyGenerationParameters(new SecureRandom(), keySizeInBits));
return kpg.generateKeyPair();
}
BigInteger#bitLength()
函数有必要的文档:
Returns the number of bits in the minimal two's-complement representation of this BigInteger, excluding a sign bit.
当您使用 bitLength
512 生成一个 BigInteger 时,最高有效位将是 0 ~50% 的时间,在这种情况下,符号位将取代它的位置并且它将适合 64 个字节,但是在其他情况下,最高有效位将为 1,这意味着符号位将被放入一个新字节中。
这意味着使用 511 作为 bitLength
总是会产生 64 字节的 BigIntegers 和 128 字节的模数。
您不应该真正自己生成 p
、q
、模数和所有其他值。最好使用现有的 API,例如 Java 的 Cipher class,它还提供适当的填充以与 OAEP 等 RSA 一起使用(PKCS#1 v1.5 不再适用): "RSA/ECB/OAEPWithSHA-256AndMGF1Padding".