将 ECPublicKey 从 Java 恢复到 JavaCard
Recovering an ECPublicKey from Java to JavaCard
这个问题与我昨天问的问题有关:
我有同样的问题,但方式相反:
将 public 密钥从我的卡发送到我的计算机后(根据 ANSI X9.62,该点表示为未压缩形式的八位字节字符串)我可以恢复相应的密钥。
但是如果我从我的电脑发送它,我无法在我的卡上恢复它,我得到一个 CryptoException
(ILLEGAL_VALUE
) 这意味着表格不正确或要点与曲线参数不匹配。
我已验证,我的参数定义正确,我以正确的形式发送了点...
为了调试它,我尝试将 public 密钥从我的卡发送到我的计算机,然后重新发送到我的卡以尝试恢复它(因此我确定参数没问题)。不管怎样,我仍然遇到同样的错误...
为了说明我的问题,我post对应的代码:
在卡端 - 发送 public 密钥 :
pubKey = (ECPublicKey) KeyBuilder.buildKey(
KeyBuilder.TYPE_EC_FP_PUBLIC, (short) 0x0100, false);
pubKey.setFieldFP(p, (short) 0x0001, (short) 0x0020);
pubKey.setA(a, (short) 0x0001, (short) 0x0020);
pubKey.setB(b, (short) 0x0000, (short) 0x0020);
pubKey.setR(r, (short) 0x0001, (short) 0x0020);
pubKey.setG(g, (short) 0x0000, (short) g.length);
privKey = (ECPrivateKey) KeyBuilder.buildKey(
KeyBuilder.TYPE_EC_FP_PRIVATE, (short) 0x0100, false);
KeyPair keypair = new KeyPair(pubKey, privKey);
keypair.genKeyPair();
short len = pubKey.getW(apduBuffer, (short) 0x0000);
setOutgoingAndSend((short) 0x0000, len);
发送的响应是:
APDU <<<: 04C2B28FBE96C5EAC1E81750E9B288B0BD8357D3AED4EA39413197D734B145EBC92F3FD7489B9A7EF4C8A956427668851F0BB3A55D5C7B9033A533F21463E1A2139000
所以第一个坐标是x = C2B28FBE96C5EAC1E81750E9B288B0BD8357D3AED4EA39413197D734B145EBC9
,第二个坐标是y = 2F3FD7489B9A7EF4C8A956427668851F0BB3A55D5C7B9033A533F21463E1A213
在计算机端 - 恢复密钥并重新发送:
byte[] x = new byte[32];
byte[] y = new byte[32];
System.arraycopy(W, 1, x, 0, x.length);
System.arraycopy(W, 1 + x.length, y, 0, y.length);
ECPublicKeySpec pub = new ECPublicKeySpec(new ECPoint(new BigInteger(1,x), new BigInteger(1,y)), ecParamSpec);
ECPublicKey ecPubKey = (ECPublicKey) kf.generatePublic(pub);
byte[] k_x = ecPubKey.getEncoded();
byte[] tmp = new byte[70];
tmp[0] = (byte) 0x80;
tmp[1] = (byte) 0x20;
tmp[2] = (byte) 0x00;
tmp[3] = (byte) 0x00;
tmp[4] = (byte) (65);
System.arraycopy(k_x, k_x.length - 65, tmp, 5,65);
sendApdu(cardChan, tmp);
发送的APDU是:
APDU >>>: 802000004104C2B28FBE96C5EAC1E81750E9B288B0BD8357D3AED4EA39413197D734B145EBC92F3FD7489B9A7EF4C8A956427668851F0BB3A55D5C7B9033A533F21463E1A213
因此我们可以很容易地看到发送的数据与之前收到的完全相同
最后,在卡端,我有以下代码来恢复密钥:
pubKey.setW(apduBuffer, ISO7816.OFFSET_CDATA,
ISO7816.OFFSET_LC);
len = pubKey.getW(apduBuffer, (short) 0x0000);
setOutgoingAndSend((short) 0x0000, len);
但我得到 APDU >>>: 0401
这意味着 CryptoException.ILLEGAL_VALUE
在指令
处引发
pubKey.setW(apduBuffer, ISO7816.OFFSET_CDATA,
ISO7816.OFFSET_LC);
知道我发送的内容与我通过 pubKey.getW()
收到的内容相同,它怎么会引发异常?
问题可能是:
pubKey.setW(apduBuffer, ISO7816.OFFSET_CDATA, ISO7816.OFFSET_LC);
首先,你不应该直接使用ISO7816.OFFSET_CDATA
和ISO7816.OFFSET_LC
。命令数据的位置用APDU.getOffsetCData
,用APDU.setIncomingAndReceive
得到Nc值(Lc是Nc值的编码)。
目前您的代码失败,因为您使用 ISO7816.OFFSET_LC
而不是 setIncomingAndReceive
的输出。 ISO7816.OFFSET_LC
是一个设置为值 4 的常量。您的 public 点比那个大。
这个问题与我昨天问的问题有关:
我有同样的问题,但方式相反: 将 public 密钥从我的卡发送到我的计算机后(根据 ANSI X9.62,该点表示为未压缩形式的八位字节字符串)我可以恢复相应的密钥。
但是如果我从我的电脑发送它,我无法在我的卡上恢复它,我得到一个 CryptoException
(ILLEGAL_VALUE
) 这意味着表格不正确或要点与曲线参数不匹配。
我已验证,我的参数定义正确,我以正确的形式发送了点...
为了调试它,我尝试将 public 密钥从我的卡发送到我的计算机,然后重新发送到我的卡以尝试恢复它(因此我确定参数没问题)。不管怎样,我仍然遇到同样的错误...
为了说明我的问题,我post对应的代码:
在卡端 - 发送 public 密钥 :
pubKey = (ECPublicKey) KeyBuilder.buildKey(
KeyBuilder.TYPE_EC_FP_PUBLIC, (short) 0x0100, false);
pubKey.setFieldFP(p, (short) 0x0001, (short) 0x0020);
pubKey.setA(a, (short) 0x0001, (short) 0x0020);
pubKey.setB(b, (short) 0x0000, (short) 0x0020);
pubKey.setR(r, (short) 0x0001, (short) 0x0020);
pubKey.setG(g, (short) 0x0000, (short) g.length);
privKey = (ECPrivateKey) KeyBuilder.buildKey(
KeyBuilder.TYPE_EC_FP_PRIVATE, (short) 0x0100, false);
KeyPair keypair = new KeyPair(pubKey, privKey);
keypair.genKeyPair();
short len = pubKey.getW(apduBuffer, (short) 0x0000);
setOutgoingAndSend((short) 0x0000, len);
发送的响应是:
APDU <<<: 04C2B28FBE96C5EAC1E81750E9B288B0BD8357D3AED4EA39413197D734B145EBC92F3FD7489B9A7EF4C8A956427668851F0BB3A55D5C7B9033A533F21463E1A2139000
所以第一个坐标是x = C2B28FBE96C5EAC1E81750E9B288B0BD8357D3AED4EA39413197D734B145EBC9
,第二个坐标是y = 2F3FD7489B9A7EF4C8A956427668851F0BB3A55D5C7B9033A533F21463E1A213
在计算机端 - 恢复密钥并重新发送:
byte[] x = new byte[32];
byte[] y = new byte[32];
System.arraycopy(W, 1, x, 0, x.length);
System.arraycopy(W, 1 + x.length, y, 0, y.length);
ECPublicKeySpec pub = new ECPublicKeySpec(new ECPoint(new BigInteger(1,x), new BigInteger(1,y)), ecParamSpec);
ECPublicKey ecPubKey = (ECPublicKey) kf.generatePublic(pub);
byte[] k_x = ecPubKey.getEncoded();
byte[] tmp = new byte[70];
tmp[0] = (byte) 0x80;
tmp[1] = (byte) 0x20;
tmp[2] = (byte) 0x00;
tmp[3] = (byte) 0x00;
tmp[4] = (byte) (65);
System.arraycopy(k_x, k_x.length - 65, tmp, 5,65);
sendApdu(cardChan, tmp);
发送的APDU是:
APDU >>>: 802000004104C2B28FBE96C5EAC1E81750E9B288B0BD8357D3AED4EA39413197D734B145EBC92F3FD7489B9A7EF4C8A956427668851F0BB3A55D5C7B9033A533F21463E1A213
因此我们可以很容易地看到发送的数据与之前收到的完全相同
最后,在卡端,我有以下代码来恢复密钥:
pubKey.setW(apduBuffer, ISO7816.OFFSET_CDATA,
ISO7816.OFFSET_LC);
len = pubKey.getW(apduBuffer, (short) 0x0000);
setOutgoingAndSend((short) 0x0000, len);
但我得到 APDU >>>: 0401
这意味着 CryptoException.ILLEGAL_VALUE
在指令
pubKey.setW(apduBuffer, ISO7816.OFFSET_CDATA,
ISO7816.OFFSET_LC);
知道我发送的内容与我通过 pubKey.getW()
收到的内容相同,它怎么会引发异常?
问题可能是:
pubKey.setW(apduBuffer, ISO7816.OFFSET_CDATA, ISO7816.OFFSET_LC);
首先,你不应该直接使用ISO7816.OFFSET_CDATA
和ISO7816.OFFSET_LC
。命令数据的位置用APDU.getOffsetCData
,用APDU.setIncomingAndReceive
得到Nc值(Lc是Nc值的编码)。
目前您的代码失败,因为您使用 ISO7816.OFFSET_LC
而不是 setIncomingAndReceive
的输出。 ISO7816.OFFSET_LC
是一个设置为值 4 的常量。您的 public 点比那个大。