forked from I2P_Developers/i2p.i2p
Crypto: Preserve CRT parameters for RSA private keys (ticket #2005)
This commit is contained in:
62
core/java/src/net/i2p/crypto/RSASigningPrivateCrtKey.java
Normal file
62
core/java/src/net/i2p/crypto/RSASigningPrivateCrtKey.java
Normal file
@@ -0,0 +1,62 @@
|
||||
package net.i2p.crypto;
|
||||
|
||||
/*
|
||||
* free (adj.): unencumbered; not under the control of others
|
||||
* No warranty of any kind, either expressed or implied.
|
||||
*/
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.interfaces.RSAPrivateCrtKey;
|
||||
import java.security.spec.RSAKeyGenParameterSpec;
|
||||
|
||||
import net.i2p.data.SigningPrivateKey;
|
||||
|
||||
/**
|
||||
* A SigningPrivateKey that retains the Chinese Remainder Theorem
|
||||
* parameters, so it can be converted back to a Java CRT key.
|
||||
*
|
||||
* By preserving the CRT parameters across a Java to I2P to Java
|
||||
* conversion, we speed up signing by about 3.3x, and
|
||||
* the parameters are correctly serialized in PEM format
|
||||
* when stored to a keystore.
|
||||
*
|
||||
* The CRT parameters are NOT retained when this object is
|
||||
* serialized via getData().
|
||||
*
|
||||
* @since 0.9.31
|
||||
*/
|
||||
final class RSASigningPrivateCrtKey extends SigningPrivateKey {
|
||||
|
||||
private final RSAPrivateCrtKey _crt;
|
||||
|
||||
/**
|
||||
* @throws IllegalArgumentException if data is not correct length
|
||||
*/
|
||||
public static RSASigningPrivateCrtKey fromJavaKey(RSAPrivateCrtKey pk) throws GeneralSecurityException {
|
||||
int sz = pk.getModulus().bitLength();
|
||||
SigType type;
|
||||
if (sz <= ((RSAKeyGenParameterSpec) SigType.RSA_SHA256_2048.getParams()).getKeysize())
|
||||
type = SigType.RSA_SHA256_2048;
|
||||
else if (sz <= ((RSAKeyGenParameterSpec) SigType.RSA_SHA384_3072.getParams()).getKeysize())
|
||||
type = SigType.RSA_SHA384_3072;
|
||||
else if (sz <= ((RSAKeyGenParameterSpec) SigType.RSA_SHA512_4096.getParams()).getKeysize())
|
||||
type = SigType.RSA_SHA512_4096;
|
||||
else
|
||||
throw new GeneralSecurityException("Unknown RSA type");
|
||||
// private key is modulus (pubkey) + exponent
|
||||
BigInteger n = pk.getModulus();
|
||||
BigInteger d = pk.getPrivateExponent();
|
||||
byte[] b = SigUtil.combine(n, d, type.getPrivkeyLen());
|
||||
return new RSASigningPrivateCrtKey(pk, type, b);
|
||||
}
|
||||
|
||||
private RSASigningPrivateCrtKey(RSAPrivateCrtKey pk, SigType type, byte[] data) {
|
||||
super(type, data);
|
||||
_crt = pk;
|
||||
}
|
||||
|
||||
public RSAPrivateCrtKey toJavaKey() {
|
||||
return _crt;
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ import java.security.interfaces.DSAPublicKey;
|
||||
import java.security.interfaces.ECPrivateKey;
|
||||
import java.security.interfaces.ECPublicKey;
|
||||
import java.security.interfaces.RSAPrivateKey;
|
||||
import java.security.interfaces.RSAPrivateCrtKey;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.security.spec.DSAPrivateKeySpec;
|
||||
@@ -444,10 +445,13 @@ public final class SigUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* As of 0.9.31, if pk is a RSASigningPrivateCrtKey,
|
||||
* this will return a RSAPrivateCrtKey.
|
||||
*/
|
||||
public static RSAPrivateKey toJavaRSAKey(SigningPrivateKey pk)
|
||||
throws GeneralSecurityException {
|
||||
if (pk instanceof RSASigningPrivateCrtKey)
|
||||
return ((RSASigningPrivateCrtKey) pk).toJavaKey();
|
||||
KeyFactory kf = KeyFactory.getInstance("RSA");
|
||||
// private key is modulus (pubkey) + exponent
|
||||
BigInteger[] nd = split(pk.getData());
|
||||
@@ -468,7 +472,8 @@ public final class SigUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated unused
|
||||
* As of 0.9.31, if pk is a RSAPrivateCrtKey,
|
||||
* this will return a RSASigningPrivateCrtKey.
|
||||
*/
|
||||
public static SigningPrivateKey fromJavaKey(RSAPrivateKey pk, SigType type)
|
||||
throws GeneralSecurityException {
|
||||
@@ -476,6 +481,8 @@ public final class SigUtil {
|
||||
BigInteger n = pk.getModulus();
|
||||
BigInteger d = pk.getPrivateExponent();
|
||||
byte[] b = combine(n, d, type.getPrivkeyLen());
|
||||
if (pk instanceof RSAPrivateCrtKey)
|
||||
return RSASigningPrivateCrtKey.fromJavaKey((RSAPrivateCrtKey) pk);
|
||||
return new SigningPrivateKey(type, b);
|
||||
}
|
||||
|
||||
@@ -569,9 +576,9 @@ public final class SigUtil {
|
||||
/**
|
||||
* Combine two BigIntegers of nominal length = len / 2
|
||||
* @return array of exactly len bytes
|
||||
* @since 0.9.9
|
||||
* @since 0.9.9, package private since 0.9.31
|
||||
*/
|
||||
private static byte[] combine(BigInteger x, BigInteger y, int len)
|
||||
static byte[] combine(BigInteger x, BigInteger y, int len)
|
||||
throws InvalidKeyException {
|
||||
if ((len & 0x01) != 0)
|
||||
throw new InvalidKeyException("length must be even");
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
2017-07-13 zzz
|
||||
* Crypto: Preserve CRT parameters for RSA private keys (ticket #2005)
|
||||
* Various fixes after review
|
||||
|
||||
2017-07-11 str4d
|
||||
* Console:
|
||||
- Increase displayed changelog lines to help ensure at least one whole
|
||||
|
||||
@@ -18,7 +18,7 @@ public class RouterVersion {
|
||||
/** deprecated */
|
||||
public final static String ID = "Monotone";
|
||||
public final static String VERSION = CoreVersion.VERSION;
|
||||
public final static long BUILD = 18;
|
||||
public final static long BUILD = 19;
|
||||
|
||||
/** for example "-test" */
|
||||
public final static String EXTRA = "-rc";
|
||||
|
||||
Reference in New Issue
Block a user