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

What is the problem with java card RSA encryption doFinal method?

我已经写了一个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 卡片套件 3.0.4。)

您使用的是 Cipher.ALG_RSA_NOPAD 算法(也称为 'raw RSA' 或 'X.509 RSA'),该算法只进行模幂运算,没有任何填充。

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

使用 Cipher.ALG_RSA_PKCS1_OAEP (if your card supports it) or Cipher.ALG_RSA_PKCS1 进行 RSA 加密。


由于未捕获 CryptoException (see documentation for Cipher.doFinal()). You might want to surround your code with try { ... } catch (CryptoException e) { ... } and get more details about problem that has happened using CardRuntimeException.getReason(),状态字 6F 00 已给出。


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

祝你好运!