【问题标题】:RSA Encrytion throws an exception intermittently on JavaCardRSA Encrytion 在 JavaCard 上间歇性地抛出异常
【发布时间】:2016-06-27 16:45:19
【问题描述】:

我编写了一个程序,使用我的 Java 卡上的 RSA 公钥加密 10 字节随机数。每次卡接收到该 APDU 命令时都会生成随机数,并且由于我的小程序中相关的密码对象块大小为 2048 位,因此我在此 10 字节随机数的末尾附加了 242 个字节的 0x00 到使其成为256 字节长度。

问题是有时响应是带有05 值的加密异常。如您所知以及提到的 JC API 文档:

0x05 = ILLEGAL_USE

public static final short ILLEGAL_USE

此原因码用于 表示签名或密码算法不填充 传入消息和输入消息不是块对齐的。

由于输入长度在我的小程序中是固定的,我无法解决我的问题!

这是我的小程序的相关部分:

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

有人知道我的小程序有什么问题吗?

【问题讨论】:

  • 你使用什么 ALG_?
  • @vojta asymCipher = Cipher.getInstance(Cipher.ALG_RSA_NOPAD, false);

标签: java cryptography rsa javacard


【解决方案1】:

您在错误的一侧填充。 RSA 适用于最大模数大小的大端编码数字。通常的填充机制(通常的 RSA 安全性需要)通过 left 填充来工作,其值严格小于模数。

所以基本上你的填充挑战被视为一个编码数字,当转换时,它有时大于模数。当这种情况发生时,RSA 例程将不接受它。

向左填充零字节应该可以解决这个问题。或者,您可以确保将质询的最高位掩码为零 (& 0x7F)。

【讨论】:

  • 谢谢您,亲爱的 Bodewes 先生。我有点困惑。我可以请你解释一下吗?我认为正如我指出的算法是 ALG_RSA_NOPAD,那么密码必须将挑战视为 256 字节数据,而不是填充或编码数据。对?那么为什么会有任何转换呢?您的回答是否意味着 ALG_RSA_NOPAD,不能加密某些形式的 256 字节数据?
  • 你在中指的是哪种转换...以及转换时,有时...
  • 是的,ALG_RSA_NOPAD 不能这样做。原因很简单;如果您对比模数更高的数字执行模运算,那么显然该值将被视为(在这种情况下)number - N。所以当你恢复它时,你也会得到number - N而不是number。这是 RSA 的一个基本问题。当然,这取决于解码数字到底有多大。如果它以FF hex 开头,那么它几乎肯定大于模数。如果它以 7F 十六进制或更低开头,那么它必须更小(因为总是设置模数的最高位)(试试这个)。
  • 知道了,谢谢:)。模数是否必须始终设置最高位?私人指数也是强制性的吗?我使用 Python 生成了一个 2048 位长度的 RSA 密钥对,以将它们加载到我的 Java 卡中。对于其中一个,最高的半字节是0!它有什么问题吗?我的意思是,我应该将卡外生成的密钥对过滤为仅模数和私有指数最高位 = 1 的密钥对吗?
  • 必须设置模数最高位。私有指数可以以任意数量个前导零开头(当然,每个下一个零的可能性较小)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-19
  • 2019-12-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多