Crypto: Preserve CRT parameters for RSA private keys (ticket #2005)

This commit is contained in:
zzz
2017-07-13 15:53:00 +00:00
parent 5ddb4edd14
commit 0b85bffeff
4 changed files with 78 additions and 5 deletions

View 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;
}
}

View File

@@ -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");

View File

@@ -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

View File

@@ -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";