package org.bouncycastle.jce.provider.asymmetric.ec;
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.interfaces.ECPublicKey;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERInteger;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DSA;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.NullDigest;
import org.bouncycastle.crypto.digests.RIPEMD160Digest;
import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.crypto.digests.SHA224Digest;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.digests.SHA384Digest;
import org.bouncycastle.crypto.digests.SHA512Digest;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.signers.ECDSASigner;
import org.bouncycastle.crypto.signers.ECNRSigner;
import org.bouncycastle.jce.interfaces.ECKey;
import org.bouncycastle.jce.provider.DSABase;
import org.bouncycastle.jce.provider.DSAEncoder;
import org.bouncycastle.jce.provider.JDKKeyFactory;
public class Signature
extends DSABase
{
Signature(Digest digest, DSA signer, DSAEncoder encoder)
{
super(digest, signer, encoder);
}
protected void engineInitVerify(PublicKey publicKey)
throws InvalidKeyException
{
CipherParameters param;
if (publicKey instanceof ECPublicKey)
{
param = ECUtil.generatePublicKeyParameter(publicKey);
}
else
{
try
{
byte[] bytes = publicKey.getEncoded();
publicKey = JDKKeyFactory.createPublicKeyFromDERStream(bytes);
if (publicKey instanceof ECPublicKey)
{
param = ECUtil.generatePublicKeyParameter(publicKey);
}
else
{
throw new InvalidKeyException("can't recognise key type in ECDSA based signer");
}
}
catch (Exception e)
{
throw new InvalidKeyException("can't recognise key type in ECDSA based signer");
}
}
digest.reset();
signer.init(false, param);
}
protected void engineInitSign(
PrivateKey privateKey,
SecureRandom random)
throws InvalidKeyException
{
CipherParameters param;
if (privateKey instanceof ECKey)
{
param = ECUtil.generatePrivateKeyParameter(privateKey);
}
else
{
throw new InvalidKeyException("can't recognise key type in ECDSA based signer");
}
digest.reset();
if (random != null)
{
signer.init(true, new ParametersWithRandom(param, random));
}
else
{
signer.init(true, param);
}
}
static public class ecDSA
extends Signature
{
public ecDSA()
{
super(new SHA1Digest(), new ECDSASigner(), new StdDSAEncoder());
}
}
static public class ecDSAnone
extends Signature
{
public ecDSAnone()
{
super(new NullDigest(), new ECDSASigner(), new StdDSAEncoder());
}
}
static public class ecDSA224
extends Signature
{
public ecDSA224()
{
super(new SHA224Digest(), new ECDSASigner(), new StdDSAEncoder());
}
}
static public class ecDSA256
extends Signature
{
public ecDSA256()
{
super(new SHA256Digest(), new ECDSASigner(), new StdDSAEncoder());
}
}
static public class ecDSA384
extends Signature
{
public ecDSA384()
{
super(new SHA384Digest(), new ECDSASigner(), new StdDSAEncoder());
}
}
static public class ecDSA512
extends Signature
{
public ecDSA512()
{
super(new SHA512Digest(), new ECDSASigner(), new StdDSAEncoder());
}
}
static public class ecDSARipeMD160
extends Signature
{
public ecDSARipeMD160()
{
super(new RIPEMD160Digest(), new ECDSASigner(), new StdDSAEncoder());
}
}
static public class ecNR
extends Signature
{
public ecNR()
{
super(new SHA1Digest(), new ECNRSigner(), new StdDSAEncoder());
}
}
static public class ecNR224
extends Signature
{
public ecNR224()
{
super(new SHA224Digest(), new ECNRSigner(), new StdDSAEncoder());
}
}
static public class ecNR256
extends Signature
{
public ecNR256()
{
super(new SHA256Digest(), new ECNRSigner(), new StdDSAEncoder());
}
}
static public class ecNR384
extends Signature
{
public ecNR384()
{
super(new SHA384Digest(), new ECNRSigner(), new StdDSAEncoder());
}
}
static public class ecNR512
extends Signature
{
public ecNR512()
{
super(new SHA512Digest(), new ECNRSigner(), new StdDSAEncoder());
}
}
static public class ecCVCDSA
extends Signature
{
public ecCVCDSA()
{
super(new SHA1Digest(), new ECDSASigner(), new CVCDSAEncoder());
}
}
static public class ecCVCDSA224
extends Signature
{
public ecCVCDSA224()
{
super(new SHA224Digest(), new ECDSASigner(), new CVCDSAEncoder());
}
}
static public class ecCVCDSA256
extends Signature
{
public ecCVCDSA256()
{
super(new SHA256Digest(), new ECDSASigner(), new CVCDSAEncoder());
}
}
private static class StdDSAEncoder
implements DSAEncoder
{
public byte[] encode(
BigInteger r,
BigInteger s)
throws IOException
{
ASN1EncodableVector v = new ASN1EncodableVector();
v.add(new DERInteger(r));
v.add(new DERInteger(s));
return new DERSequence(v).getEncoded(ASN1Encodable.DER);
}
public BigInteger[] decode(
byte[] encoding)
throws IOException
{
ASN1Sequence s = (ASN1Sequence)ASN1Object.fromByteArray(encoding);
BigInteger[] sig = new BigInteger[2];
sig[0] = ((DERInteger)s.getObjectAt(0)).getValue();
sig[1] = ((DERInteger)s.getObjectAt(1)).getValue();
return sig;
}
}
private static class CVCDSAEncoder
implements DSAEncoder
{
public byte[] encode(
BigInteger r,
BigInteger s)
throws IOException
{
byte[] first = makeUnsigned(r);
byte[] second = makeUnsigned(s);
byte[] res;
if (first.length > second.length)
{
res = new byte[first.length * 2];
}
else
{
res = new byte[second.length * 2];
}
System.arraycopy(first, 0, res, res.length / 2 - first.length, first.length);
System.arraycopy(second, 0, res, res.length - second.length, second.length);
return res;
}
private byte[] makeUnsigned(BigInteger val)
{
byte[] res = val.toByteArray();
if (res[0] == 0)
{
byte[] tmp = new byte[res.length - 1];
System.arraycopy(res, 1, tmp, 0, tmp.length);
return tmp;
}
return res;
}
public BigInteger[] decode(
byte[] encoding)
throws IOException
{
BigInteger[] sig = new BigInteger[2];
byte[] first = new byte[encoding.length / 2];
byte[] second = new byte[encoding.length / 2];
System.arraycopy(encoding, 0, first, 0, first.length);
System.arraycopy(encoding, first.length, second, 0, second.length);
sig[0] = new BigInteger(1, first);
sig[1] = new BigInteger(1, second);
return sig;
}
}
}