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)。
祝你好运!
我已经写了一个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)。
祝你好运!