org.bouncycastle.crypto.util.PrivateKeyInfoFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bcprov-ext-debug-jdk18on Show documentation
Show all versions of bcprov-ext-debug-jdk18on Show documentation
The Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. This jar contains JCE provider and lightweight API for the Bouncy Castle Cryptography APIs for Java 1.8 and later with debug enabled.
The newest version!
package org.bouncycastle.crypto.util;
import java.io.IOException;
import java.math.BigInteger;
import java.util.HashSet;
import java.util.Set;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
import org.bouncycastle.asn1.cryptopro.GOST3410PublicKeyAlgParameters;
import org.bouncycastle.asn1.edec.EdECObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.pkcs.RSAPrivateKey;
import org.bouncycastle.asn1.rosstandart.RosstandartObjectIdentifiers;
import org.bouncycastle.asn1.sec.ECPrivateKey;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.DSAParameter;
import org.bouncycastle.asn1.x9.X962Parameters;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.asn1.x9.X9ECPoint;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.DSAParameters;
import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECGOST3410Parameters;
import org.bouncycastle.crypto.params.ECNamedDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters;
import org.bouncycastle.crypto.params.Ed448PrivateKeyParameters;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
import org.bouncycastle.crypto.params.X25519PrivateKeyParameters;
import org.bouncycastle.crypto.params.X448PrivateKeyParameters;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.ec.FixedPointCombMultiplier;
/**
* Factory to create ASN.1 private key info objects from lightweight private keys.
*/
public class PrivateKeyInfoFactory
{
private static Set cryptoProOids = new HashSet(5);
static
{
cryptoProOids.add(CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_A);
cryptoProOids.add(CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_B);
cryptoProOids.add(CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_C);
cryptoProOids.add(CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_XchA);
cryptoProOids.add(CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_XchB);
}
private PrivateKeyInfoFactory()
{
}
/**
* Create a PrivateKeyInfo representation of a private key.
*
* @param privateKey the key to be encoded into the info object.
* @return the appropriate PrivateKeyInfo
* @throws java.io.IOException on an error encoding the key
*/
public static PrivateKeyInfo createPrivateKeyInfo(AsymmetricKeyParameter privateKey)
throws IOException
{
return createPrivateKeyInfo(privateKey, null);
}
/**
* Create a PrivateKeyInfo representation of a private key with attributes.
*
* @param privateKey the key to be encoded into the info object.
* @param attributes the set of attributes to be included.
* @return the appropriate PrivateKeyInfo
* @throws java.io.IOException on an error encoding the key
*/
public static PrivateKeyInfo createPrivateKeyInfo(AsymmetricKeyParameter privateKey, ASN1Set attributes)
throws IOException
{
if (privateKey instanceof RSAKeyParameters)
{
RSAPrivateCrtKeyParameters priv = (RSAPrivateCrtKeyParameters)privateKey;
return new PrivateKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE),
new RSAPrivateKey(priv.getModulus(), priv.getPublicExponent(), priv.getExponent(), priv.getP(), priv.getQ(), priv.getDP(), priv.getDQ(), priv.getQInv()),
attributes);
}
else if (privateKey instanceof DSAPrivateKeyParameters)
{
DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)privateKey;
DSAParameters params = priv.getParameters();
return new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa,
new DSAParameter(params.getP(), params.getQ(), params.getG())), new ASN1Integer(priv.getX()),
attributes);
}
else if (privateKey instanceof ECPrivateKeyParameters)
{
ECPrivateKeyParameters priv = (ECPrivateKeyParameters)privateKey;
ECDomainParameters domainParams = priv.getParameters();
ASN1Encodable params;
int orderBitLength;
if (domainParams == null)
{
params = new X962Parameters(DERNull.INSTANCE); // Implicitly CA
orderBitLength = priv.getD().bitLength(); // TODO: this is as good as currently available, must be a better way...
}
else if (domainParams instanceof ECGOST3410Parameters)
{
GOST3410PublicKeyAlgParameters gostParams = new GOST3410PublicKeyAlgParameters(
((ECGOST3410Parameters)domainParams).getPublicKeyParamSet(),
((ECGOST3410Parameters)domainParams).getDigestParamSet(),
((ECGOST3410Parameters)domainParams).getEncryptionParamSet());
int size;
ASN1ObjectIdentifier identifier;
if (cryptoProOids.contains(gostParams.getPublicKeyParamSet()))
{
size = 32;
identifier = CryptoProObjectIdentifiers.gostR3410_2001;
}
else
{
boolean is512 = priv.getD().bitLength() > 256;
identifier = (is512) ?
RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512 :
RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256;
size = (is512) ? 64 : 32;
}
byte[] encKey = new byte[size];
extractBytes(encKey, size, 0, priv.getD());
return new PrivateKeyInfo(new AlgorithmIdentifier(identifier, gostParams), new DEROctetString(encKey));
}
else if (domainParams instanceof ECNamedDomainParameters)
{
params = new X962Parameters(((ECNamedDomainParameters)domainParams).getName());
orderBitLength = domainParams.getN().bitLength();
}
else
{
X9ECParameters ecP = new X9ECParameters(
domainParams.getCurve(),
new X9ECPoint(domainParams.getG(), false),
domainParams.getN(),
domainParams.getH(),
domainParams.getSeed());
params = new X962Parameters(ecP);
orderBitLength = domainParams.getN().bitLength();
}
ECPoint q = new FixedPointCombMultiplier().multiply(domainParams.getG(), priv.getD());
// TODO Support point compression
DERBitString publicKey = new DERBitString(q.getEncoded(false));
return new PrivateKeyInfo(
new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params),
new ECPrivateKey(orderBitLength, priv.getD(), publicKey, params),
attributes);
}
else if (privateKey instanceof X448PrivateKeyParameters)
{
X448PrivateKeyParameters key = (X448PrivateKeyParameters)privateKey;
return new PrivateKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_X448),
new DEROctetString(key.getEncoded()), attributes, key.generatePublicKey().getEncoded());
}
else if (privateKey instanceof X25519PrivateKeyParameters)
{
X25519PrivateKeyParameters key = (X25519PrivateKeyParameters)privateKey;
return new PrivateKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_X25519),
new DEROctetString(key.getEncoded()), attributes, key.generatePublicKey().getEncoded());
}
else if (privateKey instanceof Ed448PrivateKeyParameters)
{
Ed448PrivateKeyParameters key = (Ed448PrivateKeyParameters)privateKey;
return new PrivateKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_Ed448),
new DEROctetString(key.getEncoded()), attributes, key.generatePublicKey().getEncoded());
}
else if (privateKey instanceof Ed25519PrivateKeyParameters)
{
Ed25519PrivateKeyParameters key = (Ed25519PrivateKeyParameters)privateKey;
return new PrivateKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_Ed25519),
new DEROctetString(key.getEncoded()), attributes, key.generatePublicKey().getEncoded());
}
else
{
throw new IOException("key parameters not recognized");
}
}
private static void extractBytes(byte[] encKey, int size, int offSet, BigInteger bI)
{
byte[] val = bI.toByteArray();
if (val.length < size)
{
byte[] tmp = new byte[size];
System.arraycopy(val, 0, tmp, tmp.length - val.length, val.length);
val = tmp;
}
for (int i = 0; i != size; i++)
{
encKey[offSet + i] = val[val.length - 1 - i];
}
}
}