Я проверяю проверку подписи надувного замка. Интересно, что он проверяет нормально после подписания, но при запуске нового экземпляра с открытым ключом, сообщение и подпись, если всегда происходит сбой. Я использую ту же самую процедуру проверки сразу после генерации подписи и следующего запуска, который является простым кодом Java. (Вся история может быть неактуальной, но я пытаюсь создать сертификат CA открытого ключа javacard и должен подписать полученный сертификат. Сразу после генерации сертификата и подписи проверка всегда проходит, но при запуске следующего экземпляр для проверки сертификата открытого ключа не удается.)
Я хотел бы попросить обратной связи, если это случилось с кем-либо еще. Я в значительной степени предполагаю, что код правильный, так как он работает сразу после подписания.
Если код все же требуется, я его почистю и опубликую, но это похоже на примеры кода, найденные в сети.
public class VerifyEccSignature {
public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeySpecException {
boolean verify;
Provider prov=new BouncyCastleProvider();
Signature ecdsaSign;
Security.addProvider(prov);
// Card Public Key
byte[] pubKey = HexAdapter.toBin("04cd7a82795bf691232e409ebe10039be6167d15b07e19da0c417c830d4db8b9d8f6919113468a1f650125545cc0bca619ec3be88723889fb439b71dee3e1dbad3");
// Certificate to sign ()
byte[] cert=HexAdapter.toBin("48656C6C6F576F726C64");
// Signature returned by chip
byte[] sigBytes=HexAdapter.toBin("30450220459408F84F45A1F960C3260D8191083617C016ADC721E5162F667D8E01BAEBCD0221008BE3EFD1F09363653B699CA39174D265218911023DA0DCBD04C1F44228D5E5FD");
try {
// Get rpivate key
KeyFactory keyFactory = KeyFactory.getInstance("ECDSA",prov);
PKCS8EncodedKeySpec spec=new PKCS8EncodedKeySpec(HexAdapter.toBin("308193020100301306072A8648CE3D020106082A8648CE3D0301070479307702010104200BF4B825E8B758853A49E01EAA45905E249B580421C7306A8EC85B4F4229675DA00A06082A8648CE3D030107A14403420004CD7A82795BF691232E409EBE10039BE6167D15B07E19DA0C417C830D4DB8B9D8F6919113468A1F650125545CC0BCA619EC3BE88723889FB439B71DEE3E1DBAD3"));
PrivateKey priv = keyFactory.generatePrivate(spec);
ecdsaSign = java.security.Signature.getInstance("SHA256withECDSA",prov);
// Generate signature of first run
byte[] cc="HelloWorld".getBytes();
ecdsaSign.initSign(priv);
ecdsaSign.update(cc);
byte[] signature=ecdsaSign.sign();
System.out.println("data " + HexAdapter.toHex(cc));
System.out.println("signature= "+HexAdapter.toHex(signature));
// Convert it to export format required for Tachograph certificate
byte[] rawSignature=VerifySignature.getRawSignature(signature);
// Setup verifing class
VerifySignature vv=new VerifySignature(prov);
// Verify current run
verify=vv.verify(pubKey, ByteBuffer.wrap(cc), rawSignature);
System.out.println("cc verify signature. Result: "+verify);
// Verify previous run whre signature is copied into cert from output of previous run
verify=vv.verify(pubKey, ByteBuffer.wrap(cert), sigBytes);
// Output information required for verification and to copy over to next run
System.out.println("pubkey "+HexAdapter.toHex(pubKey));
System.out.println("cert "+HexAdapter.toHex(cert));
System.out.println("sig "+HexAdapter.toHex(sigBytes));
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(TestCaSignerEcc.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvalidKeyException ex) {
Logger.getLogger(VerifyEccSignature.class.getName()).log(Level.SEVERE, null, ex);
} catch (SignatureException ex) {
Logger.getLogger(VerifyEccSignature.class.getName()).log(Level.SEVERE, null, ex);
} catch (Exception ex) {
Logger.getLogger(VerifyEccSignature.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Проверка:
public class VerifySignature {
Provider prov;
Signature ecdsaSign;
public VerifySignature(Provider prov) {
this.prov = prov;
}
public boolean verify(byte[] pubKey, ByteBuffer plainCert, byte[] rawSignature){
boolean verify=false;
try {
ECPublicKey pp= decodeKey(prov,pubKey);
ASN1EncodableVector v = new ASN1EncodableVector();
v.add(/*r*/new ASN1Integer(new BigInteger(1, Arrays.copyOfRange(rawSignature,0,32))));
v.add(/*s*/new ASN1Integer(new BigInteger(1, Arrays.copyOfRange(rawSignature,32,32*2))));
byte[] sigDer = new DERSequence(v).getEncoded();
System.out.println("v "+v);
// Verify signature
ecdsaSign = java.security.Signature.getInstance("SHA256withECDSA",prov);
ecdsaSign.initVerify(pp);
ecdsaSign.update(plainCert);
verify = ecdsaSign.verify(sigDer);
System.out.println(" - Singnature verified: "+verify);
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(TestCaSignerEcc.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvalidKeySpecException | SignatureException | InvalidKeyException | IOException ex) {
Logger.getLogger(VerifyEccSignature.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchProviderException ex) {
Logger.getLogger(VerifySignature.class.getName()).log(Level.SEVERE, null, ex);
}
return verify;
}
public static ECPublicKey decodeKey(Provider prov, byte[] encoded) throws InvalidKeySpecException, NoSuchAlgorithmException, NoSuchProviderException{
java.security.spec.ECPoint point = new java.security.spec.ECPoint( new BigInteger(1, Arrays.copyOfRange(encoded,1,33)),
new BigInteger(1, Arrays.copyOfRange(encoded,33,65))
);
ECNamedCurveParameterSpec params = ECNamedCurveTable.getParameterSpec(/*"secp256r1""prime256v1*/"P-256");
KeyFactory fact = KeyFactory.getInstance("ECDSA",prov);
ECCurve curve = params.getCurve();
java.security.spec.EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, params.getSeed());
java.security.spec.ECParameterSpec params2=EC5Util.convertSpec(ellipticCurve, params);
java.security.spec.ECPublicKeySpec keySpec = new java.security.spec.ECPublicKeySpec(point,params2);
ECPublicKey pubKey=(ECPublicKey) fact.generatePublic(keySpec);
return pubKey;
}
private static ASN1Primitive toAsn1Primitive(byte[] data) throws Exception
{
try (ByteArrayInputStream inStream = new ByteArrayInputStream(data);
ASN1InputStream asnInputStream = new ASN1InputStream(inStream);)
{
return asnInputStream.readObject();
}
}
public static byte[] getRawSignature(byte[] signed)throws Exception{
ASN1Primitive asn1 = toAsn1Primitive(signed);
byte[] rawSignature=new byte[0x40];
byte[] tt;
int ptr=0;
if (asn1 instanceof ASN1Sequence) {
ASN1Sequence asn1Sequence = (ASN1Sequence) asn1;
ASN1Encodable[] asn1Encodables = asn1Sequence.toArray();
for (ASN1Encodable asn1Encodable : asn1Encodables) {
ASN1Primitive asn1Primitive = asn1Encodable.toASN1Primitive();
if (asn1Primitive instanceof ASN1Integer) {
ASN1Integer asn1Integer = (ASN1Integer) asn1Primitive;
BigInteger integer = asn1Integer.getValue();
tt=BigIntegers.asUnsignedByteArray(asn1Integer.getValue());
System.arraycopy(tt, 0, rawSignature, ptr, 0x20);
ptr+=0x20;
}
}
}
return rawSignature;
}
}