В чем проблема с Java-картой, методом RSA-шифрования doFinal? - PullRequest
0 голосов
/ 02 июля 2019

Я написал апплет java-карты, чтобы RSA зашифровал входящие данные с помощью закрытого ключа и снова отправил его.

Вот мой код:

package test;

import javacard.framework.*;
import javacard.security.*;
import javacardx.crypto.Cipher;

public class test extends Applet
{
    private static byte[] Hash = new byte[32];
    private static byte[] Sign = new byte[256];
    private static short hash_len = 0;
    private static short sign_len = 0;
    MessageDigest mDigest = MessageDigest.getInstance(MessageDigest.ALG_SHA_256,false);
    Cipher rsaCipher = Cipher.getInstance(Cipher.ALG_RSA_NOPAD, false);
    KeyPair rsaKey = new KeyPair(KeyPair.ALG_RSA,KeyBuilder.LENGTH_RSA_2048);
    RSAPublicKey rsaPubKey = (RSAPublicKey)KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC, KeyBuilder.LENGTH_RSA_2048, false);

    public static void install(byte[] bArray, short bOffset, byte bLength) 
    {
        new test().register(bArray, (short) (bOffset + 1), bArray[bOffset]);
    }

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

        byte[] buf = apdu.getBuffer();
        switch (buf[ISO7816.OFFSET_INS])
        {
        case (byte)0x00: // generate keypair
            rsaKey.genKeyPair();
            break;
        case (byte)0x01: // get public key
            apdu.setIncomingAndReceive();
            rsaPubKey = (RSAPublicKey) rsaKey.getPublic();
            rsaPubKey.getModulus(buf, (short) 0);
            apdu.setOutgoingAndSend((short) 0, (short) 256);
            break;
        case (byte)0x03: //encrypt by private key
            short len = apdu.setIncomingAndReceive();
            mDigest.reset();
            hash_len = mDigest.doFinal(buf, (short) ISO7816.OFFSET_CDATA, len, Hash, (short)0);
            rsaCipher.init(rsaKey.getPrivate(), Cipher.MODE_ENCRYPT);
            sign_len = rsaCipher.doFinal(Hash, (short) 0, hash_len, Sign, (short)0);
            Util.arrayCopy(Hash, (short)0, buf, (short)0, hash_len);
            apdu.setOutgoingAndSend((short) 0, hash_len);
            break;
        default:
            ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
        }
    }

}

Я делаю ключи успешно, нокогда я пытаюсь выполнить шифрование, 6F 00 возвращается в строке sign_len = rsaCipher.doFinal(Hash, (short) 0, hash_len, Sign, (short)0);.

Теперь мой первый вопрос: как я могу узнать значение 6F 00 ПО, т. е. как работать во время выполнения?исключения в моем коде и мой второй вопрос, как это исправить и в чем проблема?Где я ошибаюсь?(Я использую набор карт Java 3.0.4.)

1 Ответ

2 голосов
/ 02 июля 2019

Вы используете Cipher.ALG_RSA_NOPAD алгоритм (также известный как «необработанный RSA» или «X.509 RSA»), который просто выполняет модульное возведение в степень без заполнения.

Этот алгоритмтребует, чтобы длина ввода была такой же, как у модуля ключа RSA (2048 бит / 256 байт), и небезопасно при использовании без надлежащего заполнения ввода .

Использование Cipher.ALG_RSA_PKCS1_OAEP (если ваша карта поддерживает это) или Cipher.ALG_RSA_PKCS1 для шифрования RSA.


Слово состояния 6F 00 дается из-за отсутствия данных CryptoException (см. Документацию для Cipher.doFinal () ).Возможно, вы захотите окружить свой код try { ... } catch (CryptoException e) { ... } и получить более подробную информацию о проблеме, которая произошла с помощью CardRuntimeException.getReason () .


Примечание. В коде, который вы шифруетехэш данных SHA-256, который не имеет особого смысла - вы хотели подписать данные?Вместо этого вы должны использовать Signature.ALG_RSA_SHA_256_PKCS1_PSS или Signature.ALG_RSA_SHA_256_PKCS1 (обратите внимание, что в этом случае вам не нужно выполнять хеширование, поскольку SHA-256 вычисляется во время вычисления подписи).

Удачи!

...