gpt4 book ai didi

java - 验证 JavaCard 中的签名字符串返回 `0x6F00` 状态字

转载 作者:行者123 更新时间:2023-12-01 16:56:31 25 4
gpt4 key购买 nike

我编写了以下 JavaCard 程序,用于根据 ALG_RSA_SHA_256_PKCS1 算法对 4 字节长度的数据进行签名,并验证此签名:

package fileSigner;

import javacard.framework.*;
import javacard.security.KeyPair;
import javacard.security.RSAPrivateKey;
import javacard.security.RSAPublicKey;
import javacard.security.Signature;

public class FileSigning extends Applet {

//Proprietary Status Words
private static final short SIGN_VERIFIED_SW = (short) 0x6701;
private static final short SIGN_NOT_VERIFIED_SW = (short) 0x6702;

//Proprietary Instructions
private static final byte SIGN_INS = (byte) 0x00;
private static final byte VERIFY_INS = (byte) 0x02;
private static final byte RET_PUB_KEY_INS = (byte) 0x04;

//Required Objects
private static RSAPrivateKey privateKey;
private static RSAPublicKey publicKey;
private static KeyPair keyPair;
private static Signature signature;

public static void install(byte[] bArray, short bOffset, byte bLength) {
new FileSigning();
}

protected FileSigning() {
register();
keyPair = new KeyPair(KeyPair.ALG_RSA, (short) 1024);
keyPair.genKeyPair();
publicKey = (RSAPublicKey) keyPair.getPublic();
privateKey = (RSAPrivateKey) keyPair.getPrivate();
signature = Signature.getInstance(Signature.ALG_RSA_SHA_256_PKCS1, false);
}

public void process(APDU apdu) {
if (selectingApplet()) {
return;
}

byte[] buffer = apdu.getBuffer();

switch (buffer[ISO7816.OFFSET_INS]) {
case SIGN_INS:
signature.init(privateKey, Signature.MODE_SIGN);
byte[] dataSignature = JCSystem.makeTransientByteArray((short) 128, JCSystem.CLEAR_ON_RESET);
short signLen = signature.sign(buffer, ISO7816.OFFSET_CDATA, (byte) ISO7816.OFFSET_LC, dataSignature, (byte) 0);
Util.arrayCopyNonAtomic(dataSignature, (short) 0, buffer, (short) 0, signLen);
apdu.setOutgoingAndSend((short) 0, signLen);
break;

case VERIFY_INS:
signature.init(privateKey, Signature.MODE_VERIFY);
boolean isVerified = signature.verify(buffer, (short)ISO7816.OFFSET_CDATA, (short)0x80, buffer, (short)(ISO7816.OFFSET_CDATA + 0X80), (short)0X04);
if (isVerified) {
ISOException.throwIt(SIGN_VERIFIED_SW);
} else {
ISOException.throwIt(SIGN_NOT_VERIFIED_SW);
}
break;

case RET_PUB_KEY_INS:
break;

default:
ISOException.throwIt((short) ISO7816.SW_INS_NOT_SUPPORTED);
}
}
}

嗯,看起来它对于 sign 方法工作得很好。

例如,在下面我签名11223344:

C:\OpenSCTool:> OSC.exe -s 00a4040006010203040501 -s 000000000411223344
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 06 01 02 03 04 05 01
Received (SW1=0x90, SW2=0x00)
Sending: 00 00 00 00 04 11 22 33 44
Received (SW1=0x90, SW2=0x00):
7B EE DE 3E 16 D6 82 CF 67 53 CC AF 87 F3 4F 31 {..>....gS....O1
BB A6 66 B6 4E E3 F5 FD 0E 04 18 24 63 C1 98 D4 ..f.N......$c...
17 CC 56 DA A0 5F 78 4D A5 AE DF E4 A6 E0 35 B6 ..V.._xM......5.
F0 F3 59 45 1E 89 EE 02 69 15 8C 27 7B 10 94 02 ..YE....i..'{...
F1 C5 A4 1C F2 3C 1A 75 8A FC 89 4F 59 A4 D5 A0 .....<.u...OY...
84 C5 5E 70 F8 B7 80 10 3D D3 84 56 EC CB 1D 01 ..^p....=..V....
D2 F4 F0 F4 FD 91 5A 52 45 17 A7 08 9D 26 82 A7 ......ZRE....&..
E3 67 A6 2C D8 CC 7F 59 F1 98 4A 4F 5D 78 63 DD .g.,...Y..JO]xc.

