blob: 8992d5faeb9e7755123507a27cdb619a36181703 [file] [log] [blame]
package org.bouncycastle.jcajce.provider.asymmetric.gost;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.util.Enumeration;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
import org.bouncycastle.asn1.cryptopro.GOST3410PublicKeyAlgParameters;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.crypto.params.GOST3410PrivateKeyParameters;
import org.bouncycastle.jcajce.provider.asymmetric.util.GOST3410Util;
import org.bouncycastle.jcajce.provider.asymmetric.util.PKCS12BagAttributeCarrierImpl;
import org.bouncycastle.jce.interfaces.GOST3410Params;
import org.bouncycastle.jce.interfaces.GOST3410PrivateKey;
import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
import org.bouncycastle.jce.spec.GOST3410ParameterSpec;
import org.bouncycastle.jce.spec.GOST3410PrivateKeySpec;
import org.bouncycastle.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 = GOST3410PublicKeyAlgParameters.getInstance(info.getPrivateKeyAlgorithm().getParameters());
ASN1Encodable privKey = info.parsePrivateKey();
if (privKey instanceof ASN1Integer)
{
this.x = ASN1Integer.getInstance(privKey).getPositiveValue();
}
else
{
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 String toString()
{
try
{
return GOSTUtil.privateKeyToString("GOST3410", x,
((GOST3410PrivateKeyParameters)GOST3410Util.generatePrivateKeyParameter(this)).getParameters());
}
catch (InvalidKeyException e)
{
throw new IllegalStateException(e.getMessage()); // should not be possible
}
}
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());
}
}
}