Cryptography 当指数超过10字节时,Java Card setExponent()方法失败

Cryptography 当指数超过10字节时,Java Card setExponent()方法失败,cryptography,rsa,javacard,exponent,Cryptography,Rsa,Javacard,Exponent,我正在尝试使用内置RSA密码系统在Java卡上实现modPow函数。代码看起来微不足道,但我已经发布了实现 我的代码直到现在: Cipher m_encryptCipherRSA = Cipher.getInstance(Cipher.ALG_RSA_NOPAD, false); // create the cipher RSAPublicKey m_rsaPublicKey = (RSAPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE

我正在尝试使用内置RSA密码系统在Java卡上实现
modPow
函数。代码看起来微不足道,但我已经发布了实现

我的代码直到现在:

    Cipher m_encryptCipherRSA = Cipher.getInstance(Cipher.ALG_RSA_NOPAD, false); // create the cipher
    RSAPublicKey m_rsaPublicKey = (RSAPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC,KeyBuilder.LENGTH_RSA_1024,false);  // create the public key
    m_random = RandomData.getInstance(RandomData.ALG_SECURE_RANDOM);
    m_random.generateData(temp1, (short)0, MODULUS_LENGTH);
    m_rsaPublicKey.setModulus(temp1,(short)0, MODULUS_LENGTH); //generate modulus
    m_random.generateData(temp1,(short)0, (short) EXPONENT_LENGTH);
    m_rsaPublicKey.setExponent(temp1,(short)0, (short)EXPONENT_LENGTH); 

如果
EXPONENT\u LENGTH
的长度不超过10个字节,那么cod似乎可以正常工作。我使用的Java卡限制了public EXPONENT的维数。然而,我的项目是基于长度不超过128字节的数字。有没有办法基于这个硬件限制创建一个通用的
modpow
函数?是否有其他方法可以实现幂指数化,但仍然可行。

我通过使用私有指数(似乎不受RSA密码系统的约束)解决了这个问题。下面是工作代码

    public byte[] modPow(byte[] x,short xOffset,short xLength,byte[] y,short yOffset,short yLength)
{
    Util.arrayCopy(y, yOffset, tempBuffer, (short)(Configuration.TEMP_OFFSET_EXPONENT+4), yLength);
    Util.arrayFillNonAtomic(tempBuffer, Configuration.TEMP_OFFSET_EXPONENT, (byte)4,(byte)0x00);
    mRsaPrivateKeyModPow.setExponent(tempBuffer,Configuration.TEMP_OFFSET_EXPONENT, (short)(yLength+4));
    mRsaCipherModPow.init(mRsaPrivateKeyModPow, Cipher.MODE_DECRYPT);
    Util.arrayCopy(x,xOffset,tempBuffer, Configuration.TEMP_OFFSET_RSA, Configuration.LENGTH_RSAOBJECT_MODULUS);
    mRsaCipherModPow.doFinal(tempBuffer,Configuration.TEMP_OFFSET_RSA, (short) (Configuration.LENGTH_RSAOBJECT_MODULUS), tempBuffer,Configuration.TEMP_OFFSET_RSA);
    mRsaPrivateKeyModPow.clearKey();
    return tempBuffer;
}

嗯,我尝试了两张不同的卡的
RSAPublicKey
rsaprovatekey
,两张卡都很好:

package soqPack;

import javacard.framework.*;
import javacard.security.KeyBuilder;
import javacard.security.RSAPrivateKey;
import javacard.security.RSAPublicKey;
import javacard.security.RandomData;
import javacardx.biometry.BioBuilder;
import javacardx.crypto.Cipher;

public class modPowtest extends Applet {

    //Definition Of INS in APDU command
    public static final byte INS_MOD_POW = (byte) 0x00;

    //Switch cases to choose RSA Public key or RSA Private key for ModPow()
    //P1 in APDU command.
    public static final byte USE_PUB_KEY = (byte) 0x00;
    public static final byte USE_PRI_KEY = (byte) 0x01;

    //Required objects
    byte[] tempMem;
    Cipher myCipher;
    RSAPrivateKey rsaPriKey;
    RSAPublicKey rsaPubKey;
    RandomData random;

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

    protected modPowtest() {
        myCipher = Cipher.getInstance(Cipher.ALG_RSA_PKCS1, false);
        rsaPriKey = (RSAPrivateKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PRIVATE, KeyBuilder.LENGTH_RSA_1024, false);
        rsaPubKey = (RSAPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC, KeyBuilder.LENGTH_RSA_1024, false);
        tempMem = JCSystem.makeTransientByteArray((short) 0x80, JCSystem.CLEAR_ON_DESELECT);
        random = RandomData.getInstance(RandomData.ALG_PSEUDO_RANDOM);
        register();
    }

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

        byte[] buffer = apdu.getBuffer();
        switch (buffer[ISO7816.OFFSET_INS]) {
            case INS_MOD_POW:
                modPow(apdu);
                break;
            default:
                ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
        }
    }

    public void modPow(APDU apdu) {
        byte[] buffer = apdu.getBuffer();
        switch (buffer[ISO7816.OFFSET_P1]) {
            case USE_PUB_KEY:
                random.generateData(tempMem, (short) 0x00, (short) 0x80);
                rsaPubKey.setModulus(tempMem, (short) 0x00, (short) 0x80);
                random.generateData(tempMem, (short) 0x00, (short) 0x03);
                rsaPubKey.setExponent(tempMem, (short) 0x00, (short) 0x03);
                break;
            case USE_PRI_KEY:
                random.generateData(tempMem, (short) 0x00, (short) 0x80);
                rsaPriKey.setModulus(tempMem, (short) 0x00, (short) 0x80);
                random.generateData(tempMem, (short) 0x00, (short) 0x03);
                rsaPriKey.setExponent(tempMem, (short) 0x00, (short) 0x03);
                break;
            default:
                ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
        }

    }
}
工作内容如下:

Download Cap begin...
Download Cap successful.
Install Applet begin...
Install Applet successful.
Select Applet begin...
Select Applet successful.

Send: 00 00 00 00 00
Recv: 90 00

Send: 00 00 01 00 00
Recv: 90 00

更新:(在评论和评论中关联您的新问题):


我还将
setmodule
setExponent
方法之前的
tempMem[0]
的值更改为
0x69
,它仍然可以正常工作。

使用
EXPONENT\u LENGTH>10
时会发生什么?您得到了什么状态字?@vojta 6f 00,这是未知错误。捕获抛出的异常并告诉我们其类型(使用instanceof运算符)及其原因(getReason()方法的输出),请。@vojta我通过使用私有指数而不是公共指数解决了这个问题。现在,当输入长度为1024位且以大于0x68的八位字节开始时,我遇到了Rsa上dofinal方法的问题。@vojta我用详细的解释开始了新问题,我读到
setExponent()
如果指数的大小大于4字节,则可能会失败。从oracle文档中,我发现所有实现都必须支持长度不超过4字节的指数值。实现可能还支持长度大于4字节的指数值。以下是问题。我从新问题开始。在我看来,模数值有问题。我猜它小于RSA的x值,因此算法失败。