但是我的 verify 方法有问题!

在下面我尝试验证上述签名:

C:\OpenSCTool:> OSC.exe -s 00a4040006010203040501 -s 00020000847BEEDE3E16D682CF6
753CCAF87F34F31BBA666B64EE3F5FD0E04182463C198D417CC56DAA05F784DA5AEDFE4A6E035B6F
0F359451E89EE0269158C277B109402F1C5A41CF23C1A758AFC894F59A4D5A084C55E70F8B780103
DD38456ECCB1D01D2F4F0F4FD915A524517A7089D2682A7E367A62CD8CC7F59F1984A4F5D7863DD1
1223344
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 06 01 02 03 04 05 01
Received (SW1=0x90, SW2=0x00)
Sending: 00 02 00 00 84 7B EE DE 3E 16 D6 82 CF 67 53 CC AF 87 F3 4F 31 BB A6 66
B6 4E E3 F5 FD 0E 04 18 24 63 C1 98 D4 17 CC 56 DA A0 5F 78 4D A5 AE DF E4 A6 E
0 35 B6 F0 F3 59 45 1E 89 EE 02 69 15 8C 27 7B 10 94 02 F1 C5 A4 1C F2 3C 1A 75
8A FC 89 4F 59 A4 D5 A0 84 C5 5E 70 F8 B7 80 10 3D D3 84 56 EC CB 1D 01 D2 F4 F0
F4 FD 91 5A 52 45 17 A7 08 9D 26 82 A7 E3 67 A6 2C D8 CC 7F 59 F1 98 4A 4F 5D 7
8 63 DD 11 22 33 44
Received (SW1=0x6F, SW2=0x00)
<小时/>

更新1:

我写错了

signature.init(privateKey, Signature.MODE_VERIFY);

而不是

signature.init(publicKey, Signature.MODE_VERIFY);

VERIFY_INS部分。所以我纠正了它,现在输出如下:

