我正在测试充气城堡签名验证。有趣的是,它在签名后会验证正常,但是当使用公钥,消息和签名运行新实例时(如果总是失败)。在签名生成和下一次运行之后,我将使用相同的验证例程,这是一个简单的Java代码。 (整个故事可能无关紧要,但是我试图创建一个javacard公钥的CA证书,并且需要对生成的证书进行签名。在生成证书并签名之后,验证始终会通过,但是在运行下一个证书时实例以验证失败的公钥证书。) 如果这已经发生在其他任何人身上,我恳请您提供反馈。我几乎认为该代码是正确的,因为它在签名后立即可用。 如果仍然需要代码,我将清理并发布它,但这与网上的代码示例相似。
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;
}
}
答案 0 :(得分:0)
很抱歉打扰大家。 看来我一直在直接注入签名,在验证期间将其转换回ASN1之前,先将其转换为原始格式。我的疏忽 彼得