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.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;

Factory to create ASN.1 private key info objects from lightweight private keys.
/** * 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.
Params:
  • privateKey – the key to be encoded into the info object.
Throws:
Returns:the appropriate PrivateKeyInfo
/** * 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.
Params:
  • privateKey – the key to be encoded into the info object.
  • attributes – the set of attributes to be included.
Throws:
Returns:the appropriate PrivateKeyInfo
/** * 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(), domainParams.getG(), domainParams.getN(), domainParams.getH(), domainParams.getSeed()); params = new X962Parameters(ecP); orderBitLength = domainParams.getN().bitLength(); } return new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params), new ECPrivateKey(orderBitLength, priv.getD(), new DERBitString(domainParams.getG().multiply(priv.getD()).getEncoded(false)), 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]; } } }