Java卡>签名并验证

发布于 2024-12-25 15:34:12 字数 2180 浏览 2 评论 0原文

有人可以给我一些关于如何使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

笑脸一如从前 2025-01-01 15:34:12

对于初学者来说,您正在使用两个单独的签名函数。较旧的 ISO9796 与 PKCS#1 签名格式有很大不同,如果您在 Java 端指定 "SHA1withRSA" ,则使用 PKCS#1 签名格式。您真的需要消息恢复吗?如今它主要用于卡可验证证书(如果它被使用)。

只需在 Java 卡端使用 SignatureALG_RSA_SHA_PKCS1 而不是 SignatureMessageRecoveryALG_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 and ALG_RSA_SHA_PKCS1 instead of SignatureMessageRecovery and ALG_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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文