C:\OpenSCTool:> OSC.exe -s 00a4040006010203040501 -s 000000000411223344
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 06 01 02 03 04 05 01
Received (SW1=0x90, SW2=0x00)
Sending: 00 00 00 00 04 11 22 33 44
Received (SW1=0x90, SW2=0x00):
73 87 1C 58 07 EB F5 55 42 E3 37 FC 84 3A CA 91 s..X...UB.7..:..
FB F4 4D AD 70 FC 43 84 C0 26 DC AE 03 47 28 F3 ..M.p.C..&...G(.
F6 77 6B 53 93 96 92 4B 66 C8 BA 05 0F 65 56 CE .wkS...Kf....eV.
0E 7A 56 DE 5A 9C FF 4C FB B5 82 33 81 22 BD BE .zV.Z..L...3."..
76 99 15 87 5D 9C 4C 5F 6A 75 38 99 A9 28 D6 45 v...].L_ju8..(.E
A5 F4 8C A2 AE 89 28 49 ED 72 14 FD 7E 3C 6A F4 ......(I.r..~<j.
EA C2 7C BD AB D3 B3 91 1C 24 E0 29 B4 9C 07 82 ..|......$.)....
32 B1 BF 00 A5 A0 82 48 C2 01 82 A1 90 5A 47 05 2......H.....ZG.

C:\OpenSCTool:> OSC.exe -s 00a4040006010203040501 -s 000200008473871C5807EBF5554
2E337FC843ACA91FBF44DAD70FC4384C026DCAE034728F3F6776B539396924B66C8BA050F6556CE0
E7A56DE5A9CFF4CFBB582338122BDBE769915875D9C4C5F6A753899A928D645A5F48CA2AE892849E
D7214FD7E3C6AF4EAC27CBDABD3B3911C24E029B49C078232B1BF00A5A08248C20182A1905A47051
1223344
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 06 01 02 03 04 05 01
Received (SW1=0x90, SW2=0x00)
Sending: 00 02 00 00 84 73 87 1C 58 07 EB F5 55 42 E3 37 FC 84 3A CA 91 FB F4 4D
AD 70 FC 43 84 C0 26 DC AE 03 47 28 F3 F6 77 6B 53 93 96 92 4B 66 C8 BA 05 0F 6
5 56 CE 0E 7A 56 DE 5A 9C FF 4C FB B5 82 33 81 22 BD BE 76 99 15 87 5D 9C 4C 5F
6A 75 38 99 A9 28 D6 45 A5 F4 8C A2 AE 89 28 49 ED 72 14 FD 7E 3C 6A F4 EA C2 7C
BD AB D3 B3 91 1C 24 E0 29 B4 9C 07 82 32 B1 BF 00 A5 A0 82 48 C2 01 82 A1 90 5
A 47 05 11 22 33 44
Received (SW1=0x67, SW2=0x02)

正如您在上面看到的,该卡无法验证它自己创建的签名。

<小时/>

更新数据2:

根据亲爱的 Maarten 先生的回答,我在程序中添加了 setIncomingAndReceive() 方法,如下所示:

public class FileSigning extends Applet {

//Proprietary Status Words
private static final short SIGN_VERIFIED_SW = (short) 0x6701;
private static final short SIGN_NOT_VERIFIED_SW = (short) 0x6702;

//Proprietary Instructions
private static final byte SIGN_INS = (byte) 0x00;
private static final byte VERIFY_INS = (byte) 0x02;
private static final byte RET_PUB_KEY_INS = (byte) 0x04;

//Required Objects
private static RSAPrivateKey privateKey;
private static RSAPublicKey publicKey;
private static KeyPair keyPair;
private static Signature signature;

public static void install(byte[] bArray, short bOffset, byte bLength) {
new FileSigning();
}

protected FileSigning() {
register();
keyPair = new KeyPair(KeyPair.ALG_RSA, (short) 1024);
keyPair.genKeyPair();
publicKey = (RSAPublicKey) keyPair.getPublic();
privateKey = (RSAPrivateKey) keyPair.getPrivate();
signature = Signature.getInstance(Signature.ALG_RSA_SHA_256_PKCS1, false);
}

public void process(APDU apdu) {
if (selectingApplet()) {
return;
}

byte[] buffer = apdu.getBuffer();
byte[] incomingData = JCSystem.makeTransientByteArray((short) 256, JCSystem.CLEAR_ON_RESET);
short bytesLeft;
short readCount;
short offSet = 0x00;

switch (buffer[ISO7816.OFFSET_INS]) {
case SIGN_INS:
signature.init(privateKey, Signature.MODE_SIGN);

bytesLeft = (short) (buffer[ISO7816.OFFSET_LC] & 0x00FF);
readCount = apdu.setIncomingAndReceive();
while (bytesLeft > 0) {
Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_CDATA, incomingData, offSet, readCount);
bytesLeft -= readCount;
offSet += readCount;
readCount = apdu.receiveBytes(ISO7816.OFFSET_CDATA);
}
short signLen = signature.sign(buffer, ISO7816.OFFSET_CDATA, (byte) ISO7816.OFFSET_LC, incomingData, (byte) 0);
Util.arrayCopyNonAtomic(incomingData, (short) 0, buffer, (short) 0, signLen);
apdu.setOutgoingAndSend((short) 0, signLen);
break;

case VERIFY_INS:
signature.init(publicKey, Signature.MODE_VERIFY);

bytesLeft = (short) (buffer[ISO7816.OFFSET_LC] & 0x00FF);
readCount = apdu.setIncomingAndReceive();
while (bytesLeft > 0) {
Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_CDATA, incomingData, offSet, readCount);
bytesLeft -= readCount;
offSet += readCount;
readCount = apdu.receiveBytes(ISO7816.OFFSET_CDATA);
}

boolean isVerified = signature.verify(incomingData, (short) 0, (short) 0x80, incomingData, (short) 0X80, (short) 0X04);
if (isVerified) {
ISOException.throwIt(SIGN_VERIFIED_SW);
} else {
ISOException.throwIt(SIGN_NOT_VERIFIED_SW);
}
break;

case RET_PUB_KEY_INS:
break;

default:
ISOException.throwIt((short) ISO7816.SW_INS_NOT_SUPPORTED);
}
}
}

嗯,看来还是有问题:

C:\OpenSCTool:> OSC.exe -s 00a4040006010203040501 -s 000000000411223344
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 06 01 02 03 04 05 01
Received (SW1=0x90, SW2=0x00)
Sending: 00 00 00 00 04 11 22 33 44
Received (SW1=0x90, SW2=0x00):
75 08 A1 D0 D7 C6 9E 60 3E 78 F0 3A 6B 50 A0 D8 u......`>x.:kP..
80 2E F3 3E 29 2C 0E 13 15 DC 78 74 14 33 4D 36 ...>),....xt.3M6
7E 5E C5 65 67 92 A0 7E B4 0A A1 C0 DE F2 63 44 ~^.eg..~......cD
84 E3 20 CC 48 96 6E B2 28 9A 1B 07 53 ED 70 AF .. .H.n.(...S.p.
8E 01 24 E0 B9 80 89 98 ED B7 A0 BB 81 37 81 22 ..$..........7."
1C C8 54 A4 91 D0 8D 83 12 31 41 1A 56 76 23 D4 ..T......1A.Vv#.
09 5C BD 1E 75 A6 D8 3A 57 15 D8 5E B0 B9 B5 E7 .\..u..:W..^....
32 46 BE C5 A8 58 79 1B D4 C5 20 DD 48 D3 70 CB 2F...Xy... .H.p.

C:\OpenSCTool:> OSC.exe -s 00a4040006010203040501 -s 00020000847508A1D0D7C69E603
E78F03A6B50A0D8802EF33E292C0E1315DC787414334D367E5EC5656792A07EB40AA1C0DEF263448
4E320CC48966EB2289A1B0753ED70AF8E0124E0B9808998EDB7A0BB813781221CC854A491D08D831
231411A567623D4095CBD1E75A6D83A5715D85EB0B9B5E73246BEC5A858791BD4C520DD48D370CB1
1223344
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 06 01 02 03 04 05 01
Received (SW1=0x90, SW2=0x00)
Sending: 00 02 00 00 84 75 08 A1 D0 D7 C6 9E 60 3E 78 F0 3A 6B 50 A0 D8 80 2E F3
3E 29 2C 0E 13 15 DC 78 74 14 33 4D 36 7E 5E C5 65 67 92 A0 7E B4 0A A1 C0 DE F
2 63 44 84 E3 20 CC 48 96 6E B2 28 9A 1B 07 53 ED 70 AF 8E 01 24 E0 B9 80 89 98
ED B7 A0 BB 81 37 81 22 1C C8 54 A4 91 D0 8D 83 12 31 41 1A 56 76 23 D4 09 5C BD
1E 75 A6 D8 3A 57 15 D8 5E B0 B9 B5 E7 32 46 BE C5 A8 58 79 1B D4 C5 20 DD 48 D
3 70 CB 11 22 33 44
Received (SW1=0x67, SW2=0x02)

最佳答案

您的 verify() 参数可能已交换(假设您在传入数据中有 [128 字节签名][4 字节数据]):

boolean isVerified = signature.verify(incomingData, (short)0x80, (short) 4, incomingData, (short)0, (short)0x80);

您的 java 卡代码需要一些改进,例如 dataSignature/incomingData 缓冲区应该在构造函数中只分配一次(并且 CLEAR_ON_DESELECT 就足够了)。

关于java - 验证 JavaCard 中的签名字符串返回 `0x6F00` 状态字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32034283/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com