我正在编写Java Applet。我需要使用APDU Command将预生成的RSAPrivateCrtKey
上传到applet。
在我的电脑中,我正在生成密钥。接下来,我在privateKeyBuffer
中序列化此密钥:
keyPair = new KeyPair(KeyPair.ALG_RSA_CRT, KeyBuilder.LENGTH_RSA_512);
keyPair.genKeyPair();
rsaPrivateKey = (RSAPrivateCrtKey) keyPair.getPrivate();
byte[] privateKeyBuffer = new byte[165];
short lengthDP1 = rsaPrivateKey.getDP1(privateKeyBuffer, 0);
offset += lengthDP1;
short lengthDQ1 = rsaPrivateKey.getDQ1(privateKeyBuffer, offset);
offset += lengthDQ1;
short lengthP = rsaPrivateKey.getP(privateKeyBuffer, offset);
offset += lengthP;
short lengthQ = rsaPrivateKey.getQ(privateKeyBuffer, offset);
offset += lengthQ;
short lengthPQ = rsaPrivateKey.getPQ(privateKeyBuffer, offset);
生成缓冲区后,我应该将每个数组元素转换为十六进制,然后使用APDU发送,最后在applet中恢复我的私钥,但在privateKeyBuffer
中我们有负数:
37,65,-96,-110,38,6,-2,73,-37,28,120,-90... (etc)
我应该如何将它们转换为十六进制并保持APDU正确(因为我知道只允许正数)或者可能有另一种方法将密钥推送到JavaCard?
有什么想法吗?
答案 0 :(得分:5)
您只需将字节数组复制到APDU缓冲区并发送即可。它会起作用。
final byte[] apduBuffer = apdu.getBuffer();
Util.arrayCopyNonAtomic(privateKeyBuffer, (short) 0, apduBuffer, (short) 0, (short) privateKeyBuffer.length);
apdu.setOutgoingAndSend((short) 0, (short) privateKeyBuffer.length);
您根本不必考虑十六进制值和正/负数!当您发送一个字节= 8位时,您根本不处理它的数字表示或含义。
额外说明:
byte[] privateKeyBuffer = new byte[165];
通常是一个坏主意。你根本不需要这个缓冲区。您可以将键值直接复制到APDU缓冲区中,节省一些持久性内存并使您的applet更快。
基于亲爱的@ Abraham评论的另一个注释:
令人遗憾的是,您在Java Card中可能面临的正面/负面数字的唯一问题是Java Card byte
已签名。这意味着它的值总是在[-128,127]范围内,尽管人们常常忘记它:
final byte b = getSomeByteValue(); //from APDU buffer, for example
if (b == 0x80) { //always false!
//this never happens!
}
如果您想将byte
理解为无符号(范围[0,255]),则必须以这种方式将其转换为short
:
final byte b = getSomeByteValue(); //from APDU buffer, for example
final short unsignedValue = (short) (b & 0xFF);
if (unsignedValue == 0x80) { //correct!
//can happen
}