RSA 加密在 JavaCard 上间歇性地抛出异常
RSA Encrytion throws an exception intermittently on JavaCard
我编写了一个程序,使用 Java 卡上的 RSA public 密钥加密 10
字节的随机数。每次卡收到该 APDU 命令时都会生成随机数,并且由于我的小程序中相关的密码对象块大小为 2048 位,所以我在这个 10
末尾附加了 242 个字节的 0x00
字节随机数,使其长度为 256
字节。
问题是有时响应是具有 05
值的加密异常。如您所知以及 JC API 文件中提到的:
0x05
= ILLEGAL_USE
public static final short ILLEGAL_USE
This reason code is used to
indicate that the signature or cipher algorithm does not pad the
incoming message and the input message is not block aligned.
由于我的小程序中输入长度是固定的,我无法解决我的问题!
这是我的小程序的相关部分:
protected final void getEncChallenge(APDU apdu) {
random.generateData(generatedChall, (short) 0, (short) 10);
initAsymCipher(ENTITY_BOB, MODE_ENC);
Util.arrayCopy(generatedChall, (short) 0, transientData, (short) 0, (short) 10);
Util.arrayFillNonAtomic(transientData, (short) 10, (short) 246, (byte) 0x00);
rsaCrypto(transientData, persistentData);
apdu.setOutgoing();
apdu.setOutgoingLength((short) 256);
apdu.sendBytesLong(persistentData, (short) 0, (short) 256);
}
protected final void rsaCrypto(byte[] inData, byte[] outData) {
try{
asymCipher.doFinal(inData, (short) 0, (short) 256, outData, (short) 0);
}catch(CryptoException e){
short reason = e.getReason();
ISOException.throwIt((short)(0x6d00 | reason));
}
}
这是回复:
transientData ---> APDU Response
---------------------------------
80 ..(Eight Random Bytes).. BD ..(246 bytes of "0x00").. ---> OK (i.e. 256 byte encrypted data)
EO ..(Eight Random Bytes).. 64 ..(246 bytes of "0x00").. ---> 6D05
02 ..(Eight Random Bytes).. B3 ..(246 bytes of "0x00").. ---> OK
CB ..(Eight Random Bytes).. 35 ..(246 bytes of "0x00").. ---> 6D05
17 ..(Eight Random Bytes).. 97 ..(246 bytes of "0x00").. ---> OK
0C ..(Eight Random Bytes).. 0C ..(246 bytes of "0x00").. ---> OK
D3 ..(Eight Random Bytes).. 91 ..(246 bytes of "0x00").. ---> 6D05
86 ..(Eight Random Bytes).. E2 ..(246 bytes of "0x00").. ---> OK
C2 ..(Eight Random Bytes).. 23 ..(246 bytes of "0x00").. ---> 6D05
有谁知道我的小程序有什么问题吗?
你在错误的一边填充。 RSA 适用于最大模数大小的大端编码数字。通常的填充机制(这是通常的 RSA 安全性所必需的)通过 left 填充来工作,该值严格小于模数。
所以基本上你填充的挑战被视为一个编码数字,并且在转换时,它有时大于模数。当发生这种情况时,RSA 例程将不会接受它。
向左填充零字节应该可以解决这个问题。或者,您可以确保挑战的最高位被屏蔽为零 (& 0x7F
)。
我编写了一个程序,使用 Java 卡上的 RSA public 密钥加密 10
字节的随机数。每次卡收到该 APDU 命令时都会生成随机数,并且由于我的小程序中相关的密码对象块大小为 2048 位,所以我在这个 10
末尾附加了 242 个字节的 0x00
字节随机数,使其长度为 256
字节。
问题是有时响应是具有 05
值的加密异常。如您所知以及 JC API 文件中提到的:
0x05
= ILLEGAL_USEpublic static final short ILLEGAL_USE
This reason code is used to indicate that the signature or cipher algorithm does not pad the incoming message and the input message is not block aligned.
由于我的小程序中输入长度是固定的,我无法解决我的问题!
这是我的小程序的相关部分:
protected final void getEncChallenge(APDU apdu) {
random.generateData(generatedChall, (short) 0, (short) 10);
initAsymCipher(ENTITY_BOB, MODE_ENC);
Util.arrayCopy(generatedChall, (short) 0, transientData, (short) 0, (short) 10);
Util.arrayFillNonAtomic(transientData, (short) 10, (short) 246, (byte) 0x00);
rsaCrypto(transientData, persistentData);
apdu.setOutgoing();
apdu.setOutgoingLength((short) 256);
apdu.sendBytesLong(persistentData, (short) 0, (short) 256);
}
protected final void rsaCrypto(byte[] inData, byte[] outData) {
try{
asymCipher.doFinal(inData, (short) 0, (short) 256, outData, (short) 0);
}catch(CryptoException e){
short reason = e.getReason();
ISOException.throwIt((short)(0x6d00 | reason));
}
}
这是回复:
transientData ---> APDU Response
---------------------------------
80 ..(Eight Random Bytes).. BD ..(246 bytes of "0x00").. ---> OK (i.e. 256 byte encrypted data)
EO ..(Eight Random Bytes).. 64 ..(246 bytes of "0x00").. ---> 6D05
02 ..(Eight Random Bytes).. B3 ..(246 bytes of "0x00").. ---> OK
CB ..(Eight Random Bytes).. 35 ..(246 bytes of "0x00").. ---> 6D05
17 ..(Eight Random Bytes).. 97 ..(246 bytes of "0x00").. ---> OK
0C ..(Eight Random Bytes).. 0C ..(246 bytes of "0x00").. ---> OK
D3 ..(Eight Random Bytes).. 91 ..(246 bytes of "0x00").. ---> 6D05
86 ..(Eight Random Bytes).. E2 ..(246 bytes of "0x00").. ---> OK
C2 ..(Eight Random Bytes).. 23 ..(246 bytes of "0x00").. ---> 6D05
有谁知道我的小程序有什么问题吗?
你在错误的一边填充。 RSA 适用于最大模数大小的大端编码数字。通常的填充机制(这是通常的 RSA 安全性所必需的)通过 left 填充来工作,该值严格小于模数。
所以基本上你填充的挑战被视为一个编码数字,并且在转换时,它有时大于模数。当发生这种情况时,RSA 例程将不会接受它。
向左填充零字节应该可以解决这个问题。或者,您可以确保挑战的最高位被屏蔽为零 (& 0x7F
)。