diff options
author | Roberto Tyley <roberto.tyley@gmail.com> | 2014-07-15 01:38:01 +0400 |
---|---|---|
committer | Roberto Tyley <roberto.tyley@gmail.com> | 2014-07-26 11:23:17 +0400 |
commit | 7cb752aaf746dc0b473afeb9e892b7fbc12666c5 (patch) | |
tree | cc4f91ddc18332b5adbe82e3fcb040d976c90105 /prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/gost | |
parent | 551830f8ea5177042af2c7dd1fc90888bc67387d (diff) |
Execute become-spongy.sh
https://github.com/rtyley/spongycastle/blob/3040af/become-spongy.sh
Diffstat (limited to 'prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/gost')
7 files changed, 1111 insertions, 0 deletions
diff --git a/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/gost/AlgorithmParameterGeneratorSpi.java b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/gost/AlgorithmParameterGeneratorSpi.java new file mode 100644 index 00000000..0cf5908a --- /dev/null +++ b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/gost/AlgorithmParameterGeneratorSpi.java @@ -0,0 +1,65 @@ +package org.spongycastle.jcajce.provider.asymmetric.gost; + +import java.security.AlgorithmParameters; +import java.security.InvalidAlgorithmParameterException; +import java.security.SecureRandom; +import java.security.spec.AlgorithmParameterSpec; + +import org.spongycastle.crypto.generators.GOST3410ParametersGenerator; +import org.spongycastle.crypto.params.GOST3410Parameters; +import org.spongycastle.jce.provider.BouncyCastleProvider; +import org.spongycastle.jce.spec.GOST3410ParameterSpec; +import org.spongycastle.jce.spec.GOST3410PublicKeyParameterSetSpec; + +public abstract class AlgorithmParameterGeneratorSpi + extends java.security.AlgorithmParameterGeneratorSpi +{ + protected SecureRandom random; + protected int strength = 1024; + + protected void engineInit( + int strength, + SecureRandom random) + { + this.strength = strength; + this.random = random; + } + + protected void engineInit( + AlgorithmParameterSpec genParamSpec, + SecureRandom random) + throws InvalidAlgorithmParameterException + { + throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for GOST3410 parameter generation."); + } + + protected AlgorithmParameters engineGenerateParameters() + { + GOST3410ParametersGenerator pGen = new GOST3410ParametersGenerator(); + + if (random != null) + { + pGen.init(strength, 2, random); + } + else + { + pGen.init(strength, 2, new SecureRandom()); + } + + GOST3410Parameters p = pGen.generateParameters(); + + AlgorithmParameters params; + + try + { + params = AlgorithmParameters.getInstance("GOST3410", BouncyCastleProvider.PROVIDER_NAME); + params.init(new GOST3410ParameterSpec(new GOST3410PublicKeyParameterSetSpec(p.getP(), p.getQ(), p.getA()))); + } + catch (Exception e) + { + throw new RuntimeException(e.getMessage()); + } + + return params; + } +} diff --git a/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/gost/AlgorithmParametersSpi.java b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/gost/AlgorithmParametersSpi.java new file mode 100644 index 00000000..c046d008 --- /dev/null +++ b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/gost/AlgorithmParametersSpi.java @@ -0,0 +1,138 @@ +package org.spongycastle.jcajce.provider.asymmetric.gost; + +import java.io.IOException; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.InvalidParameterSpecException; + +import org.spongycastle.asn1.ASN1Encoding; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.ASN1Primitive; +import org.spongycastle.asn1.ASN1Sequence; +import org.spongycastle.asn1.cryptopro.GOST3410PublicKeyAlgParameters; +import org.spongycastle.jce.spec.GOST3410ParameterSpec; +import org.spongycastle.jce.spec.GOST3410PublicKeyParameterSetSpec; + +public class AlgorithmParametersSpi + extends java.security.AlgorithmParametersSpi +{ + GOST3410ParameterSpec 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 GOST3410Parameter. + * <p/> + * <pre> + * GOST3410Parameter ::= SEQUENCE { + * prime INTEGER, -- p + * subprime INTEGER, -- q + * base INTEGER, -- a} + * </pre> + */ + protected byte[] engineGetEncoded() + { + GOST3410PublicKeyAlgParameters gost3410P = new GOST3410PublicKeyAlgParameters(new ASN1ObjectIdentifier(currentSpec.getPublicKeyParamSetOID()), new ASN1ObjectIdentifier(currentSpec.getDigestParamSetOID()), new ASN1ObjectIdentifier(currentSpec.getEncryptionParamSetOID())); + + try + { + return gost3410P.getEncoded(ASN1Encoding.DER); + } + catch (IOException e) + { + throw new RuntimeException("Error encoding GOST3410Parameters"); + } + } + + protected byte[] engineGetEncoded( + String format) + { + if (isASN1FormatString(format) || format.equalsIgnoreCase("X.509")) + { + return engineGetEncoded(); + } + + return null; + } + + protected AlgorithmParameterSpec localEngineGetParameterSpec( + Class paramSpec) + throws InvalidParameterSpecException + { + if (paramSpec == GOST3410PublicKeyParameterSetSpec.class) + { + return currentSpec; + } + + throw new InvalidParameterSpecException("unknown parameter spec passed to GOST3410 parameters object."); + } + + protected void engineInit( + AlgorithmParameterSpec paramSpec) + throws InvalidParameterSpecException + { + if (!(paramSpec instanceof GOST3410ParameterSpec)) + { + throw new InvalidParameterSpecException("GOST3410ParameterSpec required to initialise a GOST3410 algorithm parameters object"); + } + + this.currentSpec = (GOST3410ParameterSpec)paramSpec; + } + + protected void engineInit( + byte[] params) + throws IOException + { + try + { + ASN1Sequence seq = (ASN1Sequence)ASN1Primitive.fromByteArray(params); + + this.currentSpec = GOST3410ParameterSpec.fromPublicKeyAlg( + new GOST3410PublicKeyAlgParameters(seq)); + } + catch (ClassCastException e) + { + throw new IOException("Not a valid GOST3410 Parameter encoding."); + } + catch (ArrayIndexOutOfBoundsException e) + { + throw new IOException("Not a valid GOST3410 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 "GOST3410 Parameters"; + } + +} diff --git a/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/gost/BCGOST3410PrivateKey.java b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/gost/BCGOST3410PrivateKey.java new file mode 100644 index 00000000..13340f1e --- /dev/null +++ b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/gost/BCGOST3410PrivateKey.java @@ -0,0 +1,253 @@ +package org.spongycastle.jcajce.provider.asymmetric.gost; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.math.BigInteger; +import java.util.Enumeration; + +import org.spongycastle.asn1.ASN1Encodable; +import org.spongycastle.asn1.ASN1Encoding; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.ASN1OctetString; +import org.spongycastle.asn1.ASN1Sequence; +import org.spongycastle.asn1.DEROctetString; +import org.spongycastle.asn1.cryptopro.CryptoProObjectIdentifiers; +import org.spongycastle.asn1.cryptopro.GOST3410PublicKeyAlgParameters; +import org.spongycastle.asn1.pkcs.PrivateKeyInfo; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.crypto.params.GOST3410PrivateKeyParameters; +import org.spongycastle.jcajce.provider.asymmetric.util.PKCS12BagAttributeCarrierImpl; +import org.spongycastle.jce.interfaces.GOST3410Params; +import org.spongycastle.jce.interfaces.GOST3410PrivateKey; +import org.spongycastle.jce.interfaces.PKCS12BagAttributeCarrier; +import org.spongycastle.jce.spec.GOST3410ParameterSpec; +import org.spongycastle.jce.spec.GOST3410PrivateKeySpec; +import org.spongycastle.jce.spec.GOST3410PublicKeyParameterSetSpec; + +public class BCGOST3410PrivateKey + implements GOST3410PrivateKey, PKCS12BagAttributeCarrier +{ + static final long serialVersionUID = 8581661527592305464L; + + private BigInteger x; + + private transient GOST3410Params gost3410Spec; + private transient PKCS12BagAttributeCarrier attrCarrier = new PKCS12BagAttributeCarrierImpl(); + + protected BCGOST3410PrivateKey() + { + } + + BCGOST3410PrivateKey( + GOST3410PrivateKey key) + { + this.x = key.getX(); + this.gost3410Spec = key.getParameters(); + } + + BCGOST3410PrivateKey( + GOST3410PrivateKeySpec spec) + { + this.x = spec.getX(); + this.gost3410Spec = new GOST3410ParameterSpec(new GOST3410PublicKeyParameterSetSpec(spec.getP(), spec.getQ(), spec.getA())); + } + + BCGOST3410PrivateKey( + PrivateKeyInfo info) + throws IOException + { + GOST3410PublicKeyAlgParameters params = new GOST3410PublicKeyAlgParameters((ASN1Sequence)info.getAlgorithmId().getParameters()); + ASN1OctetString derX = ASN1OctetString.getInstance(info.parsePrivateKey()); + byte[] keyEnc = derX.getOctets(); + byte[] keyBytes = new byte[keyEnc.length]; + + for (int i = 0; i != keyEnc.length; i++) + { + keyBytes[i] = keyEnc[keyEnc.length - 1 - i]; // was little endian + } + + this.x = new BigInteger(1, keyBytes); + this.gost3410Spec = GOST3410ParameterSpec.fromPublicKeyAlg(params); + } + + BCGOST3410PrivateKey( + GOST3410PrivateKeyParameters params, + GOST3410ParameterSpec spec) + { + this.x = params.getX(); + this.gost3410Spec = spec; + + if (spec == null) + { + throw new IllegalArgumentException("spec is null"); + } + } + + public String getAlgorithm() + { + return "GOST3410"; + } + + /** + * 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() + { + PrivateKeyInfo info; + byte[] keyEnc = this.getX().toByteArray(); + byte[] keyBytes; + + if (keyEnc[0] == 0) + { + keyBytes = new byte[keyEnc.length - 1]; + } + else + { + keyBytes = new byte[keyEnc.length]; + } + + for (int i = 0; i != keyBytes.length; i++) + { + keyBytes[i] = keyEnc[keyEnc.length - 1 - i]; // must be little endian + } + + try + { + if (gost3410Spec instanceof GOST3410ParameterSpec) + { + info = new PrivateKeyInfo(new AlgorithmIdentifier(CryptoProObjectIdentifiers.gostR3410_94, new GOST3410PublicKeyAlgParameters(new ASN1ObjectIdentifier(gost3410Spec.getPublicKeyParamSetOID()), new ASN1ObjectIdentifier(gost3410Spec.getDigestParamSetOID()))), new DEROctetString(keyBytes)); + } + else + { + info = new PrivateKeyInfo(new AlgorithmIdentifier(CryptoProObjectIdentifiers.gostR3410_94), new DEROctetString(keyBytes)); + } + + return info.getEncoded(ASN1Encoding.DER); + } + catch (IOException e) + { + return null; + } + } + + public GOST3410Params getParameters() + { + return gost3410Spec; + } + + public BigInteger getX() + { + return x; + } + + public boolean equals( + Object o) + { + if (!(o instanceof GOST3410PrivateKey)) + { + return false; + } + + GOST3410PrivateKey other = (GOST3410PrivateKey)o; + + return this.getX().equals(other.getX()) + && this.getParameters().getPublicKeyParameters().equals(other.getParameters().getPublicKeyParameters()) + && this.getParameters().getDigestParamSetOID().equals(other.getParameters().getDigestParamSetOID()) + && compareObj(this.getParameters().getEncryptionParamSetOID(), other.getParameters().getEncryptionParamSetOID()); + } + + private boolean compareObj(Object o1, Object o2) + { + if (o1 == o2) + { + return true; + } + + if (o1 == null) + { + return false; + } + + return o1.equals(o2); + } + + public int hashCode() + { + return this.getX().hashCode() ^ gost3410Spec.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(); + + String publicKeyParamSetOID = (String)in.readObject(); + if (publicKeyParamSetOID != null) + { + this.gost3410Spec = new GOST3410ParameterSpec(publicKeyParamSetOID, (String)in.readObject(), (String)in.readObject()); + } + else + { + this.gost3410Spec = new GOST3410ParameterSpec(new GOST3410PublicKeyParameterSetSpec((BigInteger)in.readObject(), (BigInteger)in.readObject(), (BigInteger)in.readObject())); + in.readObject(); + in.readObject(); + } + this.attrCarrier = new PKCS12BagAttributeCarrierImpl(); + } + + private void writeObject( + ObjectOutputStream out) + throws IOException + { + out.defaultWriteObject(); + + if (gost3410Spec.getPublicKeyParamSetOID() != null) + { + out.writeObject(gost3410Spec.getPublicKeyParamSetOID()); + out.writeObject(gost3410Spec.getDigestParamSetOID()); + out.writeObject(gost3410Spec.getEncryptionParamSetOID()); + } + else + { + out.writeObject(null); + out.writeObject(gost3410Spec.getPublicKeyParameters().getP()); + out.writeObject(gost3410Spec.getPublicKeyParameters().getQ()); + out.writeObject(gost3410Spec.getPublicKeyParameters().getA()); + out.writeObject(gost3410Spec.getDigestParamSetOID()); + out.writeObject(gost3410Spec.getEncryptionParamSetOID()); + } + } +} diff --git a/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/gost/BCGOST3410PublicKey.java b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/gost/BCGOST3410PublicKey.java new file mode 100644 index 00000000..658715c9 --- /dev/null +++ b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/gost/BCGOST3410PublicKey.java @@ -0,0 +1,224 @@ +package org.spongycastle.jcajce.provider.asymmetric.gost; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.math.BigInteger; + +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.ASN1Sequence; +import org.spongycastle.asn1.DEROctetString; +import org.spongycastle.asn1.cryptopro.CryptoProObjectIdentifiers; +import org.spongycastle.asn1.cryptopro.GOST3410PublicKeyAlgParameters; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; +import org.spongycastle.crypto.params.GOST3410PublicKeyParameters; +import org.spongycastle.jcajce.provider.asymmetric.util.KeyUtil; +import org.spongycastle.jce.interfaces.GOST3410Params; +import org.spongycastle.jce.interfaces.GOST3410PublicKey; +import org.spongycastle.jce.spec.GOST3410ParameterSpec; +import org.spongycastle.jce.spec.GOST3410PublicKeyParameterSetSpec; +import org.spongycastle.jce.spec.GOST3410PublicKeySpec; + +public class BCGOST3410PublicKey + implements GOST3410PublicKey +{ + static final long serialVersionUID = -6251023343619275990L; + + private BigInteger y; + private transient GOST3410Params gost3410Spec; + + BCGOST3410PublicKey( + GOST3410PublicKeySpec spec) + { + this.y = spec.getY(); + this.gost3410Spec = new GOST3410ParameterSpec(new GOST3410PublicKeyParameterSetSpec(spec.getP(), spec.getQ(), spec.getA())); + } + + BCGOST3410PublicKey( + GOST3410PublicKey key) + { + this.y = key.getY(); + this.gost3410Spec = key.getParameters(); + } + + BCGOST3410PublicKey( + GOST3410PublicKeyParameters params, + GOST3410ParameterSpec spec) + { + this.y = params.getY(); + this.gost3410Spec = spec; + } + + BCGOST3410PublicKey( + BigInteger y, + GOST3410ParameterSpec gost3410Spec) + { + this.y = y; + this.gost3410Spec = gost3410Spec; + } + + BCGOST3410PublicKey( + SubjectPublicKeyInfo info) + { + GOST3410PublicKeyAlgParameters params = new GOST3410PublicKeyAlgParameters((ASN1Sequence)info.getAlgorithmId().getParameters()); + DEROctetString derY; + + try + { + derY = (DEROctetString)info.parsePublicKey(); + + byte[] keyEnc = derY.getOctets(); + byte[] keyBytes = new byte[keyEnc.length]; + + for (int i = 0; i != keyEnc.length; i++) + { + keyBytes[i] = keyEnc[keyEnc.length - 1 - i]; // was little endian + } + + this.y = new BigInteger(1, keyBytes); + } + catch (IOException e) + { + throw new IllegalArgumentException("invalid info structure in GOST3410 public key"); + } + + this.gost3410Spec = GOST3410ParameterSpec.fromPublicKeyAlg(params); + } + + public String getAlgorithm() + { + return "GOST3410"; + } + + public String getFormat() + { + return "X.509"; + } + + public byte[] getEncoded() + { + SubjectPublicKeyInfo info; + byte[] keyEnc = this.getY().toByteArray(); + byte[] keyBytes; + + if (keyEnc[0] == 0) + { + keyBytes = new byte[keyEnc.length - 1]; + } + else + { + keyBytes = new byte[keyEnc.length]; + } + + for (int i = 0; i != keyBytes.length; i++) + { + keyBytes[i] = keyEnc[keyEnc.length - 1 - i]; // must be little endian + } + + try + { + if (gost3410Spec instanceof GOST3410ParameterSpec) + { + if (gost3410Spec.getEncryptionParamSetOID() != null) + { + info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(CryptoProObjectIdentifiers.gostR3410_94, new GOST3410PublicKeyAlgParameters(new ASN1ObjectIdentifier(gost3410Spec.getPublicKeyParamSetOID()), new ASN1ObjectIdentifier(gost3410Spec.getDigestParamSetOID()), new ASN1ObjectIdentifier(gost3410Spec.getEncryptionParamSetOID()))), new DEROctetString(keyBytes)); + } + else + { + info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(CryptoProObjectIdentifiers.gostR3410_94, new GOST3410PublicKeyAlgParameters(new ASN1ObjectIdentifier(gost3410Spec.getPublicKeyParamSetOID()), new ASN1ObjectIdentifier(gost3410Spec.getDigestParamSetOID()))), new DEROctetString(keyBytes)); + } + } + else + { + info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(CryptoProObjectIdentifiers.gostR3410_94), new DEROctetString(keyBytes)); + } + + return KeyUtil.getEncodedSubjectPublicKeyInfo(info); + } + catch (IOException e) + { + return null; + } + } + + public GOST3410Params getParameters() + { + return gost3410Spec; + } + + public BigInteger getY() + { + return y; + } + + public String toString() + { + StringBuffer buf = new StringBuffer(); + String nl = System.getProperty("line.separator"); + + buf.append("GOST3410 Public Key").append(nl); + buf.append(" y: ").append(this.getY().toString(16)).append(nl); + + return buf.toString(); + } + + public boolean equals(Object o) + { + if (o instanceof BCGOST3410PublicKey) + { + BCGOST3410PublicKey other = (BCGOST3410PublicKey)o; + + return this.y.equals(other.y) && this.gost3410Spec.equals(other.gost3410Spec); + } + + return false; + } + + public int hashCode() + { + return y.hashCode() ^ gost3410Spec.hashCode(); + } + + private void readObject( + ObjectInputStream in) + throws IOException, ClassNotFoundException + { + in.defaultReadObject(); + + String publicKeyParamSetOID = (String)in.readObject(); + if (publicKeyParamSetOID != null) + { + this.gost3410Spec = new GOST3410ParameterSpec(publicKeyParamSetOID, (String)in.readObject(), (String)in.readObject()); + } + else + { + this.gost3410Spec = new GOST3410ParameterSpec(new GOST3410PublicKeyParameterSetSpec((BigInteger)in.readObject(), (BigInteger)in.readObject(), (BigInteger)in.readObject())); + in.readObject(); + in.readObject(); + } + } + + private void writeObject( + ObjectOutputStream out) + throws IOException + { + out.defaultWriteObject(); + + if (gost3410Spec.getPublicKeyParamSetOID() != null) + { + out.writeObject(gost3410Spec.getPublicKeyParamSetOID()); + out.writeObject(gost3410Spec.getDigestParamSetOID()); + out.writeObject(gost3410Spec.getEncryptionParamSetOID()); + } + else + { + out.writeObject(null); + out.writeObject(gost3410Spec.getPublicKeyParameters().getP()); + out.writeObject(gost3410Spec.getPublicKeyParameters().getQ()); + out.writeObject(gost3410Spec.getPublicKeyParameters().getA()); + out.writeObject(gost3410Spec.getDigestParamSetOID()); + out.writeObject(gost3410Spec.getEncryptionParamSetOID()); + } + } +} diff --git a/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/gost/KeyFactorySpi.java b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/gost/KeyFactorySpi.java new file mode 100644 index 00000000..acf1f480 --- /dev/null +++ b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/gost/KeyFactorySpi.java @@ -0,0 +1,121 @@ +package org.spongycastle.jcajce.provider.asymmetric.gost; + +import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; + +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.cryptopro.CryptoProObjectIdentifiers; +import org.spongycastle.asn1.pkcs.PrivateKeyInfo; +import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; +import org.spongycastle.jcajce.provider.asymmetric.util.BaseKeyFactorySpi; +import org.spongycastle.jce.interfaces.GOST3410PrivateKey; +import org.spongycastle.jce.interfaces.GOST3410PublicKey; +import org.spongycastle.jce.spec.GOST3410PrivateKeySpec; +import org.spongycastle.jce.spec.GOST3410PublicKeyParameterSetSpec; +import org.spongycastle.jce.spec.GOST3410PublicKeySpec; + +public class KeyFactorySpi + extends BaseKeyFactorySpi +{ + public KeyFactorySpi() + { + } + + protected KeySpec engineGetKeySpec( + Key key, + Class spec) + throws InvalidKeySpecException + { + if (spec.isAssignableFrom(GOST3410PublicKeySpec.class) && key instanceof GOST3410PublicKey) + { + GOST3410PublicKey k = (GOST3410PublicKey)key; + GOST3410PublicKeyParameterSetSpec parameters = k.getParameters().getPublicKeyParameters(); + + return new GOST3410PublicKeySpec(k.getY(), parameters.getP(), parameters.getQ(), parameters.getA()); + } + else if (spec.isAssignableFrom(GOST3410PrivateKeySpec.class) && key instanceof GOST3410PrivateKey) + { + GOST3410PrivateKey k = (GOST3410PrivateKey)key; + GOST3410PublicKeyParameterSetSpec parameters = k.getParameters().getPublicKeyParameters(); + + return new GOST3410PrivateKeySpec(k.getX(), parameters.getP(), parameters.getQ(), parameters.getA()); + } + + return super.engineGetKeySpec(key, spec); + } + + protected Key engineTranslateKey( + Key key) + throws InvalidKeyException + { + if (key instanceof GOST3410PublicKey) + { + return new BCGOST3410PublicKey((GOST3410PublicKey)key); + } + else if (key instanceof GOST3410PrivateKey) + { + return new BCGOST3410PrivateKey((GOST3410PrivateKey)key); + } + + throw new InvalidKeyException("key type unknown"); + } + + protected PrivateKey engineGeneratePrivate( + KeySpec keySpec) + throws InvalidKeySpecException + { + if (keySpec instanceof GOST3410PrivateKeySpec) + { + return new BCGOST3410PrivateKey((GOST3410PrivateKeySpec)keySpec); + } + + return super.engineGeneratePrivate(keySpec); + } + + protected PublicKey engineGeneratePublic( + KeySpec keySpec) + throws InvalidKeySpecException + { + if (keySpec instanceof GOST3410PublicKeySpec) + { + return new BCGOST3410PublicKey((GOST3410PublicKeySpec)keySpec); + } + + return super.engineGeneratePublic(keySpec); + } + + public PrivateKey generatePrivate(PrivateKeyInfo keyInfo) + throws IOException + { + ASN1ObjectIdentifier algOid = keyInfo.getPrivateKeyAlgorithm().getAlgorithm(); + + if (algOid.equals(CryptoProObjectIdentifiers.gostR3410_94)) + { + return new BCGOST3410PrivateKey(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 (algOid.equals(CryptoProObjectIdentifiers.gostR3410_94)) + { + return new BCGOST3410PublicKey(keyInfo); + } + else + { + throw new IOException("algorithm identifier " + algOid + " in key not recognised"); + } + } +} diff --git a/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/gost/KeyPairGeneratorSpi.java b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/gost/KeyPairGeneratorSpi.java new file mode 100644 index 00000000..67ac1b91 --- /dev/null +++ b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/gost/KeyPairGeneratorSpi.java @@ -0,0 +1,81 @@ +package org.spongycastle.jcajce.provider.asymmetric.gost; + +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyPair; +import java.security.SecureRandom; +import java.security.spec.AlgorithmParameterSpec; + +import org.spongycastle.asn1.cryptopro.CryptoProObjectIdentifiers; +import org.spongycastle.crypto.AsymmetricCipherKeyPair; +import org.spongycastle.crypto.generators.GOST3410KeyPairGenerator; +import org.spongycastle.crypto.params.GOST3410KeyGenerationParameters; +import org.spongycastle.crypto.params.GOST3410Parameters; +import org.spongycastle.crypto.params.GOST3410PrivateKeyParameters; +import org.spongycastle.crypto.params.GOST3410PublicKeyParameters; +import org.spongycastle.jce.spec.GOST3410ParameterSpec; +import org.spongycastle.jce.spec.GOST3410PublicKeyParameterSetSpec; + +public class KeyPairGeneratorSpi + extends java.security.KeyPairGenerator +{ + GOST3410KeyGenerationParameters param; + GOST3410KeyPairGenerator engine = new GOST3410KeyPairGenerator(); + GOST3410ParameterSpec gost3410Params; + int strength = 1024; + SecureRandom random = null; + boolean initialised = false; + + public KeyPairGeneratorSpi() + { + super("GOST3410"); + } + + public void initialize( + int strength, + SecureRandom random) + { + this.strength = strength; + this.random = random; + } + + private void init( + GOST3410ParameterSpec gParams, + SecureRandom random) + { + GOST3410PublicKeyParameterSetSpec spec = gParams.getPublicKeyParameters(); + + param = new GOST3410KeyGenerationParameters(random, new GOST3410Parameters(spec.getP(), spec.getQ(), spec.getA())); + + engine.init(param); + + initialised = true; + gost3410Params = gParams; + } + + public void initialize( + AlgorithmParameterSpec params, + SecureRandom random) + throws InvalidAlgorithmParameterException + { + if (!(params instanceof GOST3410ParameterSpec)) + { + throw new InvalidAlgorithmParameterException("parameter object not a GOST3410ParameterSpec"); + } + + init((GOST3410ParameterSpec)params, random); + } + + public KeyPair generateKeyPair() + { + if (!initialised) + { + init(new GOST3410ParameterSpec(CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_A.getId()), new SecureRandom()); + } + + AsymmetricCipherKeyPair pair = engine.generateKeyPair(); + GOST3410PublicKeyParameters pub = (GOST3410PublicKeyParameters)pair.getPublic(); + GOST3410PrivateKeyParameters priv = (GOST3410PrivateKeyParameters)pair.getPrivate(); + + return new KeyPair(new BCGOST3410PublicKey(pub, gost3410Params), new BCGOST3410PrivateKey(priv, gost3410Params)); + } +} diff --git a/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/gost/SignatureSpi.java b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/gost/SignatureSpi.java new file mode 100644 index 00000000..199af6dc --- /dev/null +++ b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/gost/SignatureSpi.java @@ -0,0 +1,229 @@ +package org.spongycastle.jcajce.provider.asymmetric.gost; + +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.spec.AlgorithmParameterSpec; + +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.GOST3411Digest; +import org.spongycastle.crypto.params.ParametersWithRandom; +import org.spongycastle.crypto.signers.GOST3410Signer; +import org.spongycastle.jcajce.provider.asymmetric.util.ECUtil; +import org.spongycastle.jce.interfaces.ECKey; +import org.spongycastle.jce.interfaces.ECPublicKey; +import org.spongycastle.jce.interfaces.GOST3410Key; +import org.spongycastle.jce.provider.BouncyCastleProvider; +import org.spongycastle.jcajce.provider.asymmetric.util.GOST3410Util; + +public class SignatureSpi + extends java.security.SignatureSpi + implements PKCSObjectIdentifiers, X509ObjectIdentifiers +{ + private Digest digest; + private DSA signer; + private SecureRandom random; + + public SignatureSpi() + { + this.digest = new GOST3411Digest(); + this.signer = new GOST3410Signer(); + } + + protected void engineInitVerify( + PublicKey publicKey) + throws InvalidKeyException + { + CipherParameters param; + + if (publicKey instanceof ECPublicKey) + { + param = ECUtil.generatePublicKeyParameter(publicKey); + } + else if (publicKey instanceof GOST3410Key) + { + param = GOST3410Util.generatePublicKeyParameter(publicKey); + } + else + { + try + { + byte[] bytes = publicKey.getEncoded(); + + publicKey = BouncyCastleProvider.getPublicKey(SubjectPublicKeyInfo.getInstance(bytes)); + + if (publicKey instanceof ECPublicKey) + { + param = ECUtil.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; + + if (privateKey instanceof ECKey) + { + param = ECUtil.generatePrivateKeyParameter(privateKey); + } + else + { + param = GOST3410Util.generatePrivateKeyParameter(privateKey); + } + + digest.reset(); + + if (random != null) + { + signer.init(true, new ParametersWithRandom(param, random)); + } + else + { + 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 + { + byte[] sigBytes = new byte[64]; + BigInteger[] sig = signer.generateSignature(hash); + byte[] r = sig[0].toByteArray(); + byte[] s = sig[1].toByteArray(); + + if (s[0] != 0) + { + System.arraycopy(s, 0, sigBytes, 32 - s.length, s.length); + } + else + { + System.arraycopy(s, 1, sigBytes, 32 - (s.length - 1), s.length - 1); + } + + if (r[0] != 0) + { + System.arraycopy(r, 0, sigBytes, 64 - r.length, r.length); + } + else + { + System.arraycopy(r, 1, sigBytes, 64 - (r.length - 1), r.length - 1); + } + + return sigBytes; + } + 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 + { + byte[] r = new byte[32]; + byte[] s = new byte[32]; + + System.arraycopy(sigBytes, 0, s, 0, 32); + + System.arraycopy(sigBytes, 32, r, 0, 32); + + sig = new BigInteger[2]; + sig[0] = new BigInteger(1, r); + sig[1] = new BigInteger(1, s); + } + 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"); + } +} |