diff options
Diffstat (limited to 'core/src/main/java/org/spongycastle/crypto/util')
5 files changed, 729 insertions, 0 deletions
diff --git a/core/src/main/java/org/spongycastle/crypto/util/Pack.java b/core/src/main/java/org/spongycastle/crypto/util/Pack.java new file mode 100644 index 00000000..e7743e9a --- /dev/null +++ b/core/src/main/java/org/spongycastle/crypto/util/Pack.java @@ -0,0 +1,204 @@ +package org.spongycastle.crypto.util; + +/** + * @deprecated use org.spongycastle.util.pack + */ +public abstract class Pack +{ + public static int bigEndianToInt(byte[] bs, int off) + { + int n = bs[ off] << 24; + n |= (bs[++off] & 0xff) << 16; + n |= (bs[++off] & 0xff) << 8; + n |= (bs[++off] & 0xff); + return n; + } + + public static void bigEndianToInt(byte[] bs, int off, int[] ns) + { + for (int i = 0; i < ns.length; ++i) + { + ns[i] = bigEndianToInt(bs, off); + off += 4; + } + } + + public static byte[] intToBigEndian(int n) + { + byte[] bs = new byte[4]; + intToBigEndian(n, bs, 0); + return bs; + } + + public static void intToBigEndian(int n, byte[] bs, int off) + { + bs[ off] = (byte)(n >>> 24); + bs[++off] = (byte)(n >>> 16); + bs[++off] = (byte)(n >>> 8); + bs[++off] = (byte)(n ); + } + + public static byte[] intToBigEndian(int[] ns) + { + byte[] bs = new byte[4 * ns.length]; + intToBigEndian(ns, bs, 0); + return bs; + } + + public static void intToBigEndian(int[] ns, byte[] bs, int off) + { + for (int i = 0; i < ns.length; ++i) + { + intToBigEndian(ns[i], bs, off); + off += 4; + } + } + + public static long bigEndianToLong(byte[] bs, int off) + { + int hi = bigEndianToInt(bs, off); + int lo = bigEndianToInt(bs, off + 4); + return ((long)(hi & 0xffffffffL) << 32) | (long)(lo & 0xffffffffL); + } + + public static void bigEndianToLong(byte[] bs, int off, long[] ns) + { + for (int i = 0; i < ns.length; ++i) + { + ns[i] = bigEndianToLong(bs, off); + off += 8; + } + } + + public static byte[] longToBigEndian(long n) + { + byte[] bs = new byte[8]; + longToBigEndian(n, bs, 0); + return bs; + } + + public static void longToBigEndian(long n, byte[] bs, int off) + { + intToBigEndian((int)(n >>> 32), bs, off); + intToBigEndian((int)(n & 0xffffffffL), bs, off + 4); + } + + public static byte[] longToBigEndian(long[] ns) + { + byte[] bs = new byte[8 * ns.length]; + longToBigEndian(ns, bs, 0); + return bs; + } + + public static void longToBigEndian(long[] ns, byte[] bs, int off) + { + for (int i = 0; i < ns.length; ++i) + { + longToBigEndian(ns[i], bs, off); + off += 8; + } + } + + public static int littleEndianToInt(byte[] bs, int off) + { + int n = bs[ off] & 0xff; + n |= (bs[++off] & 0xff) << 8; + n |= (bs[++off] & 0xff) << 16; + n |= bs[++off] << 24; + return n; + } + + public static void littleEndianToInt(byte[] bs, int off, int[] ns) + { + for (int i = 0; i < ns.length; ++i) + { + ns[i] = littleEndianToInt(bs, off); + off += 4; + } + } + + public static void littleEndianToInt(byte[] bs, int bOff, int[] ns, int nOff, int count) + { + for (int i = 0; i < count; ++i) + { + ns[nOff + i] = littleEndianToInt(bs, bOff); + bOff += 4; + } + } + + public static byte[] intToLittleEndian(int n) + { + byte[] bs = new byte[4]; + intToLittleEndian(n, bs, 0); + return bs; + } + + public static void intToLittleEndian(int n, byte[] bs, int off) + { + bs[ off] = (byte)(n ); + bs[++off] = (byte)(n >>> 8); + bs[++off] = (byte)(n >>> 16); + bs[++off] = (byte)(n >>> 24); + } + + public static byte[] intToLittleEndian(int[] ns) + { + byte[] bs = new byte[4 * ns.length]; + intToLittleEndian(ns, bs, 0); + return bs; + } + + public static void intToLittleEndian(int[] ns, byte[] bs, int off) + { + for (int i = 0; i < ns.length; ++i) + { + intToLittleEndian(ns[i], bs, off); + off += 4; + } + } + + public static long littleEndianToLong(byte[] bs, int off) + { + int lo = littleEndianToInt(bs, off); + int hi = littleEndianToInt(bs, off + 4); + return ((long)(hi & 0xffffffffL) << 32) | (long)(lo & 0xffffffffL); + } + + public static void littleEndianToLong(byte[] bs, int off, long[] ns) + { + for (int i = 0; i < ns.length; ++i) + { + ns[i] = littleEndianToLong(bs, off); + off += 8; + } + } + + public static byte[] longToLittleEndian(long n) + { + byte[] bs = new byte[8]; + longToLittleEndian(n, bs, 0); + return bs; + } + + public static void longToLittleEndian(long n, byte[] bs, int off) + { + intToLittleEndian((int)(n & 0xffffffffL), bs, off); + intToLittleEndian((int)(n >>> 32), bs, off + 4); + } + + public static byte[] longToLittleEndian(long[] ns) + { + byte[] bs = new byte[8 * ns.length]; + longToLittleEndian(ns, bs, 0); + return bs; + } + + public static void longToLittleEndian(long[] ns, byte[] bs, int off) + { + for (int i = 0; i < ns.length; ++i) + { + longToLittleEndian(ns[i], bs, off); + off += 8; + } + } +} diff --git a/core/src/main/java/org/spongycastle/crypto/util/PrivateKeyFactory.java b/core/src/main/java/org/spongycastle/crypto/util/PrivateKeyFactory.java new file mode 100644 index 00000000..289b25f5 --- /dev/null +++ b/core/src/main/java/org/spongycastle/crypto/util/PrivateKeyFactory.java @@ -0,0 +1,159 @@ +package org.spongycastle.crypto.util; + +import java.io.IOException; +import java.io.InputStream; +import java.math.BigInteger; + +import org.spongycastle.asn1.ASN1Encodable; +import org.spongycastle.asn1.ASN1InputStream; +import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.ASN1Primitive; +import org.spongycastle.asn1.oiw.ElGamalParameter; +import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; +import org.spongycastle.asn1.pkcs.DHParameter; +import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.spongycastle.asn1.pkcs.PrivateKeyInfo; +import org.spongycastle.asn1.pkcs.RSAPrivateKey; +import org.spongycastle.asn1.sec.ECPrivateKey; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.asn1.x509.DSAParameter; +import org.spongycastle.asn1.x9.ECNamedCurveTable; +import org.spongycastle.asn1.x9.X962Parameters; +import org.spongycastle.asn1.x9.X9ECParameters; +import org.spongycastle.asn1.x9.X9ObjectIdentifiers; +import org.spongycastle.crypto.ec.CustomNamedCurves; +import org.spongycastle.crypto.params.AsymmetricKeyParameter; +import org.spongycastle.crypto.params.DHParameters; +import org.spongycastle.crypto.params.DHPrivateKeyParameters; +import org.spongycastle.crypto.params.DSAParameters; +import org.spongycastle.crypto.params.DSAPrivateKeyParameters; +import org.spongycastle.crypto.params.ECDomainParameters; +import org.spongycastle.crypto.params.ECNamedDomainParameters; +import org.spongycastle.crypto.params.ECPrivateKeyParameters; +import org.spongycastle.crypto.params.ElGamalParameters; +import org.spongycastle.crypto.params.ElGamalPrivateKeyParameters; +import org.spongycastle.crypto.params.RSAPrivateCrtKeyParameters; + +/** + * Factory for creating private key objects from PKCS8 PrivateKeyInfo objects. + */ +public class PrivateKeyFactory +{ + /** + * Create a private key parameter from a PKCS8 PrivateKeyInfo encoding. + * + * @param privateKeyInfoData the PrivateKeyInfo encoding + * @return a suitable private key parameter + * @throws IOException on an error decoding the key + */ + public static AsymmetricKeyParameter createKey(byte[] privateKeyInfoData) throws IOException + { + return createKey(PrivateKeyInfo.getInstance(ASN1Primitive.fromByteArray(privateKeyInfoData))); + } + + /** + * Create a private key parameter from a PKCS8 PrivateKeyInfo encoding read from a + * stream. + * + * @param inStr the stream to read the PrivateKeyInfo encoding from + * @return a suitable private key parameter + * @throws IOException on an error decoding the key + */ + public static AsymmetricKeyParameter createKey(InputStream inStr) throws IOException + { + return createKey(PrivateKeyInfo.getInstance(new ASN1InputStream(inStr).readObject())); + } + + /** + * Create a private key parameter from the passed in PKCS8 PrivateKeyInfo object. + * + * @param keyInfo the PrivateKeyInfo object containing the key material + * @return a suitable private key parameter + * @throws IOException on an error decoding the key + */ + public static AsymmetricKeyParameter createKey(PrivateKeyInfo keyInfo) throws IOException + { + AlgorithmIdentifier algId = keyInfo.getPrivateKeyAlgorithm(); + + if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.rsaEncryption)) + { + RSAPrivateKey keyStructure = RSAPrivateKey.getInstance(keyInfo.parsePrivateKey()); + + return new RSAPrivateCrtKeyParameters(keyStructure.getModulus(), + keyStructure.getPublicExponent(), keyStructure.getPrivateExponent(), + keyStructure.getPrime1(), keyStructure.getPrime2(), keyStructure.getExponent1(), + keyStructure.getExponent2(), keyStructure.getCoefficient()); + } + // TODO? +// else if (algId.getObjectId().equals(X9ObjectIdentifiers.dhpublicnumber)) + else if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.dhKeyAgreement)) + { + DHParameter params = DHParameter.getInstance(algId.getParameters()); + ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey(); + + BigInteger lVal = params.getL(); + int l = lVal == null ? 0 : lVal.intValue(); + DHParameters dhParams = new DHParameters(params.getP(), params.getG(), null, l); + + return new DHPrivateKeyParameters(derX.getValue(), dhParams); + } + else if (algId.getAlgorithm().equals(OIWObjectIdentifiers.elGamalAlgorithm)) + { + ElGamalParameter params = ElGamalParameter.getInstance(algId.getParameters()); + ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey(); + + return new ElGamalPrivateKeyParameters(derX.getValue(), new ElGamalParameters( + params.getP(), params.getG())); + } + else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_dsa)) + { + ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey(); + ASN1Encodable de = algId.getParameters(); + + DSAParameters parameters = null; + if (de != null) + { + DSAParameter params = DSAParameter.getInstance(de.toASN1Primitive()); + parameters = new DSAParameters(params.getP(), params.getQ(), params.getG()); + } + + return new DSAPrivateKeyParameters(derX.getValue(), parameters); + } + else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_ecPublicKey)) + { + X962Parameters params = new X962Parameters((ASN1Primitive)algId.getParameters()); + + X9ECParameters x9; + ECDomainParameters dParams; + + if (params.isNamedCurve()) + { + ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)params.getParameters(); + + 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 + { + x9 = X9ECParameters.getInstance(params.getParameters()); + dParams = new ECDomainParameters( + x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed()); + } + + ECPrivateKey ec = ECPrivateKey.getInstance(keyInfo.parsePrivateKey()); + BigInteger d = ec.getKey(); + + return new ECPrivateKeyParameters(d, dParams); + } + else + { + throw new RuntimeException("algorithm identifier in key not recognised"); + } + } +} diff --git a/core/src/main/java/org/spongycastle/crypto/util/PrivateKeyInfoFactory.java b/core/src/main/java/org/spongycastle/crypto/util/PrivateKeyInfoFactory.java new file mode 100644 index 00000000..3fa6d2f1 --- /dev/null +++ b/core/src/main/java/org/spongycastle/crypto/util/PrivateKeyInfoFactory.java @@ -0,0 +1,86 @@ +package org.spongycastle.crypto.util; + +import java.io.IOException; + +import org.spongycastle.asn1.ASN1Encodable; +import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.DERNull; +import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.spongycastle.asn1.pkcs.PrivateKeyInfo; +import org.spongycastle.asn1.pkcs.RSAPrivateKey; +import org.spongycastle.asn1.sec.ECPrivateKey; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.asn1.x509.DSAParameter; +import org.spongycastle.asn1.x9.X962Parameters; +import org.spongycastle.asn1.x9.X9ECParameters; +import org.spongycastle.asn1.x9.X9ObjectIdentifiers; +import org.spongycastle.crypto.params.AsymmetricKeyParameter; +import org.spongycastle.crypto.params.DSAParameters; +import org.spongycastle.crypto.params.DSAPrivateKeyParameters; +import org.spongycastle.crypto.params.ECDomainParameters; +import org.spongycastle.crypto.params.ECNamedDomainParameters; +import org.spongycastle.crypto.params.ECPrivateKeyParameters; +import org.spongycastle.crypto.params.RSAKeyParameters; +import org.spongycastle.crypto.params.RSAPrivateCrtKeyParameters; + +/** + * Factory to create ASN.1 private key info objects from lightweight private keys. + */ +public class PrivateKeyInfoFactory +{ + /** + * Create a PrivateKeyInfo representation of a private key. + * + * @param privateKey the SubjectPublicKeyInfo encoding + * @return the appropriate key parameter + * @throws java.io.IOException on an error encoding the key + */ + public static PrivateKeyInfo createPrivateKeyInfo(AsymmetricKeyParameter privateKey) 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())); + } + 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())); + } + else if (privateKey instanceof ECPrivateKeyParameters) + { + ECPrivateKeyParameters priv = (ECPrivateKeyParameters)privateKey; + ECDomainParameters domainParams = priv.getParameters(); + ASN1Encodable params; + + if (domainParams == null) + { + params = new X962Parameters(DERNull.INSTANCE); // Implicitly CA + } + else if (domainParams instanceof ECNamedDomainParameters) + { + params = new X962Parameters(((ECNamedDomainParameters)domainParams).getName()); + } + else + { + X9ECParameters ecP = new X9ECParameters( + domainParams.getCurve(), + domainParams.getG(), + domainParams.getN(), + domainParams.getH(), + domainParams.getSeed()); + + params = new X962Parameters(ecP); + } + + return new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params), new ECPrivateKey(priv.getD(), params)); + } + else + { + throw new IOException("key parameters not recognised."); + } + } +} diff --git a/core/src/main/java/org/spongycastle/crypto/util/PublicKeyFactory.java b/core/src/main/java/org/spongycastle/crypto/util/PublicKeyFactory.java new file mode 100644 index 00000000..ec588f46 --- /dev/null +++ b/core/src/main/java/org/spongycastle/crypto/util/PublicKeyFactory.java @@ -0,0 +1,195 @@ +package org.spongycastle.crypto.util; + +import java.io.IOException; +import java.io.InputStream; +import java.math.BigInteger; + +import org.spongycastle.asn1.ASN1Encodable; +import org.spongycastle.asn1.ASN1InputStream; +import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.ASN1OctetString; +import org.spongycastle.asn1.ASN1Primitive; +import org.spongycastle.asn1.DEROctetString; +import org.spongycastle.asn1.oiw.ElGamalParameter; +import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; +import org.spongycastle.asn1.pkcs.DHParameter; +import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.spongycastle.asn1.pkcs.RSAPublicKey; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.asn1.x509.DSAParameter; +import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; +import org.spongycastle.asn1.x509.X509ObjectIdentifiers; +import org.spongycastle.asn1.x9.DHDomainParameters; +import org.spongycastle.asn1.x9.DHPublicKey; +import org.spongycastle.asn1.x9.DHValidationParms; +import org.spongycastle.asn1.x9.ECNamedCurveTable; +import org.spongycastle.asn1.x9.X962Parameters; +import org.spongycastle.asn1.x9.X9ECParameters; +import org.spongycastle.asn1.x9.X9ECPoint; +import org.spongycastle.asn1.x9.X9ObjectIdentifiers; +import org.spongycastle.crypto.ec.CustomNamedCurves; +import org.spongycastle.crypto.params.AsymmetricKeyParameter; +import org.spongycastle.crypto.params.DHParameters; +import org.spongycastle.crypto.params.DHPublicKeyParameters; +import org.spongycastle.crypto.params.DHValidationParameters; +import org.spongycastle.crypto.params.DSAParameters; +import org.spongycastle.crypto.params.DSAPublicKeyParameters; +import org.spongycastle.crypto.params.ECDomainParameters; +import org.spongycastle.crypto.params.ECNamedDomainParameters; +import org.spongycastle.crypto.params.ECPublicKeyParameters; +import org.spongycastle.crypto.params.ElGamalParameters; +import org.spongycastle.crypto.params.ElGamalPublicKeyParameters; +import org.spongycastle.crypto.params.RSAKeyParameters; + +/** + * Factory to create asymmetric public key parameters for asymmetric ciphers from range of + * ASN.1 encoded SubjectPublicKeyInfo objects. + */ +public class PublicKeyFactory +{ + /** + * 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 + { + AlgorithmIdentifier algId = keyInfo.getAlgorithm(); + + if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.rsaEncryption) + || algId.getAlgorithm().equals(X509ObjectIdentifiers.id_ea_rsa)) + { + RSAPublicKey pubKey = RSAPublicKey.getInstance(keyInfo.parsePublicKey()); + + return new RSAKeyParameters(false, pubKey.getModulus(), pubKey.getPublicExponent()); + } + else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.dhpublicnumber)) + { + DHPublicKey dhPublicKey = DHPublicKey.getInstance(keyInfo.parsePublicKey()); + + BigInteger y = dhPublicKey.getY().getValue(); + + DHDomainParameters dhParams = DHDomainParameters.getInstance(algId.getParameters()); + + BigInteger p = dhParams.getP().getValue(); + BigInteger g = dhParams.getG().getValue(); + BigInteger q = dhParams.getQ().getValue(); + + BigInteger j = null; + if (dhParams.getJ() != null) + { + j = dhParams.getJ().getValue(); + } + + DHValidationParameters validation = null; + DHValidationParms dhValidationParms = dhParams.getValidationParms(); + if (dhValidationParms != null) + { + byte[] seed = dhValidationParms.getSeed().getBytes(); + BigInteger pgenCounter = dhValidationParms.getPgenCounter().getValue(); + + // TODO Check pgenCounter size? + + validation = new DHValidationParameters(seed, pgenCounter.intValue()); + } + + return new DHPublicKeyParameters(y, new DHParameters(p, g, q, j, validation)); + } + else if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.dhKeyAgreement)) + { + DHParameter params = DHParameter.getInstance(algId.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); + } + else if (algId.getAlgorithm().equals(OIWObjectIdentifiers.elGamalAlgorithm)) + { + ElGamalParameter params = ElGamalParameter.getInstance(algId.getParameters()); + ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey(); + + return new ElGamalPublicKeyParameters(derY.getValue(), new ElGamalParameters( + params.getP(), params.getG())); + } + else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_dsa) + || algId.getAlgorithm().equals(OIWObjectIdentifiers.dsaWithSHA1)) + { + ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey(); + ASN1Encodable de = algId.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); + } + else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_ecPublicKey)) + { + X962Parameters params = X962Parameters.getInstance(algId.getParameters()); + + X9ECParameters x9; + ECDomainParameters dParams; + + if (params.isNamedCurve()) + { + ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)params.getParameters(); + + 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 + { + x9 = X9ECParameters.getInstance(params.getParameters()); + dParams = new ECDomainParameters( + x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed()); + } + + ASN1OctetString key = new DEROctetString(keyInfo.getPublicKeyData().getBytes()); + X9ECPoint derQ = new X9ECPoint(x9.getCurve(), key); + + return new ECPublicKeyParameters(derQ.getPoint(), dParams); + } + else + { + throw new RuntimeException("algorithm identifier in key not recognised"); + } + } +} diff --git a/core/src/main/java/org/spongycastle/crypto/util/SubjectPublicKeyInfoFactory.java b/core/src/main/java/org/spongycastle/crypto/util/SubjectPublicKeyInfoFactory.java new file mode 100644 index 00000000..749de7f3 --- /dev/null +++ b/core/src/main/java/org/spongycastle/crypto/util/SubjectPublicKeyInfoFactory.java @@ -0,0 +1,85 @@ +package org.spongycastle.crypto.util; + +import java.io.IOException; + +import org.spongycastle.asn1.ASN1Encodable; +import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.ASN1OctetString; +import org.spongycastle.asn1.DERNull; +import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.spongycastle.asn1.pkcs.RSAPublicKey; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; +import org.spongycastle.asn1.x9.X962Parameters; +import org.spongycastle.asn1.x9.X9ECParameters; +import org.spongycastle.asn1.x9.X9ECPoint; +import org.spongycastle.asn1.x9.X9ObjectIdentifiers; +import org.spongycastle.crypto.params.AsymmetricKeyParameter; +import org.spongycastle.crypto.params.DSAPublicKeyParameters; +import org.spongycastle.crypto.params.ECDomainParameters; +import org.spongycastle.crypto.params.ECNamedDomainParameters; +import org.spongycastle.crypto.params.ECPublicKeyParameters; +import org.spongycastle.crypto.params.RSAKeyParameters; + +/** + * Factory to create ASN.1 subject public key info objects from lightweight public keys. + */ +public class SubjectPublicKeyInfoFactory +{ + /** + * Create a SubjectPublicKeyInfo public key. + * + * @param publicKey the SubjectPublicKeyInfo encoding + * @return the appropriate key parameter + * @throws java.io.IOException on an error encoding the key + */ + public static SubjectPublicKeyInfo createSubjectPublicKeyInfo(AsymmetricKeyParameter publicKey) throws IOException + { + if (publicKey instanceof RSAKeyParameters) + { + RSAKeyParameters pub = (RSAKeyParameters)publicKey; + + return new SubjectPublicKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE), new RSAPublicKey(pub.getModulus(), pub.getExponent())); + } + else if (publicKey instanceof DSAPublicKeyParameters) + { + DSAPublicKeyParameters pub = (DSAPublicKeyParameters)publicKey; + + return new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa), new ASN1Integer(pub.getY())); + } + else if (publicKey instanceof ECPublicKeyParameters) + { + ECPublicKeyParameters pub = (ECPublicKeyParameters)publicKey; + ECDomainParameters domainParams = pub.getParameters(); + ASN1Encodable params; + + if (domainParams == null) + { + params = new X962Parameters(DERNull.INSTANCE); // Implicitly CA + } + else if (domainParams instanceof ECNamedDomainParameters) + { + params = new X962Parameters(((ECNamedDomainParameters)domainParams).getName()); + } + else + { + X9ECParameters ecP = new X9ECParameters( + domainParams.getCurve(), + domainParams.getG(), + domainParams.getN(), + domainParams.getH(), + domainParams.getSeed()); + + params = new X962Parameters(ecP); + } + + ASN1OctetString p = (ASN1OctetString)new X9ECPoint(pub.getQ()).toASN1Primitive(); + + return new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params), p.getOctets()); + } + else + { + throw new IOException("key parameters not recognised."); + } + } +} |