Java卡>签名并验证
有人可以给我一些关于如何使用 javacard 进行签名并验证它的小建议吗? 想我在签名生成和验证方面做错了什么:
…………
SignatureMessageRecovery sig;
我
private Cardlet(byte[] bArray, short bOffset, byte bLength) {
/* Generate our RSA key */
keyPair = new KeyPair(KeyPair.ALG_RSA, (short) 512);
keyPair.genKeyPair();
/* signature buffer is 64 + 2 (offset + length) */
sigBuff = JCSystem.makeTransientByteArray((short) (SIG_LENGTH + 2), JCSystem.CLEAR_ON_DESELECT);
sig = (SignatureMessageRecovery) Signature.getInstance(Signature.ALG_RSA_SHA_ISO9796_MR, false);
}
private void insCryptoSigne(APDU apdu) {
byte[] buffer = apdu.getBuffer();
short bytesRead = apdu.setIncomingAndReceive();
short[] m1Data = JCSystem.makeTransientShortArray((short) 1, JCSystem.CLEAR_ON_DESELECT);
sigLen = sig.sign(buffer, ISO7816.OFFSET_CDATA, bytesRead, sigBuff, (short) 0, m1Data, (short) 0);
// set m1Length into sigBuff array
sigBuff[sigLen] = (byte) ((short) (m1Data[(short) 0] & ((short) 0xFF00)) >> ((short) 8));
sigBuff[(short) (sigLen + 1)] = (byte) (m1Data[(short) 0] & ((short) 0x00FF));
apdu.setOutgoing();
apdu.setOutgoingLength((short) (sigLen + 2));// The extra 2 bytes for
apdu.sendBytesLong(sigBuff, (short) 0, (short) (sigLen + 2));
}
在 Java 端 我已经获得了公钥,并将其作为 X509Certificate 保存在本地文件中。很确定它们是相同的,因为证书和卡中的模数和指数似乎相同。
FileInputStream certis = new FileInputStream(cert);
X509Certificate c1 = new X509Certificate(certis);
...
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
byte[] testsig = new byte[64];
System.arraycopy(raw_signature,0, testsig, 0, 64);
Signature signature = Signature.getInstance("SHA1withRSA", "BC");
signature.initVerify(c1.getPublicKey());
System.out.println(c1.getPublicKey());
System.out.println(signature);
System.out.println(file_data.length+":> "+new String(file_data));
signature.update(file_data);
System.out.println("VERIFY > "+signature.verify(testsig)+" <");
结果是假的:(
谢谢和问候 图里
Can someone give me a small advice on how to make a signature with javacard and verify it?
I guess I am doing something wrong with the signature generation and verification:
...
SignatureMessageRecovery sig;
...
private Cardlet(byte[] bArray, short bOffset, byte bLength) {
/* Generate our RSA key */
keyPair = new KeyPair(KeyPair.ALG_RSA, (short) 512);
keyPair.genKeyPair();
/* signature buffer is 64 + 2 (offset + length) */
sigBuff = JCSystem.makeTransientByteArray((short) (SIG_LENGTH + 2), JCSystem.CLEAR_ON_DESELECT);
sig = (SignatureMessageRecovery) Signature.getInstance(Signature.ALG_RSA_SHA_ISO9796_MR, false);
}
...
private void insCryptoSigne(APDU apdu) {
byte[] buffer = apdu.getBuffer();
short bytesRead = apdu.setIncomingAndReceive();
short[] m1Data = JCSystem.makeTransientShortArray((short) 1, JCSystem.CLEAR_ON_DESELECT);
sigLen = sig.sign(buffer, ISO7816.OFFSET_CDATA, bytesRead, sigBuff, (short) 0, m1Data, (short) 0);
// set m1Length into sigBuff array
sigBuff[sigLen] = (byte) ((short) (m1Data[(short) 0] & ((short) 0xFF00)) >> ((short) 8));
sigBuff[(short) (sigLen + 1)] = (byte) (m1Data[(short) 0] & ((short) 0x00FF));
apdu.setOutgoing();
apdu.setOutgoingLength((short) (sigLen + 2));// The extra 2 bytes for
apdu.sendBytesLong(sigBuff, (short) 0, (short) (sigLen + 2));
}
ON Java side
I already have gotten the public key saved it in a file localy as a X509Certificate. Pretty sure they are the same as the modulus and exponent seem the same in both, certificate and card.
FileInputStream certis = new FileInputStream(cert);
X509Certificate c1 = new X509Certificate(certis);
...
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
byte[] testsig = new byte[64];
System.arraycopy(raw_signature,0, testsig, 0, 64);
Signature signature = Signature.getInstance("SHA1withRSA", "BC");
signature.initVerify(c1.getPublicKey());
System.out.println(c1.getPublicKey());
System.out.println(signature);
System.out.println(file_data.length+":> "+new String(file_data));
signature.update(file_data);
System.out.println("VERIFY > "+signature.verify(testsig)+" <");
The result is false :(
Thanks and Regards
Turi
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
对于初学者来说,您正在使用两个单独的签名函数。较旧的 ISO9796 与 PKCS#1 签名格式有很大不同,如果您在 Java 端指定
"SHA1withRSA"
,则使用 PKCS#1 签名格式。您真的需要消息恢复吗?如今它主要用于卡可验证证书(如果它被使用)。只需在 Java 卡端使用
Signature
和ALG_RSA_SHA_PKCS1
而不是SignatureMessageRecovery
和ALG_RSA_SHA_ISO9796_MR
即可。如果您想要消息恢复,您可能必须在 Java 端使用 Bouncy Castle 库(即使在 Bouncy 中,要使其正常工作也有点棘手)。
For starters, you are using two separate signature functions. The older ISO9796 is rather different from the PKCS#1 signature format which is used if you specify
"SHA1withRSA"
on the Java side. Do you really need message recovery? It's mostly used for card verifiable certificates nowadays (if it is used).Simply use
Signature
andALG_RSA_SHA_PKCS1
instead ofSignatureMessageRecovery
andALG_RSA_SHA_ISO9796_MR
on the Java Card side.If you want message recovery you may have to use the Bouncy Castle library at the Java side (and even in Bouncy it is a bit tricky to get it working correctly).