org.bouncycastle.crypto.util.PublicKeyFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bcprov-ext-debug-jdk15on Show documentation
Show all versions of bcprov-ext-debug-jdk15on 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 JDK 1.5 to JDK 1.8 with debug enabled.
package org.bouncycastle.crypto.util;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves;
import org.bouncycastle.asn1.cryptopro.GOST3410PublicKeyAlgParameters;
import org.bouncycastle.asn1.oiw.ElGamalParameter;
import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.DHParameter;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.RSAPublicKey;
import org.bouncycastle.asn1.rosstandart.RosstandartObjectIdentifiers;
import org.bouncycastle.asn1.ua.DSTU4145BinaryField;
import org.bouncycastle.asn1.ua.DSTU4145ECBinary;
import org.bouncycastle.asn1.ua.DSTU4145NamedCurves;
import org.bouncycastle.asn1.ua.DSTU4145Params;
import org.bouncycastle.asn1.ua.DSTU4145PointEncoder;
import org.bouncycastle.asn1.ua.UAObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.DSAParameter;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
import org.bouncycastle.asn1.x9.DHPublicKey;
import org.bouncycastle.asn1.x9.DomainParameters;
import org.bouncycastle.asn1.x9.ECNamedCurveTable;
import org.bouncycastle.asn1.x9.ValidationParams;
import org.bouncycastle.asn1.x9.X962Parameters;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.asn1.x9.X9ECPoint;
import org.bouncycastle.asn1.x9.X9IntegerConverter;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.crypto.ec.CustomNamedCurves;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.DHParameters;
import org.bouncycastle.crypto.params.DHPublicKeyParameters;
import org.bouncycastle.crypto.params.DHValidationParameters;
import org.bouncycastle.crypto.params.DSAParameters;
import org.bouncycastle.crypto.params.DSAPublicKeyParameters;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECNamedDomainParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ElGamalParameters;
import org.bouncycastle.crypto.params.ElGamalPublicKeyParameters;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.math.ec.ECCurve;
/**
* Factory to create asymmetric public key parameters for asymmetric ciphers from range of
* ASN.1 encoded SubjectPublicKeyInfo objects.
*/
public class PublicKeyFactory
{
private static Map converters = new HashMap();
static
{
converters.put(PKCSObjectIdentifiers.rsaEncryption, new RSAConverter());
converters.put(X509ObjectIdentifiers.id_ea_rsa, new RSAConverter());
converters.put(X9ObjectIdentifiers.dhpublicnumber, new DHPublicNumberConverter());
converters.put(PKCSObjectIdentifiers.dhKeyAgreement, new DHAgreementConverter());
converters.put(X9ObjectIdentifiers.id_dsa, new DSAConverter());
converters.put(OIWObjectIdentifiers.dsaWithSHA1, new DSAConverter());
converters.put(OIWObjectIdentifiers.elGamalAlgorithm, new ElGamalConverter());
converters.put(X9ObjectIdentifiers.id_ecPublicKey, new ECConverter());
converters.put(CryptoProObjectIdentifiers.gostR3410_2001, new GOST3410_2001Converter());
converters.put(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256, new GOST3410_2012Converter());
converters.put(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512, new GOST3410_2012Converter());
converters.put(UAObjectIdentifiers.dstu4145be, new DSTUConverter());
converters.put(UAObjectIdentifiers.dstu4145le, new DSTUConverter());
}
/**
* Create a public key from a SubjectPublicKeyInfo encoding
*
* @param keyInfoData the SubjectPublicKeyInfo encoding
* @return the appropriate key parameter
* @throws IOException on an error decoding the key
*/
public static AsymmetricKeyParameter createKey(byte[] keyInfoData)
throws IOException
{
return createKey(SubjectPublicKeyInfo.getInstance(ASN1Primitive.fromByteArray(keyInfoData)));
}
/**
* Create a public key from a SubjectPublicKeyInfo encoding read from a stream
*
* @param inStr the stream to read the SubjectPublicKeyInfo encoding from
* @return the appropriate key parameter
* @throws IOException on an error decoding the key
*/
public static AsymmetricKeyParameter createKey(InputStream inStr)
throws IOException
{
return createKey(SubjectPublicKeyInfo.getInstance(new ASN1InputStream(inStr).readObject()));
}
/**
* Create a public key from the passed in SubjectPublicKeyInfo
*
* @param keyInfo the SubjectPublicKeyInfo containing the key data
* @return the appropriate key parameter
* @throws IOException on an error decoding the key
*/
public static AsymmetricKeyParameter createKey(SubjectPublicKeyInfo keyInfo)
throws IOException
{
return createKey(keyInfo, null);
}
/**
* Create a public key from the passed in SubjectPublicKeyInfo
*
* @param keyInfo the SubjectPublicKeyInfo containing the key data
* @param defaultParams default parameters that might be needed.
* @return the appropriate key parameter
* @throws IOException on an error decoding the key
*/
public static AsymmetricKeyParameter createKey(SubjectPublicKeyInfo keyInfo, Object defaultParams)
throws IOException
{
AlgorithmIdentifier algId = keyInfo.getAlgorithm();
SubjectPublicKeyInfoConverter converter = (SubjectPublicKeyInfoConverter)converters.get(algId.getAlgorithm());
if (converter != null)
{
return converter.getPublicKeyParameters(keyInfo, defaultParams);
}
else
{
throw new IOException("algorithm identifier in key not recognised: " + algId.getAlgorithm());
}
}
private static abstract class SubjectPublicKeyInfoConverter
{
abstract AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
throws IOException;
}
private static class RSAConverter
extends SubjectPublicKeyInfoConverter
{
AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
throws IOException
{
RSAPublicKey pubKey = RSAPublicKey.getInstance(keyInfo.parsePublicKey());
return new RSAKeyParameters(false, pubKey.getModulus(), pubKey.getPublicExponent());
}
}
private static class DHPublicNumberConverter
extends SubjectPublicKeyInfoConverter
{
AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
throws IOException
{
DHPublicKey dhPublicKey = DHPublicKey.getInstance(keyInfo.parsePublicKey());
BigInteger y = dhPublicKey.getY();
DomainParameters dhParams = DomainParameters.getInstance(keyInfo.getAlgorithm().getParameters());
BigInteger p = dhParams.getP();
BigInteger g = dhParams.getG();
BigInteger q = dhParams.getQ();
BigInteger j = null;
if (dhParams.getJ() != null)
{
j = dhParams.getJ();
}
DHValidationParameters validation = null;
ValidationParams dhValidationParms = dhParams.getValidationParams();
if (dhValidationParms != null)
{
byte[] seed = dhValidationParms.getSeed();
BigInteger pgenCounter = dhValidationParms.getPgenCounter();
// TODO Check pgenCounter size?
validation = new DHValidationParameters(seed, pgenCounter.intValue());
}
return new DHPublicKeyParameters(y, new DHParameters(p, g, q, j, validation));
}
}
private static class DHAgreementConverter
extends SubjectPublicKeyInfoConverter
{
AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
throws IOException
{
DHParameter params = DHParameter.getInstance(keyInfo.getAlgorithm().getParameters());
ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey();
BigInteger lVal = params.getL();
int l = lVal == null ? 0 : lVal.intValue();
DHParameters dhParams = new DHParameters(params.getP(), params.getG(), null, l);
return new DHPublicKeyParameters(derY.getValue(), dhParams);
}
}
private static class ElGamalConverter
extends SubjectPublicKeyInfoConverter
{
AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
throws IOException
{
ElGamalParameter params = ElGamalParameter.getInstance(keyInfo.getAlgorithm().getParameters());
ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey();
return new ElGamalPublicKeyParameters(derY.getValue(), new ElGamalParameters(
params.getP(), params.getG()));
}
}
private static class DSAConverter
extends SubjectPublicKeyInfoConverter
{
AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
throws IOException
{
ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey();
ASN1Encodable de = keyInfo.getAlgorithm().getParameters();
DSAParameters parameters = null;
if (de != null)
{
DSAParameter params = DSAParameter.getInstance(de.toASN1Primitive());
parameters = new DSAParameters(params.getP(), params.getQ(), params.getG());
}
return new DSAPublicKeyParameters(derY.getValue(), parameters);
}
}
private static class ECConverter
extends SubjectPublicKeyInfoConverter
{
AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
{
X962Parameters params = X962Parameters.getInstance(keyInfo.getAlgorithm().getParameters());
ECDomainParameters dParams;
if (params.isNamedCurve())
{
ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)params.getParameters();
X9ECParameters x9 = CustomNamedCurves.getByOID(oid);
if (x9 == null)
{
x9 = ECNamedCurveTable.getByOID(oid);
}
dParams = new ECNamedDomainParameters(
oid, x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
}
else if (params.isImplicitlyCA())
{
dParams = (ECDomainParameters)defaultParams;
}
else
{
X9ECParameters x9 = X9ECParameters.getInstance(params.getParameters());
dParams = new ECDomainParameters(
x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
}
DERBitString bits = keyInfo.getPublicKeyData();
byte[] data = bits.getBytes();
ASN1OctetString key = new DEROctetString(data);
//
// extra octet string - the old extra embedded octet string
//
if (data[0] == 0x04 && data[1] == data.length - 2
&& (data[2] == 0x02 || data[2] == 0x03))
{
int qLength = new X9IntegerConverter().getByteLength(dParams.getCurve());
if (qLength >= data.length - 3)
{
try
{
key = (ASN1OctetString)ASN1Primitive.fromByteArray(data);
}
catch (IOException ex)
{
throw new IllegalArgumentException("error recovering public key");
}
}
}
X9ECPoint derQ = new X9ECPoint(dParams.getCurve(), key);
return new ECPublicKeyParameters(derQ.getPoint(), dParams);
}
}
private static class GOST3410_2001Converter
extends SubjectPublicKeyInfoConverter
{
AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
{
DERBitString bits = keyInfo.getPublicKeyData();
ASN1OctetString key;
try
{
key = (ASN1OctetString)ASN1Primitive.fromByteArray(bits.getBytes());
}
catch (IOException ex)
{
throw new IllegalArgumentException("error recovering public key");
}
byte[] keyEnc = key.getOctets();
byte[] x9Encoding = new byte[65];
x9Encoding[0] = 0x04;
for (int i = 1; i <= 32; ++i)
{
x9Encoding[i] = keyEnc[32 - i];
x9Encoding[i + 32] = keyEnc[64 - i];
}
ASN1ObjectIdentifier paramOID;
if (keyInfo.getAlgorithm().getParameters() instanceof ASN1ObjectIdentifier)
{
paramOID = ASN1ObjectIdentifier.getInstance(keyInfo.getAlgorithm().getParameters());
}
else
{
GOST3410PublicKeyAlgParameters params = GOST3410PublicKeyAlgParameters.getInstance(keyInfo.getAlgorithm().getParameters());
paramOID = params.getPublicKeyParamSet();
}
ECDomainParameters ecDomainParameters = ECGOST3410NamedCurves.getByOID(paramOID);
return new ECPublicKeyParameters(ecDomainParameters.getCurve().decodePoint(x9Encoding), ecDomainParameters);
}
}
private static class GOST3410_2012Converter
extends SubjectPublicKeyInfoConverter
{
AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
{
ASN1ObjectIdentifier algOid = keyInfo.getAlgorithm().getAlgorithm();
DERBitString bits = keyInfo.getPublicKeyData();
ASN1OctetString key;
try
{
key = (ASN1OctetString)ASN1Primitive.fromByteArray(bits.getBytes());
}
catch (IOException ex)
{
throw new IllegalArgumentException("error recovering public key");
}
byte[] keyEnc = key.getOctets();
int fieldSize = 32;
if (algOid.equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512))
{
fieldSize = 64;
}
int keySize = 2 * fieldSize;
byte[] x9Encoding = new byte[1 + keySize];
x9Encoding[0] = 0x04;
for (int i = 1; i <= fieldSize; ++i)
{
x9Encoding[i] = keyEnc[fieldSize - i];
x9Encoding[i + fieldSize] = keyEnc[keySize - i];
}
GOST3410PublicKeyAlgParameters gostParams = GOST3410PublicKeyAlgParameters.getInstance(keyInfo.getAlgorithm().getParameters());
ECDomainParameters ecDomainParameters = ECGOST3410NamedCurves.getByOID(gostParams.getPublicKeyParamSet());
return new ECPublicKeyParameters(ecDomainParameters.getCurve().decodePoint(x9Encoding), ecDomainParameters);
}
}
private static class DSTUConverter
extends SubjectPublicKeyInfoConverter
{
AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
throws IOException
{
DERBitString bits = keyInfo.getPublicKeyData();
ASN1OctetString key;
try
{
key = (ASN1OctetString)ASN1Primitive.fromByteArray(bits.getBytes());
}
catch (IOException ex)
{
throw new IllegalArgumentException("error recovering public key");
}
byte[] keyEnc = key.getOctets();
if (keyInfo.getAlgorithm().getAlgorithm().equals(UAObjectIdentifiers.dstu4145le))
{
reverseBytes(keyEnc);
}
DSTU4145Params dstuParams = DSTU4145Params.getInstance(keyInfo.getAlgorithm().getParameters());
ECDomainParameters ecDomain;
if (dstuParams.isNamedCurve())
{
ASN1ObjectIdentifier curveOid = dstuParams.getNamedCurve();
ecDomain = DSTU4145NamedCurves.getByOID(curveOid);
}
else
{
DSTU4145ECBinary binary = dstuParams.getECBinary();
byte[] b_bytes = binary.getB();
if (keyInfo.getAlgorithm().getAlgorithm().equals(UAObjectIdentifiers.dstu4145le))
{
reverseBytes(b_bytes);
}
DSTU4145BinaryField field = binary.getField();
ECCurve curve = new ECCurve.F2m(field.getM(), field.getK1(), field.getK2(), field.getK3(), binary.getA(), new BigInteger(1, b_bytes));
byte[] g_bytes = binary.getG();
if (keyInfo.getAlgorithm().getAlgorithm().equals(UAObjectIdentifiers.dstu4145le))
{
reverseBytes(g_bytes);
}
ecDomain = new ECDomainParameters(curve, DSTU4145PointEncoder.decodePoint(curve, g_bytes), binary.getN());
}
return new ECPublicKeyParameters(DSTU4145PointEncoder.decodePoint(ecDomain.getCurve(), keyEnc), ecDomain);
}
private void reverseBytes(byte[] bytes)
{
byte tmp;
for (int i = 0; i < bytes.length / 2; i++)
{
tmp = bytes[i];
bytes[i] = bytes[bytes.length - 1 - i];
bytes[bytes.length - 1 - i] = tmp;
}
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy