| package org.bouncycastle.jcajce.provider.asymmetric.ec; |
| |
| import java.io.IOException; |
| import java.math.BigInteger; |
| import java.security.InvalidKeyException; |
| import java.security.PrivateKey; |
| import java.security.PublicKey; |
| |
| import org.bouncycastle.asn1.ASN1EncodableVector; |
| import org.bouncycastle.asn1.ASN1Encoding; |
| import org.bouncycastle.asn1.ASN1Integer; |
| import org.bouncycastle.asn1.ASN1Primitive; |
| import org.bouncycastle.asn1.ASN1Sequence; |
| 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.SM3Digest; |
| import org.bouncycastle.crypto.params.ParametersWithRandom; |
| import org.bouncycastle.crypto.signers.SM2Signer; |
| import org.bouncycastle.jcajce.provider.asymmetric.util.DSABase; |
| import org.bouncycastle.jcajce.provider.asymmetric.util.DSAEncoder; |
| import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil; |
| import org.bouncycastle.util.Arrays; |
| |
| public class GMSignatureSpi |
| extends DSABase |
| { |
| GMSignatureSpi(Digest digest, DSA signer, DSAEncoder encoder) |
| { |
| super(digest, signer, encoder); |
| } |
| |
| protected void engineInitVerify(PublicKey publicKey) |
| throws InvalidKeyException |
| { |
| CipherParameters param = ECUtils.generatePublicKeyParameter(publicKey); |
| |
| digest.reset(); |
| signer.init(false, param); |
| } |
| |
| protected void engineInitSign( |
| PrivateKey privateKey) |
| throws InvalidKeyException |
| { |
| CipherParameters param = ECUtil.generatePrivateKeyParameter(privateKey); |
| |
| digest.reset(); |
| |
| if (appRandom != null) |
| { |
| signer.init(true, new ParametersWithRandom(param, appRandom)); |
| } |
| else |
| { |
| signer.init(true, param); |
| } |
| } |
| |
| static public class sm3WithSM2 |
| extends GMSignatureSpi |
| { |
| public sm3WithSM2() |
| { |
| super(new SM3Digest(), new SM2Signer(), new StdDSAEncoder()); |
| } |
| } |
| |
| private static class StdDSAEncoder |
| implements DSAEncoder |
| { |
| public byte[] encode( |
| BigInteger r, |
| BigInteger s) |
| throws IOException |
| { |
| ASN1EncodableVector v = new ASN1EncodableVector(); |
| |
| v.add(new ASN1Integer(r)); |
| v.add(new ASN1Integer(s)); |
| |
| return new DERSequence(v).getEncoded(ASN1Encoding.DER); |
| } |
| |
| public BigInteger[] decode( |
| byte[] encoding) |
| throws IOException |
| { |
| ASN1Sequence s = (ASN1Sequence)ASN1Primitive.fromByteArray(encoding); |
| if (s.size() != 2) |
| { |
| throw new IOException("malformed signature"); |
| } |
| if (!Arrays.areEqual(encoding, s.getEncoded(ASN1Encoding.DER))) |
| { |
| throw new IOException("malformed signature"); |
| } |
| |
| BigInteger[] sig = new BigInteger[2]; |
| |
| |
| sig[0] = ASN1Integer.getInstance(s.getObjectAt(0)).getValue(); |
| sig[1] = ASN1Integer.getInstance(s.getObjectAt(1)).getValue(); |
| |
| return sig; |
| } |
| } |
| |
| private static class PlainDSAEncoder |
| 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; |
| } |
| } |
| } |