Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/quite/humla-spongycastle.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa')
-rw-r--r--prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/AlgorithmParameterGeneratorSpi.java103
-rw-r--r--prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/AlgorithmParametersSpi.java132
-rw-r--r--prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/BCDSAPrivateKey.java167
-rw-r--r--prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/BCDSAPublicKey.java171
-rw-r--r--prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/DSASigner.java313
-rw-r--r--prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/DSAUtil.java72
-rw-r--r--prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/KeyFactorySpi.java117
-rw-r--r--prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/KeyPairGeneratorSpi.java82
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));
+ }
+}