java卡RSA加密doFinal方法有什么问题?

时间:2019-07-02 05:44:14

标签: exception rsa javacard

我已经编写了一个Java卡小程序,用于RSA使用私钥对传入的数据进行加密,然后再次发送出去。

这是我的代码:

package test;

import javacard.framework.*;
import javacard.security.*;
import javacardx.crypto.Cipher;

public class test extends Applet
{
    private static byte[] Hash = new byte[32];
    private static byte[] Sign = new byte[256];
    private static short hash_len = 0;
    private static short sign_len = 0;
    MessageDigest mDigest = MessageDigest.getInstance(MessageDigest.ALG_SHA_256,false);
    Cipher rsaCipher = Cipher.getInstance(Cipher.ALG_RSA_NOPAD, false);
    KeyPair rsaKey = new KeyPair(KeyPair.ALG_RSA,KeyBuilder.LENGTH_RSA_2048);
    RSAPublicKey rsaPubKey = (RSAPublicKey)KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC, KeyBuilder.LENGTH_RSA_2048, false);

    public static void install(byte[] bArray, short bOffset, byte bLength) 
    {
        new test().register(bArray, (short) (bOffset + 1), bArray[bOffset]);
    }

    public void process(APDU apdu)
    {
        if (selectingApplet())
        {
            return;
        }

        byte[] buf = apdu.getBuffer();
        switch (buf[ISO7816.OFFSET_INS])
        {
        case (byte)0x00: // generate keypair
            rsaKey.genKeyPair();
            break;
        case (byte)0x01: // get public key
            apdu.setIncomingAndReceive();
            rsaPubKey = (RSAPublicKey) rsaKey.getPublic();
            rsaPubKey.getModulus(buf, (short) 0);
            apdu.setOutgoingAndSend((short) 0, (short) 256);
            break;
        case (byte)0x03: //encrypt by private key
            short len = apdu.setIncomingAndReceive();
            mDigest.reset();
            hash_len = mDigest.doFinal(buf, (short) ISO7816.OFFSET_CDATA, len, Hash, (short)0);
            rsaCipher.init(rsaKey.getPrivate(), Cipher.MODE_ENCRYPT);
            sign_len = rsaCipher.doFinal(Hash, (short) 0, hash_len, Sign, (short)0);
            Util.arrayCopy(Hash, (short)0, buf, (short)0, hash_len);
            apdu.setOutgoingAndSend((short) 0, hash_len);
            break;
        default:
            ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
        }
    }

}

我成功创建了密钥,但是当我尝试进行加密时,在6F 00行中返回sign_len = rsaCipher.doFinal(Hash, (short) 0, hash_len, Sign, (short)0);

现在,我的第一个问题是如何找出6F 00 SW的含义,即如何在代码中处理运行时异常,而第二个问题是如何解决它以及问题是什么?我在哪里弄错了? (我正在使用Java Card Kit 3.0.4。)

1 个答案:

答案 0 :(得分:2)

您正在使用Cipher.ALG_RSA_NOPAD算法(也称为“原始RSA”或“ X.509 RSA”),该算法仅执行模块化幂运算而没有任何填充。

此算法要求输入的长度与RSA密钥模数(2048位)相同 / 256字节),并且在没有正确输入填充的情况下使用不安全

使用Cipher.ALG_RSA_PKCS1_OAEP(如果您的卡支持)或Cipher.ALG_RSA_PKCS1进行RSA加密。


由于未捕获CryptoException而给出了状态字6F 00(请参阅Cipher.doFinal()的文档)。您可能想用try { ... } catch (CryptoException e) { ... }包围代码,并获得有关使用CardRuntimeException.getReason()发生的问题的更多详细信息。


注意:在您的代码中,您正在加密SHA-256数据散列,这没有多大意义-您是否要对数据签名?您应该改用Signature.ALG_RSA_SHA_256_PKCS1_PSSSignature.ALG_RSA_SHA_256_PKCS1(请注意,在这种情况下您无需进行哈希处理,因为在签名计算期间会计算SHA-256)。

祝你好运!