2
我寫了一段代碼來散列和rsa加密(以某種方式簽名)發送給java卡的數據。如何從我的RSA Sign中獲得正確的結果?
這是Java卡代碼:
public class HelloWorldApplet extends Applet {
final static byte APLET_CLA = (byte)0x80;
final static byte INITIALIZE = (byte)0x00;
final static byte SIGN = (byte)0x01;
final static byte HASHVERIFY = (byte)0x07;
final static byte GETHASH = (byte)0x08;
final static short SW_WRONG_DATA_LENGTH = 0x6300;
final static short SW_KEY_NOT_INITIALIZED = 0x6301;
final static short SW_KEY_IS_INITIALIZED = 0x6302;
final static short SW_KEY_IS_NOT_INITIALIZED = 0x6303;
final static short SW_INCORRECT_PARAMETER = 0x6304;
public static byte[] Message;
public static short message_len = 0;
public static short hashLen = 0;
public static short signLen = 0;
public static boolean key_initialization_flag256 = false;
public static boolean key_initialization_flag128 = false;
// use unpadded RSA cipher for signing
Cipher cipherRSA256 = Cipher.getInstance(Cipher.ALG_RSA_NOPAD, false);
Cipher cipherRSA128 = Cipher.getInstance(Cipher.ALG_RSA_NOPAD, false);
KeyPair rsaPair256 = new KeyPair(KeyPair.ALG_RSA_CRT, KeyBuilder.LENGTH_RSA_2048);
KeyPair rsaPair128 = new KeyPair(KeyPair.ALG_RSA_CRT, KeyBuilder.LENGTH_RSA_1024);
RSAPrivateCrtKey rsaKeyPriv256;
RSAPrivateCrtKey rsaKeyPriv128;
RSAPublicKey rsaKeyPub256;
RSAPublicKey rsaKeyPub128;
byte[] hashBuffer = JCSystem.makeTransientByteArray((short)256, JCSystem.CLEAR_ON_DESELECT);
byte[] signBuffer = JCSystem.makeTransientByteArray((short)256, JCSystem.CLEAR_ON_DESELECT);
byte[] dataBuffer = JCSystem.makeTransientByteArray((short)256, JCSystem.CLEAR_ON_DESELECT);
MessageDigest md = MessageDigest.getInstance(MessageDigest.ALG_SHA_256, false);
public static void install(byte[] bArray, short bOffset, byte bLength)
{
Message = new byte[256];
new HelloWorldApplet().register(bArray, (short) (bOffset + 1), bArray[bOffset]);
}
public void process(APDU apdu)
{
if (selectingApplet())
{
return;
}
byte[] buffer = apdu.getBuffer();
if (buffer[ISO7816.OFFSET_CLA] == APPLET_CLA) {
switch (buffer[ISO7816.OFFSET_INS]) {
case INITIALIZE:
// generate a new key
initialize(apdu);
break;
case SIGN:
// sign a given incoming message
sign_message(apdu);
break;
case HASHVERIFY:
verify_hash(apdu);
break;
case GETHASH:
get_hash(apdu);
break;
default:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
} else {
ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
}
}
public void initialize(APDU apdu)
{
byte[] buffer = apdu.getBuffer();
switch(buffer[ISO7816.OFFSET_P1]) {
case 0x00: // gen 256 byte RSA key (P1=00)
if (key_initialization_flag256)
ISOException.throwIt(SW_KEY_IS_INITIALIZED);
rsaPair256.genKeyPair();
rsaKeyPriv256 = (RSAPrivateCrtKey) rsaPair256.getPrivate();
rsaKeyPub256 = (RSAPublicKey) rsaPair256.getPublic();
key_initialization_flag256 = true;
break;
case 0x01: // gen 128 byte RSA key (P1=01)
if (key_initialization_flag128)
ISOException.throwIt(SW_KEY_IS_INITIALIZED);
rsaPair128.genKeyPair();
rsaKeyPriv128 = (RSAPrivateCrtKey) rsaPair128.getPrivate();
rsaKeyPub128 = (RSAPublicKey) rsaPair128.getPublic();
key_initialization_flag128 = true;
break;
}
}
// P1=0 for modulus, P1=1 for exponent
private void getPublicRSA(APDU apdu)
{
byte[] buffer = apdu.getBuffer();
short length = 0;
switch (buffer[ISO7816.OFFSET_P1])
{
case 0x00: // 256 byte RSA (P1)
if (!key_initialization_flag256)
ISOException.throwIt(SW_KEY_IS_INITIALIZED);
switch (buffer[ISO7816.OFFSET_P2]) {
case 0x00: // get the modulus (P2)
length = rsaKeyPub256.getModulus(buffer, (short) 0);
break;
case 0x01: // get the exponent (P2)
length = rsaKeyPub256.getExponent(buffer, (short) 0);
break;
default:
ISOException.throwIt(SW_INCORRECT_PARAMETER);
break;
}
break;
case 0x01: // 128 byte RSA (P1)
if (!key_initialization_flag128)
ISOException.throwIt(SW_KEY_IS_INITIALIZED);
switch (buffer[ISO7816.OFFSET_P2]) {
case 0x00: // get the modulus (P2)
length = rsaKeyPub128.getModulus(buffer, (short) 0);
break;
case 0x01: // get the exponent (P2)
length = rsaKeyPub128.getExponent(buffer, (short) 0);
break;
default:
ISOException.throwIt(SW_INCORRECT_PARAMETER);
break;
}
break;
default:
ISOException.throwIt(SW_INCORRECT_PARAMETER);
}
apdu.setOutgoingAndSend((short) 0, length);
}
public void sign_message(APDU apdu)
{
byte[] buffer = apdu.getBuffer();
switch(message_len) {
case 256:
if(!key_initialization_flag256)
ISOException.throwIt(SW_KEY_IS_NOT_INITIALIZED);
cipherRSA256.init(rsaPair256.getPrivate(), Cipher.MODE_ENCRYPT);
Util.arrayCopyNonAtomic(Message, (short) 0, dataBuffer, (short) 0, message_len);
pkcs1_sha(dataBuffer, (short) 0, message_len, hashBuffer); // 32 Bytes
signLen = cipherRSA256.doFinal(hashBuffer, (short) 0, message_len, signBuffer, (short) 0); // 128 Bytes
Util.arrayCopy(signBuffer,(short)0,buffer,(short)0,signLen);
apdu.setOutgoingAndSend((short) 0, signLen);
break;
case 128:
if(!key_initialization_flag128)
ISOException.throwIt(SW_KEY_IS_NOT_INITIALIZED);
cipherRSA128.init(rsaPair128.getPrivate(), Cipher.MODE_ENCRYPT);
Util.arrayCopyNonAtomic(Message, (short) 0, dataBuffer, (short) 0, message_len);
pkcs1_sha(dataBuffer, (short) 0, message_len, hashBuffer); // 32 Bytes
signLen = cipherRSA128.doFinal(hashBuffer, (short) 0, message_len, signBuffer, (short) 0); // 128 Bytes
Util.arrayCopy(signBuffer, (short) 0, buffer, (short) 0, signLen);
apdu.setOutgoingAndSend((short) 0, signLen);
break;
default:
ISOException.throwIt(SW_WRONG_DATA_LENGTH);
break;
}
}
public void verify_hash(APDU apdu) {
byte[] buffer = apdu.getBuffer();
switch(message_len) {
case 256:
if(!key_initialization_flag256)
ISOException.throwIt(SW_KEY_IS_INITIALIZED);
cipherRSA256.init(rsaPair256.getPublic(), Cipher.MODE_DECRYPT);
hashLen = cipherRSA256.doFinal(signBuffer, (short) 0, message_len, buffer, (short) 0);
apdu.setOutgoingAndSend((short) 0, message_len);
break;
case 128:
if(!key_initialization_flag128)
ISOException.throwIt(SW_KEY_IS_INITIALIZED);
cipherRSA128.init(rsaPair128.getPublic(), Cipher.MODE_DECRYPT);
hashLen = cipherRSA128.doFinal(signBuffer, (short) 0, message_len, buffer, (short) 0);
apdu.setOutgoingAndSend((short) 0, message_len);
break;
default:
ISOException.throwIt(SW_WRONG_DATA_LENGTH);
break;
}
}
public void get_hash(APDU apdu) {
byte[] buffer = apdu.getBuffer();
Util.arrayCopy(hashBuffer,(short)0,buffer,(short)0,message_len);
apdu.setOutgoingAndSend((short)0,message_len);
}
// this function will leave tempBuffer with the data to be signed
public void pkcs1_sha(byte[] toSign, short bOffset, short bLength,byte[] out)
{
md.reset();
hashLen = md.doFinal(toSign, bOffset, bLength, out, (short) 0);
}
}
的問題是,當我執行簽名,驗證並獲得哈希命令,我渴望得到驗證並獲得哈希相同的答案。對於一些數據卡正確答案:
mode_211
enable_trace
establish_context
enable_trace
enable_timer
card_connect
command time: 593 ms
select -AID E0E1E2E3E4E501
Command --> 00A4040007E0E1E2E3E4E501
Wrapped command --> 00A4040007E0E1E2E3E4E501
Response <-- 9000
command time: 31 ms
send_apdu -sc 1 -APDU 8000010000 // Gen RSA Key 128
Command --> 8000010000
Wrapped command --> 8000010000
Response <-- 6302
send_APDU() returns 0x80206302 (Unknown ISO7816 error: 0x6302)
command time: 0 ms
send_apdu -sc 1 -APDU 80040000802EEEEFF1115D0B637ED81CE45EA86984E37521409EB67A7D
9E7DE88CF3BDC693B2B4F05748F9E705B2FE1C1D8CB9288B32D06952B6193935DD14FF9C89B9860B
0B31B9BA3C4130A4CC1CEC5CE430A784525B10706EC971C25B4C45CA3C9D98ECDB0825DADB499F31
36CB7322DFC44F4DAD71133CA894A14446416021684B9029
Command --> 80040000802EEEEFF1115D0B637ED81CE45EA86984E37521409EB67A7D9E7DE88CF3
BDC693B2B4F05748F9E705B2FE1C1D8CB9288B32D06952B6193935DD14FF9C89B9860B0B31B9BA3C
4130A4CC1CEC5CE430A784525B10706EC971C25B4C45CA3C9D98ECDB0825DADB499F3136CB7322DF
C44F4DAD71133CA894A14446416021684B9029
Wrapped command --> 80040000802EEEEFF1115D0B637ED81CE45EA86984E37521409EB67A7D9E
7DE88CF3BDC693B2B4F05748F9E705B2FE1C1D8CB9288B32D06952B6193935DD14FF9C89B9860B0B
31B9BA3C4130A4CC1CEC5CE430A784525B10706EC971C25B4C45CA3C9D98ECDB0825DADB499F3136
CB7322DFC44F4DAD71133CA894A14446416021684B9029
Response <-- 9000
send_APDU() returns 0x80209000 (9000: Success. No error.)
command time: 78 ms
send_apdu -sc 1 -APDU 8001000000 // Sign Message
Command --> 8001000000
Wrapped command --> 8001000000
Response <-- BF9E0C7BE366F6E9B2E78A8E7E101F8BFEDB3497AE68A7B8FCCA158DBDB937E6F62
76971AC7BF2B96F4258D4745719CBC93DEEDD344B512BCB1B8D6105837FB2C5F983C92F01FF0D8B5
3B009DA8EB76124EB4BFE24D598144A6726926A2A84E7F0C8FD00CE13121CDF68A3B87D6DCD06ED4
6EB56DE0E073B3BDBF37EC9934BCD9000
send_APDU() returns 0x80209000 (9000: Success. No error.)
command time: 203 ms
send_apdu -sc 1 -APDU 8008000000 // get hash
Command --> 8008000000
Wrapped command --> 8008000000
Response <-- 0BDE2856A3EC1083EBE56E8FCC7294ED06A7B63633C438A6CCB3C3B1D1C88811000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000009000
send_APDU() returns 0x80209000 (9000: Success. No error.)
command time: 47 ms
send_apdu -sc 1 -APDU 8007000000 // verify hash
Command --> 8007000000
Wrapped command --> 8007000000
Response <-- 0BDE2856A3EC1083EBE56E8FCC7294ED06A7B63633C438A6CCB3C3B1D1C88811000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000009000
send_APDU() returns 0x80209000 (9000: Success. No error.)
command time: 78 ms
card_disconnect
command time: 203 ms
release_context
command time: 0 ms
但對於其他一些數據,我從卡不正確迴應,我不知道爲什麼會這樣。這裏是第二個數據回答正確:
mode_211
enable_trace
establish_context
enable_trace
enable_timer
card_connect
command time: 577 ms
select -AID E0E1E2E3E4E501
Command --> 00A4040007E0E1E2E3E4E501
Wrapped command --> 00A4040007E0E1E2E3E4E501
Response <-- 9000
command time: 32 ms
send_apdu -sc 1 -APDU 8000010000 // Gen RSA Key 128
Command --> 8000010000
Wrapped command --> 8000010000
Response <-- 6302
send_APDU() returns 0x80206302 (Unknown ISO7816 error: 0x6302)
command time: 15 ms
send_apdu -sc 1 -APDU 8004000080335BE314CBC5C739DB41CCDD8FD0F53BB8F80E57DD3C18A9
091A715347BAFC5FD912A8973389BDFF05CF50A6E1B4716969A2C828A924D399D0A6A93DB0427666
7C9B623065D13192E5F372C8584A7111E74FC61923E1C1353DD1AE7D18991BEB3D83C49E6B756ABC
3359F9920E10BBEA24A999FB3E9A0CC1AC07E5C368F463DF
Command --> 8004000080335BE314CBC5C739DB41CCDD8FD0F53BB8F80E57DD3C18A9091A715347
BAFC5FD912A8973389BDFF05CF50A6E1B4716969A2C828A924D399D0A6A93DB04276667C9B623065
D13192E5F372C8584A7111E74FC61923E1C1353DD1AE7D18991BEB3D83C49E6B756ABC3359F9920E
10BBEA24A999FB3E9A0CC1AC07E5C368F463DF
Wrapped command --> 8004000080335BE314CBC5C739DB41CCDD8FD0F53BB8F80E57DD3C18A909
1A715347BAFC5FD912A8973389BDFF05CF50A6E1B4716969A2C828A924D399D0A6A93DB04276667C
9B623065D13192E5F372C8584A7111E74FC61923E1C1353DD1AE7D18991BEB3D83C49E6B756ABC33
59F9920E10BBEA24A999FB3E9A0CC1AC07E5C368F463DF
Response <-- 9000
send_APDU() returns 0x80209000 (9000: Success. No error.)
command time: 63 ms
send_apdu -sc 1 -APDU 8001000000 // Sign Message
Command --> 8001000000
Wrapped command --> 8001000000
Response <-- 9581924BA1F374489F83845FEEB7D71D71D3240C915CB1462434230982CA87A8AF3
0C2A716127C184E5DBB9EFF890A74A67967AC3EFE7E03FB433A3E52989459FDEF2CA8C19CD7BCD98
16434C4D84CF639F1D542F50B19BB56251BEA965F88168803F98906567CF1C2C6CE8B38999E16C50
49E2329F13156FA964F7477C07EF79000
send_APDU() returns 0x80209000 (9000: Success. No error.)
command time: 202 ms
send_apdu -sc 1 -APDU 8008000000 // get hash
Command --> 8008000000
Wrapped command --> 8008000000
Response <-- D9FE50E885FA4F2F85C70DC66FF42B5ABFAFB81820BF66F1967CB33D6E08AAE6000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000009000
send_APDU() returns 0x80209000 (9000: Success. No error.)
command time: 47 ms
send_apdu -sc 1 -APDU 8007000000 // verify hash
Command --> 8007000000
Wrapped command --> 8007000000
Response <-- 13AD6610CA13A7064193753BE50F268EC3F0D0AE8A5F079C0D40548835EAB0E9267
63B8EC02435CE8E126A4C97643D6BD2051E146CE353D351FF5FC58C0D2AD8BC5ADB40067F807EFE1
B2E1A37E027E6F50BA82DCE55DC37584F5941B6F29439234D97BE7612B03987E99C1F9F9A5A3B949
1E9758ECC7E02767D76B7C6C7A0B99000
send_APDU() returns 0x80209000 (9000: Success. No error.)
command time: 78 ms
card_disconnect
command time: 203 ms
release_context
command time: 0 ms
我會很感激,如果任何人都可以給我一個提示或有過相同的經歷!
爲什麼你使用'Cipher'爲計算簽名?你爲什麼不用'Signature'呢? – vojta
@vojta謝謝你回答我,問題是我使用的卡不支持'Signature'類。 – MJay
除非您讓問題重現,否則我們無法幫助您。你至少應該澄清一下,「但是對於其他一些數據,我從卡片上得到了不正確的答覆」(這個問題已經放入我對SO小冊子不清楚的錯誤描述中,很快就會出現)。 –