如何从我的 RSA Sign 获得正确的结果?

How to get correct result from my RSA Sign?

我写了一段代码来散列和 rsa 加密(以某种方式签名)发送到 java 卡的数据。

这是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

如果有人能给我提示或有相同经历,我将不胜感激!!!

您的哈希值位于值的最重要端,因为 RSA 使用大端编码。这意味着该值可能会返回 mod N(modulus),这将导致与您输入的值不同。

将散列放在消息的最不重要的一端,您的代码应该 运行。


备注:

  • 没有填充的 RSA 安全;
  • 签名生成不同于如果您考虑填充、侧信道攻击、性能等,则与使用私钥加密哈希值相同。