2017-03-11 94 views
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 

我會很感激,如果任何人都可以給我一個提示或有過相同的經歷!

+0

爲什麼你使用'Cipher'爲計算簽名?你爲什麼不用'Signature'呢? – vojta

+0

@vojta謝謝你回答我,問題是我使用的卡不支持'Signature'類。 – MJay

+0

除非您讓問題重現,否則我們無法幫助您。你至少應該澄清一下,「但是對於其他一些數據,我從卡片上得到了不正確的答覆」(這個問題已經放入我對SO小冊子不清楚的錯誤描述中,很快就會出現)。 –

回答

2

由於RSA使用大端編碼,因此您的哈希位於值的最高位。這意味着該值可能會返回mod N(模數),這會導致與您輸入的值不同的值。

將散列放在消息的最低有效位置,並且您的代碼應該運行。


注:

  • RSA沒有填充是不安全;
  • 簽名生成是一樣,如果你考慮填充,側信道攻擊,性能等等,等等等等用私鑰加密哈希值..
相關問題