我已经编写了一个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。)
答案 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_PSS或Signature.ALG_RSA_SHA_256_PKCS1(请注意,在这种情况下您无需进行哈希处理,因为在签名计算期间会计算SHA-256)。
祝你好运!