diff options
Diffstat (limited to 'prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa')
8 files changed, 1157 insertions, 0 deletions
diff --git a/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/AlgorithmParameterGeneratorSpi.java b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/AlgorithmParameterGeneratorSpi.java new file mode 100644 index 00000000..9bbdca3d --- /dev/null +++ b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/AlgorithmParameterGeneratorSpi.java @@ -0,0 +1,103 @@ +package org.spongycastle.jcajce.provider.asymmetric.dsa; + +import java.security.AlgorithmParameters; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidParameterException; +import java.security.SecureRandom; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.DSAParameterSpec; + +import org.spongycastle.crypto.digests.SHA256Digest; +import org.spongycastle.crypto.generators.DSAParametersGenerator; +import org.spongycastle.crypto.params.DSAParameterGenerationParameters; +import org.spongycastle.crypto.params.DSAParameters; +import org.spongycastle.jce.provider.BouncyCastleProvider; + +public class AlgorithmParameterGeneratorSpi + extends java.security.AlgorithmParameterGeneratorSpi +{ + protected SecureRandom random; + protected int strength = 1024; + protected DSAParameterGenerationParameters params; + + protected void engineInit( + int strength, + SecureRandom random) + { + if (strength < 512 || strength > 3072) + { + throw new InvalidParameterException("strength must be from 512 - 3072"); + } + + if (strength <= 1024 && strength % 64 != 0) + { + throw new InvalidParameterException("strength must be a multiple of 64 below 1024 bits."); + } + + if (strength > 1024 && strength % 1024 != 0) + { + throw new InvalidParameterException("strength must be a multiple of 1024 above 1024 bits."); + } + + this.strength = strength; + this.random = random; + } + + protected void engineInit( + AlgorithmParameterSpec genParamSpec, + SecureRandom random) + throws InvalidAlgorithmParameterException + { + throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for DSA parameter generation."); + } + + protected AlgorithmParameters engineGenerateParameters() + { + DSAParametersGenerator pGen; + + if (strength <= 1024) + { + pGen = new DSAParametersGenerator(); + } + else + { + pGen = new DSAParametersGenerator(new SHA256Digest()); + } + + if (random == null) + { + random = new SecureRandom(); + } + + if (strength == 1024) + { + params = new DSAParameterGenerationParameters(1024, 160, 80, random); + pGen.init(params); + } + else if (strength > 1024) + { + params = new DSAParameterGenerationParameters(strength, 256, 80, random); + pGen.init(params); + } + else + { + pGen.init(strength, 20, random); + } + + DSAParameters p = pGen.generateParameters(); + + AlgorithmParameters params; + + try + { + params = AlgorithmParameters.getInstance("DSA", BouncyCastleProvider.PROVIDER_NAME); + params.init(new DSAParameterSpec(p.getP(), p.getQ(), p.getG())); + } + catch (Exception e) + { + throw new RuntimeException(e.getMessage()); + } + + return params; + } +} diff --git a/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/AlgorithmParametersSpi.java b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/AlgorithmParametersSpi.java new file mode 100644 index 00000000..2ace504d --- /dev/null +++ b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/AlgorithmParametersSpi.java @@ -0,0 +1,132 @@ +package org.spongycastle.jcajce.provider.asymmetric.dsa; + +import java.io.IOException; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.DSAParameterSpec; +import java.security.spec.InvalidParameterSpecException; + +import org.spongycastle.asn1.ASN1Encoding; +import org.spongycastle.asn1.ASN1Primitive; +import org.spongycastle.asn1.x509.DSAParameter; + +public class AlgorithmParametersSpi + extends java.security.AlgorithmParametersSpi +{ + DSAParameterSpec currentSpec; + + protected boolean isASN1FormatString(String format) + { + return format == null || format.equals("ASN.1"); + } + + protected AlgorithmParameterSpec engineGetParameterSpec( + Class paramSpec) + throws InvalidParameterSpecException + { + if (paramSpec == null) + { + throw new NullPointerException("argument to getParameterSpec must not be null"); + } + + return localEngineGetParameterSpec(paramSpec); + } + + /** + * Return the X.509 ASN.1 structure DSAParameter. + * <p/> + * <pre> + * DSAParameter ::= SEQUENCE { + * prime INTEGER, -- p + * subprime INTEGER, -- q + * base INTEGER, -- g} + * </pre> + */ + protected byte[] engineGetEncoded() + { + DSAParameter dsaP = new DSAParameter(currentSpec.getP(), currentSpec.getQ(), currentSpec.getG()); + + try + { + return dsaP.getEncoded(ASN1Encoding.DER); + } + catch (IOException e) + { + throw new RuntimeException("Error encoding DSAParameters"); + } + } + + protected byte[] engineGetEncoded( + String format) + { + if (isASN1FormatString(format)) + { + return engineGetEncoded(); + } + + return null; + } + + protected AlgorithmParameterSpec localEngineGetParameterSpec( + Class paramSpec) + throws InvalidParameterSpecException + { + if (paramSpec == DSAParameterSpec.class) + { + return currentSpec; + } + + throw new InvalidParameterSpecException("unknown parameter spec passed to DSA parameters object."); + } + + protected void engineInit( + AlgorithmParameterSpec paramSpec) + throws InvalidParameterSpecException + { + if (!(paramSpec instanceof DSAParameterSpec)) + { + throw new InvalidParameterSpecException("DSAParameterSpec required to initialise a DSA algorithm parameters object"); + } + + this.currentSpec = (DSAParameterSpec)paramSpec; + } + + protected void engineInit( + byte[] params) + throws IOException + { + try + { + DSAParameter dsaP = DSAParameter.getInstance(ASN1Primitive.fromByteArray(params)); + + currentSpec = new DSAParameterSpec(dsaP.getP(), dsaP.getQ(), dsaP.getG()); + } + catch (ClassCastException e) + { + throw new IOException("Not a valid DSA Parameter encoding."); + } + catch (ArrayIndexOutOfBoundsException e) + { + throw new IOException("Not a valid DSA Parameter encoding."); + } + } + + protected void engineInit( + byte[] params, + String format) + throws IOException + { + if (isASN1FormatString(format) || format.equalsIgnoreCase("X.509")) + { + engineInit(params); + } + else + { + throw new IOException("Unknown parameter format " + format); + } + } + + protected String engineToString() + { + return "DSA Parameters"; + } +} diff --git a/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/BCDSAPrivateKey.java b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/BCDSAPrivateKey.java new file mode 100644 index 00000000..bcd3dfe8 --- /dev/null +++ b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/BCDSAPrivateKey.java @@ -0,0 +1,167 @@ +package org.spongycastle.jcajce.provider.asymmetric.dsa; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.math.BigInteger; +import java.security.interfaces.DSAParams; +import java.security.interfaces.DSAPrivateKey; +import java.security.spec.DSAParameterSpec; +import java.security.spec.DSAPrivateKeySpec; +import java.util.Enumeration; + +import org.spongycastle.asn1.ASN1Encodable; +import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.pkcs.PrivateKeyInfo; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.asn1.x509.DSAParameter; +import org.spongycastle.asn1.x9.X9ObjectIdentifiers; +import org.spongycastle.crypto.params.DSAPrivateKeyParameters; +import org.spongycastle.jcajce.provider.asymmetric.util.KeyUtil; +import org.spongycastle.jcajce.provider.asymmetric.util.PKCS12BagAttributeCarrierImpl; +import org.spongycastle.jce.interfaces.PKCS12BagAttributeCarrier; + +public class BCDSAPrivateKey + implements DSAPrivateKey, PKCS12BagAttributeCarrier +{ + private static final long serialVersionUID = -4677259546958385734L; + + private BigInteger x; + private transient DSAParams dsaSpec; + + private transient PKCS12BagAttributeCarrierImpl attrCarrier = new PKCS12BagAttributeCarrierImpl(); + + protected BCDSAPrivateKey() + { + } + + BCDSAPrivateKey( + DSAPrivateKey key) + { + this.x = key.getX(); + this.dsaSpec = key.getParams(); + } + + BCDSAPrivateKey( + DSAPrivateKeySpec spec) + { + this.x = spec.getX(); + this.dsaSpec = new DSAParameterSpec(spec.getP(), spec.getQ(), spec.getG()); + } + + public BCDSAPrivateKey( + PrivateKeyInfo info) + throws IOException + { + DSAParameter params = DSAParameter.getInstance(info.getPrivateKeyAlgorithm().getParameters()); + ASN1Integer derX = (ASN1Integer)info.parsePrivateKey(); + + this.x = derX.getValue(); + this.dsaSpec = new DSAParameterSpec(params.getP(), params.getQ(), params.getG()); + } + + BCDSAPrivateKey( + DSAPrivateKeyParameters params) + { + this.x = params.getX(); + this.dsaSpec = new DSAParameterSpec(params.getParameters().getP(), params.getParameters().getQ(), params.getParameters().getG()); + } + + public String getAlgorithm() + { + return "DSA"; + } + + /** + * return the encoding format we produce in getEncoded(). + * + * @return the string "PKCS#8" + */ + public String getFormat() + { + return "PKCS#8"; + } + + /** + * Return a PKCS8 representation of the key. The sequence returned + * represents a full PrivateKeyInfo object. + * + * @return a PKCS8 representation of the key. + */ + public byte[] getEncoded() + { + return KeyUtil.getEncodedPrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa, new DSAParameter(dsaSpec.getP(), dsaSpec.getQ(), dsaSpec.getG()).toASN1Primitive()), new ASN1Integer(getX())); + } + + public DSAParams getParams() + { + return dsaSpec; + } + + public BigInteger getX() + { + return x; + } + + public boolean equals( + Object o) + { + if (!(o instanceof DSAPrivateKey)) + { + return false; + } + + DSAPrivateKey other = (DSAPrivateKey)o; + + return this.getX().equals(other.getX()) + && this.getParams().getG().equals(other.getParams().getG()) + && this.getParams().getP().equals(other.getParams().getP()) + && this.getParams().getQ().equals(other.getParams().getQ()); + } + + public int hashCode() + { + return this.getX().hashCode() ^ this.getParams().getG().hashCode() + ^ this.getParams().getP().hashCode() ^ this.getParams().getQ().hashCode(); + } + + public void setBagAttribute( + ASN1ObjectIdentifier oid, + ASN1Encodable attribute) + { + attrCarrier.setBagAttribute(oid, attribute); + } + + public ASN1Encodable getBagAttribute( + ASN1ObjectIdentifier oid) + { + return attrCarrier.getBagAttribute(oid); + } + + public Enumeration getBagAttributeKeys() + { + return attrCarrier.getBagAttributeKeys(); + } + + private void readObject( + ObjectInputStream in) + throws IOException, ClassNotFoundException + { + in.defaultReadObject(); + + this.dsaSpec = new DSAParameterSpec((BigInteger)in.readObject(), (BigInteger)in.readObject(), (BigInteger)in.readObject()); + this.attrCarrier = new PKCS12BagAttributeCarrierImpl(); + } + + private void writeObject( + ObjectOutputStream out) + throws IOException + { + out.defaultWriteObject(); + + out.writeObject(dsaSpec.getP()); + out.writeObject(dsaSpec.getQ()); + out.writeObject(dsaSpec.getG()); + } +} diff --git a/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/BCDSAPublicKey.java b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/BCDSAPublicKey.java new file mode 100644 index 00000000..f4ccaeae --- /dev/null +++ b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/BCDSAPublicKey.java @@ -0,0 +1,171 @@ +package org.spongycastle.jcajce.provider.asymmetric.dsa; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.math.BigInteger; +import java.security.interfaces.DSAParams; +import java.security.interfaces.DSAPublicKey; +import java.security.spec.DSAParameterSpec; +import java.security.spec.DSAPublicKeySpec; + +import org.spongycastle.asn1.ASN1Encodable; +import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.DERNull; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.asn1.x509.DSAParameter; +import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; +import org.spongycastle.asn1.x9.X9ObjectIdentifiers; +import org.spongycastle.crypto.params.DSAPublicKeyParameters; +import org.spongycastle.jcajce.provider.asymmetric.util.KeyUtil; + +public class BCDSAPublicKey + implements DSAPublicKey +{ + private static final long serialVersionUID = 1752452449903495175L; + + private BigInteger y; + private transient DSAParams dsaSpec; + + BCDSAPublicKey( + DSAPublicKeySpec spec) + { + this.y = spec.getY(); + this.dsaSpec = new DSAParameterSpec(spec.getP(), spec.getQ(), spec.getG()); + } + + BCDSAPublicKey( + DSAPublicKey key) + { + this.y = key.getY(); + this.dsaSpec = key.getParams(); + } + + BCDSAPublicKey( + DSAPublicKeyParameters params) + { + this.y = params.getY(); + this.dsaSpec = new DSAParameterSpec(params.getParameters().getP(), params.getParameters().getQ(), params.getParameters().getG()); + } + + BCDSAPublicKey( + BigInteger y, + DSAParameterSpec dsaSpec) + { + this.y = y; + this.dsaSpec = dsaSpec; + } + + public BCDSAPublicKey( + SubjectPublicKeyInfo info) + { + + ASN1Integer derY; + + try + { + derY = (ASN1Integer)info.parsePublicKey(); + } + catch (IOException e) + { + throw new IllegalArgumentException("invalid info structure in DSA public key"); + } + + this.y = derY.getValue(); + + if (isNotNull(info.getAlgorithm().getParameters())) + { + DSAParameter params = DSAParameter.getInstance(info.getAlgorithm().getParameters()); + + this.dsaSpec = new DSAParameterSpec(params.getP(), params.getQ(), params.getG()); + } + } + + private boolean isNotNull(ASN1Encodable parameters) + { + return parameters != null && !DERNull.INSTANCE.equals(parameters.toASN1Primitive()); + } + + public String getAlgorithm() + { + return "DSA"; + } + + public String getFormat() + { + return "X.509"; + } + + public byte[] getEncoded() + { + if (dsaSpec == null) + { + return KeyUtil.getEncodedSubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa), new ASN1Integer(y)); + } + + return KeyUtil.getEncodedSubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa, new DSAParameter(dsaSpec.getP(), dsaSpec.getQ(), dsaSpec.getG()).toASN1Primitive()), new ASN1Integer(y)); + } + + public DSAParams getParams() + { + return dsaSpec; + } + + public BigInteger getY() + { + return y; + } + + public String toString() + { + StringBuffer buf = new StringBuffer(); + String nl = System.getProperty("line.separator"); + + buf.append("DSA Public Key").append(nl); + buf.append(" y: ").append(this.getY().toString(16)).append(nl); + + return buf.toString(); + } + + public int hashCode() + { + return this.getY().hashCode() ^ this.getParams().getG().hashCode() + ^ this.getParams().getP().hashCode() ^ this.getParams().getQ().hashCode(); + } + + public boolean equals( + Object o) + { + if (!(o instanceof DSAPublicKey)) + { + return false; + } + + DSAPublicKey other = (DSAPublicKey)o; + + return this.getY().equals(other.getY()) + && this.getParams().getG().equals(other.getParams().getG()) + && this.getParams().getP().equals(other.getParams().getP()) + && this.getParams().getQ().equals(other.getParams().getQ()); + } + + private void readObject( + ObjectInputStream in) + throws IOException, ClassNotFoundException + { + in.defaultReadObject(); + + this.dsaSpec = new DSAParameterSpec((BigInteger)in.readObject(), (BigInteger)in.readObject(), (BigInteger)in.readObject()); + } + + private void writeObject( + ObjectOutputStream out) + throws IOException + { + out.defaultWriteObject(); + + out.writeObject(dsaSpec.getP()); + out.writeObject(dsaSpec.getQ()); + out.writeObject(dsaSpec.getG()); + } +} diff --git a/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/DSASigner.java b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/DSASigner.java new file mode 100644 index 00000000..c2b9e5d3 --- /dev/null +++ b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/DSASigner.java @@ -0,0 +1,313 @@ +package org.spongycastle.jcajce.provider.asymmetric.dsa; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.InvalidKeyException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.SignatureException; +import java.security.SignatureSpi; +import java.security.interfaces.DSAKey; +import java.security.spec.AlgorithmParameterSpec; + +import org.spongycastle.asn1.ASN1Encoding; +import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.ASN1Primitive; +import org.spongycastle.asn1.ASN1Sequence; +import org.spongycastle.asn1.DERSequence; +import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; +import org.spongycastle.asn1.x509.X509ObjectIdentifiers; +import org.spongycastle.crypto.CipherParameters; +import org.spongycastle.crypto.DSA; +import org.spongycastle.crypto.Digest; +import org.spongycastle.crypto.digests.NullDigest; +import org.spongycastle.crypto.digests.SHA1Digest; +import org.spongycastle.crypto.digests.SHA224Digest; +import org.spongycastle.crypto.digests.SHA256Digest; +import org.spongycastle.crypto.digests.SHA384Digest; +import org.spongycastle.crypto.digests.SHA512Digest; +import org.spongycastle.crypto.params.ParametersWithRandom; +import org.spongycastle.crypto.signers.HMacDSAKCalculator; + +public class DSASigner + extends SignatureSpi + implements PKCSObjectIdentifiers, X509ObjectIdentifiers +{ + private Digest digest; + private DSA signer; + private SecureRandom random; + + protected DSASigner( + Digest digest, + DSA signer) + { + this.digest = digest; + this.signer = signer; + } + + protected void engineInitVerify( + PublicKey publicKey) + throws InvalidKeyException + { + CipherParameters param; + + if (publicKey instanceof DSAKey) + { + param = DSAUtil.generatePublicKeyParameter(publicKey); + } + else + { + try + { + byte[] bytes = publicKey.getEncoded(); + + publicKey = new BCDSAPublicKey(SubjectPublicKeyInfo.getInstance(bytes)); + + if (publicKey instanceof DSAKey) + { + param = DSAUtil.generatePublicKeyParameter(publicKey); + } + else + { + throw new InvalidKeyException("can't recognise key type in DSA based signer"); + } + } + catch (Exception e) + { + throw new InvalidKeyException("can't recognise key type in DSA based signer"); + } + } + + digest.reset(); + signer.init(false, param); + } + + protected void engineInitSign( + PrivateKey privateKey, + SecureRandom random) + throws InvalidKeyException + { + this.random = random; + engineInitSign(privateKey); + } + + protected void engineInitSign( + PrivateKey privateKey) + throws InvalidKeyException + { + CipherParameters param; + + param = DSAUtil.generatePrivateKeyParameter(privateKey); + + if (random != null) + { + param = new ParametersWithRandom(param, random); + } + + digest.reset(); + signer.init(true, param); + } + + protected void engineUpdate( + byte b) + throws SignatureException + { + digest.update(b); + } + + protected void engineUpdate( + byte[] b, + int off, + int len) + throws SignatureException + { + digest.update(b, off, len); + } + + protected byte[] engineSign() + throws SignatureException + { + byte[] hash = new byte[digest.getDigestSize()]; + + digest.doFinal(hash, 0); + + try + { + BigInteger[] sig = signer.generateSignature(hash); + + return derEncode(sig[0], sig[1]); + } + catch (Exception e) + { + throw new SignatureException(e.toString()); + } + } + + protected boolean engineVerify( + byte[] sigBytes) + throws SignatureException + { + byte[] hash = new byte[digest.getDigestSize()]; + + digest.doFinal(hash, 0); + + BigInteger[] sig; + + try + { + sig = derDecode(sigBytes); + } + catch (Exception e) + { + throw new SignatureException("error decoding signature bytes."); + } + + return signer.verifySignature(hash, sig[0], sig[1]); + } + + protected void engineSetParameter( + AlgorithmParameterSpec params) + { + throw new UnsupportedOperationException("engineSetParameter unsupported"); + } + + /** + * @deprecated replaced with <a href = "#engineSetParameter(java.security.spec.AlgorithmParameterSpec)"> + */ + protected void engineSetParameter( + String param, + Object value) + { + throw new UnsupportedOperationException("engineSetParameter unsupported"); + } + + /** + * @deprecated + */ + protected Object engineGetParameter( + String param) + { + throw new UnsupportedOperationException("engineSetParameter unsupported"); + } + + private byte[] derEncode( + BigInteger r, + BigInteger s) + throws IOException + { + ASN1Integer[] rs = new ASN1Integer[]{ new ASN1Integer(r), new ASN1Integer(s) }; + return new DERSequence(rs).getEncoded(ASN1Encoding.DER); + } + + private BigInteger[] derDecode( + byte[] encoding) + throws IOException + { + ASN1Sequence s = (ASN1Sequence)ASN1Primitive.fromByteArray(encoding); + return new BigInteger[]{ + ((ASN1Integer)s.getObjectAt(0)).getValue(), + ((ASN1Integer)s.getObjectAt(1)).getValue() + }; + } + + static public class stdDSA + extends DSASigner + { + public stdDSA() + { + super(new SHA1Digest(), new org.spongycastle.crypto.signers.DSASigner()); + } + } + + static public class detDSA + extends DSASigner + { + public detDSA() + { + super(new SHA1Digest(), new org.spongycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(new SHA1Digest()))); + } + } + + static public class dsa224 + extends DSASigner + { + public dsa224() + { + super(new SHA224Digest(), new org.spongycastle.crypto.signers.DSASigner()); + } + } + + static public class detDSA224 + extends DSASigner + { + public detDSA224() + { + super(new SHA224Digest(), new org.spongycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(new SHA224Digest()))); + } + } + + static public class dsa256 + extends DSASigner + { + public dsa256() + { + super(new SHA256Digest(), new org.spongycastle.crypto.signers.DSASigner()); + } + } + + static public class detDSA256 + extends DSASigner + { + public detDSA256() + { + super(new SHA256Digest(), new org.spongycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(new SHA256Digest()))); + } + } + + static public class dsa384 + extends DSASigner + { + public dsa384() + { + super(new SHA384Digest(), new org.spongycastle.crypto.signers.DSASigner()); + } + } + + static public class detDSA384 + extends DSASigner + { + public detDSA384() + { + super(new SHA384Digest(), new org.spongycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(new SHA384Digest()))); + } + } + + static public class dsa512 + extends DSASigner + { + public dsa512() + { + super(new SHA512Digest(), new org.spongycastle.crypto.signers.DSASigner()); + } + } + + static public class detDSA512 + extends DSASigner + { + public detDSA512() + { + super(new SHA512Digest(), new org.spongycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(new SHA512Digest()))); + } + } + + static public class noneDSA + extends DSASigner + { + public noneDSA() + { + super(new NullDigest(), new org.spongycastle.crypto.signers.DSASigner()); + } + } +} diff --git a/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/DSAUtil.java b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/DSAUtil.java new file mode 100644 index 00000000..ae627195 --- /dev/null +++ b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/DSAUtil.java @@ -0,0 +1,72 @@ +package org.spongycastle.jcajce.provider.asymmetric.dsa; + +import java.security.InvalidKeyException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.interfaces.DSAPrivateKey; +import java.security.interfaces.DSAPublicKey; + +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; +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.DSAPublicKeyParameters; + +/** + * utility class for converting jce/jca DSA objects + * objects into their org.spongycastle.crypto counterparts. + */ +public class DSAUtil +{ + public static final ASN1ObjectIdentifier[] dsaOids = + { + X9ObjectIdentifiers.id_dsa, + OIWObjectIdentifiers.dsaWithSHA1 + }; + + public static boolean isDsaOid( + ASN1ObjectIdentifier algOid) + { + for (int i = 0; i != dsaOids.length; i++) + { + if (algOid.equals(dsaOids[i])) + { + return true; + } + } + + return false; + } + + static public AsymmetricKeyParameter generatePublicKeyParameter( + PublicKey key) + throws InvalidKeyException + { + if (key instanceof DSAPublicKey) + { + DSAPublicKey k = (DSAPublicKey)key; + + return new DSAPublicKeyParameters(k.getY(), + new DSAParameters(k.getParams().getP(), k.getParams().getQ(), k.getParams().getG())); + } + + throw new InvalidKeyException("can't identify DSA public key: " + key.getClass().getName()); + } + + static public AsymmetricKeyParameter generatePrivateKeyParameter( + PrivateKey key) + throws InvalidKeyException + { + if (key instanceof DSAPrivateKey) + { + DSAPrivateKey k = (DSAPrivateKey)key; + + return new DSAPrivateKeyParameters(k.getX(), + new DSAParameters(k.getParams().getP(), k.getParams().getQ(), k.getParams().getG())); + } + + throw new InvalidKeyException("can't identify DSA private key."); + } +} diff --git a/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/KeyFactorySpi.java b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/KeyFactorySpi.java new file mode 100644 index 00000000..2b5c693e --- /dev/null +++ b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/KeyFactorySpi.java @@ -0,0 +1,117 @@ +package org.spongycastle.jcajce.provider.asymmetric.dsa; + +import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.interfaces.DSAPrivateKey; +import java.security.interfaces.DSAPublicKey; +import java.security.spec.DSAPrivateKeySpec; +import java.security.spec.DSAPublicKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; + +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.pkcs.PrivateKeyInfo; +import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; +import org.spongycastle.jcajce.provider.asymmetric.util.BaseKeyFactorySpi; + +public class KeyFactorySpi + extends BaseKeyFactorySpi +{ + public KeyFactorySpi() + { + } + + protected KeySpec engineGetKeySpec( + Key key, + Class spec) + throws InvalidKeySpecException + { + if (spec.isAssignableFrom(DSAPublicKeySpec.class) && key instanceof DSAPublicKey) + { + DSAPublicKey k = (DSAPublicKey)key; + + return new DSAPublicKeySpec(k.getY(), k.getParams().getP(), k.getParams().getQ(), k.getParams().getG()); + } + else if (spec.isAssignableFrom(DSAPrivateKeySpec.class) && key instanceof java.security.interfaces.DSAPrivateKey) + { + java.security.interfaces.DSAPrivateKey k = (java.security.interfaces.DSAPrivateKey)key; + + return new DSAPrivateKeySpec(k.getX(), k.getParams().getP(), k.getParams().getQ(), k.getParams().getG()); + } + + return super.engineGetKeySpec(key, spec); + } + + protected Key engineTranslateKey( + Key key) + throws InvalidKeyException + { + if (key instanceof DSAPublicKey) + { + return new BCDSAPublicKey((DSAPublicKey)key); + } + else if (key instanceof DSAPrivateKey) + { + return new BCDSAPrivateKey((DSAPrivateKey)key); + } + + throw new InvalidKeyException("key type unknown"); + } + + public PrivateKey generatePrivate(PrivateKeyInfo keyInfo) + throws IOException + { + ASN1ObjectIdentifier algOid = keyInfo.getPrivateKeyAlgorithm().getAlgorithm(); + + if (DSAUtil.isDsaOid(algOid)) + { + return new BCDSAPrivateKey(keyInfo); + } + else + { + throw new IOException("algorithm identifier " + algOid + " in key not recognised"); + } + } + + public PublicKey generatePublic(SubjectPublicKeyInfo keyInfo) + throws IOException + { + ASN1ObjectIdentifier algOid = keyInfo.getAlgorithm().getAlgorithm(); + + if (DSAUtil.isDsaOid(algOid)) + { + return new BCDSAPublicKey(keyInfo); + } + else + { + throw new IOException("algorithm identifier " + algOid + " in key not recognised"); + } + } + + protected PrivateKey engineGeneratePrivate( + KeySpec keySpec) + throws InvalidKeySpecException + { + if (keySpec instanceof DSAPrivateKeySpec) + { + return new BCDSAPrivateKey((DSAPrivateKeySpec)keySpec); + } + + return super.engineGeneratePrivate(keySpec); + } + + protected PublicKey engineGeneratePublic( + KeySpec keySpec) + throws InvalidKeySpecException + { + if (keySpec instanceof DSAPublicKeySpec) + { + return new BCDSAPublicKey((DSAPublicKeySpec)keySpec); + } + + return super.engineGeneratePublic(keySpec); + } +} diff --git a/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/KeyPairGeneratorSpi.java b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/KeyPairGeneratorSpi.java new file mode 100644 index 00000000..c67c417f --- /dev/null +++ b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/KeyPairGeneratorSpi.java @@ -0,0 +1,82 @@ +package org.spongycastle.jcajce.provider.asymmetric.dsa; + +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidParameterException; +import java.security.KeyPair; +import java.security.SecureRandom; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.DSAParameterSpec; + +import org.spongycastle.crypto.AsymmetricCipherKeyPair; +import org.spongycastle.crypto.generators.DSAKeyPairGenerator; +import org.spongycastle.crypto.generators.DSAParametersGenerator; +import org.spongycastle.crypto.params.DSAKeyGenerationParameters; +import org.spongycastle.crypto.params.DSAParameters; +import org.spongycastle.crypto.params.DSAPrivateKeyParameters; +import org.spongycastle.crypto.params.DSAPublicKeyParameters; + +public class KeyPairGeneratorSpi + extends java.security.KeyPairGenerator +{ + DSAKeyGenerationParameters param; + DSAKeyPairGenerator engine = new DSAKeyPairGenerator(); + int strength = 1024; + int certainty = 20; + SecureRandom random = new SecureRandom(); + boolean initialised = false; + + public KeyPairGeneratorSpi() + { + super("DSA"); + } + + public void initialize( + int strength, + SecureRandom random) + { + if (strength < 512 || strength > 4096 || ((strength < 1024) && strength % 64 != 0) || (strength >= 1024 && strength % 1024 != 0)) + { + throw new InvalidParameterException("strength must be from 512 - 4096 and a multiple of 1024 above 1024"); + } + + this.strength = strength; + this.random = random; + } + + public void initialize( + AlgorithmParameterSpec params, + SecureRandom random) + throws InvalidAlgorithmParameterException + { + if (!(params instanceof DSAParameterSpec)) + { + throw new InvalidAlgorithmParameterException("parameter object not a DSAParameterSpec"); + } + DSAParameterSpec dsaParams = (DSAParameterSpec)params; + + param = new DSAKeyGenerationParameters(random, new DSAParameters(dsaParams.getP(), dsaParams.getQ(), dsaParams.getG())); + + engine.init(param); + initialised = true; + } + + public KeyPair generateKeyPair() + { + if (!initialised) + { + DSAParametersGenerator pGen = new DSAParametersGenerator(); + + pGen.init(strength, certainty, random); + param = new DSAKeyGenerationParameters(random, pGen.generateParameters()); + engine.init(param); + initialised = true; + } + + AsymmetricCipherKeyPair pair = engine.generateKeyPair(); + DSAPublicKeyParameters pub = (DSAPublicKeyParameters)pair.getPublic(); + DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)pair.getPrivate(); + + return new KeyPair(new BCDSAPublicKey(pub), + new BCDSAPrivateKey(priv)); + } +} |