用于 Secp192r1 的 Javacard 2.2.1 中的 genKeyPair 抛出 "java.lang.ArithmeticException: BigInteger not invertible"

genKeyPair in Javacard 2.2.1 for Secp192r1 throws "java.lang.ArithmeticException: BigInteger not invertible"

我正在尝试通过调用 javacard Keypair 对象的 KeyPair.genKeyPair 函数,使用 Javacard 2.2.1(我也尝试过使用 Javacard 2.2.2)为 Secp192r1 曲线生成一个密钥对。

但是在生成密钥对的过程中,有时会抛出以下错误"java.lang.ArithmeticException: BigInteger not invertible"。错误不是每次都抛出,而是发生在大约 50% 的世代中。如果密钥生成成功,但似乎不会生成正确的密钥对。这是因为我在那些成功的案例中尝试使用生成的 public 密钥来创建 public 密钥的赏金城堡表示,然后失败并表明 public 密钥是一个不正确的点。

我已经尝试进一步调试代码,但由于我缺少 javacard 内部的源文件,所以除了在 AsymmetricCipherKeyPairGenerator generateKeyPair 函数中抛出的错误之外,我无法进一步跟踪错误.

我对自己做错了什么完全感到困惑,我所有解决问题的尝试都失败了。如果有人能发现我做错了什么,我将非常感激!

应该注意的是,我只使用 jcardsim 测试代码来模拟和调试代码的执行,而不是 运行 实际物理芯片上的代码,如果这很重要的话。我使用的 jcardsim 版本如下:https://github.com/licel/jcardsim/raw/master/jcardsim-2.2.1-all.jar

我在下面创建了一些示例源代码,偶尔会抛出错误:

Secp192r1曲线代码:

package example.applet;
import javacard.security.ECKey;

public class Secp192r1 {

    public static final byte[] EC192_FP_P = new byte[]{
            (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
            (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
            (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
            (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFE,
            (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
            (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF};

    public static final byte[] EC192_FP_A = new byte[]{
            (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
            (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
            (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
            (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFE,
            (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
            (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFC};

    public static final byte[] EC192_FP_B = new byte[]{
            (byte) 0x64, (byte) 0x21, (byte) 0x05, (byte) 0x19,
            (byte) 0xE5, (byte) 0x9C, (byte) 0x80, (byte) 0xE7,
            (byte) 0x0F, (byte) 0xA7, (byte) 0xE9, (byte) 0xAB,
            (byte) 0x72, (byte) 0x24, (byte) 0x30, (byte) 0x49,
            (byte) 0xFE, (byte) 0xB8, (byte) 0xDE, (byte) 0xEC,
            (byte) 0xC1, (byte) 0x46, (byte) 0xB9, (byte) 0xB1};

    public static final byte[] EC192_FP_G_UNCOMPRESSED = new byte[]{
            (byte) 0x04, // Uncompressed
            (byte) 0x18, (byte) 0x8D, (byte) 0xA8, (byte) 0x0E,
            (byte) 0xB0, (byte) 0x30, (byte) 0x90, (byte) 0xF6,
            (byte) 0x7C, (byte) 0xBF, (byte) 0x20, (byte) 0xEB,
            (byte) 0x43, (byte) 0xA1, (byte) 0x88, (byte) 0x00,
            (byte) 0xF4, (byte) 0xFF, (byte) 0x0A, (byte) 0xFD,
            (byte) 0x82, (byte) 0xFF, (byte) 0x10, (byte) 0x12,
            (byte) 0x07, (byte) 0x19, (byte) 0x2B, (byte) 0x95,
            (byte) 0xFF, (byte) 0xC8, (byte) 0xDA, (byte) 0x78,
            (byte) 0x63, (byte) 0x10, (byte) 0x11, (byte) 0xED,
            (byte) 0x6B, (byte) 0x24, (byte) 0xCD, (byte) 0xD5,
            (byte) 0x73, (byte) 0xF9, (byte) 0x77, (byte) 0xA1,
            (byte) 0x1E, (byte) 0x79, (byte) 0x48, (byte) 0x11};

    public static final byte[] EC192_FP_R = new byte[]{
            (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
            (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
            (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
            (byte) 0x99, (byte) 0xDE, (byte) 0xF8, (byte) 0x36,
            (byte) 0x14, (byte) 0x6B, (byte) 0xC9, (byte) 0xB1,
            (byte) 0xB4, (byte) 0xD2, (byte) 0x28, (byte) 0x31};

    public static final short EC192_FP_K = 1;

    protected static boolean setCommonCurveParameters(ECKey key) {
        try {
            key.setFieldFP(EC192_FP_P, (short)0, (short)EC192_FP_P.length);
            key.setA(EC192_FP_A, (short)0, (short)EC192_FP_A.length);
            key.setB(EC192_FP_B, (short)0, (short)EC192_FP_B.length);
            key.setG(EC192_FP_G_UNCOMPRESSED, (short)0, (short)EC192_FP_G_UNCOMPRESSED.length);
            key.setR(EC192_FP_R, (short)0, (short)EC192_FP_R.length);
            key.setK(EC192_FP_K);
            return true;
        }
        catch(Exception e) {
            return false;
        }

    }
}

密钥生成代码:

 package example.applet;
 import javacard.security.*;

 public class ExampleKeyImpl {

     private static KeyPair keyPair;

     public ExampleKeyImpl() {
         keyPair = new KeyPair(
                 (ECPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_192, false),
                 (ECPrivateKey) KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE, KeyBuilder.LENGTH_EC_FP_192, false));

         Secp192r1.setCommonCurveParameters((ECKey) keyPair.getPrivate());
         Secp192r1.setCommonCurveParameters((ECKey) keyPair.getPublic());
     }


     public void generateKeyPair() {
         try {
             keyPair.genKeyPair(); // THIS IS WHERE THE ERROR IS THROWN
         }
         catch (Exception e){
             String errorMessage = e.getMessage(); // GIVES THE BigInteger ERROR MESSAGE
         }
     }
 }

小程序代码:

package example.applet;

import javacard.framework.*;
import javacard.security.Signature;

public class ExampleApplet extends Applet {


    private static byte[] scratch;
    private static ExampleKeyImpl keyImpl;

    private static Signature localSignature;

    public static void install(byte[] parameters, short startOffset, byte lengthToRead) throws ISOException {
        new ExampleApplet();
    }

    public ExampleApplet() {
        initializeResources();
        generateKeyPair();
    }

    private void initializeResources() {
        scratch = JCSystem.makeTransientByteArray((short) (200), JCSystem.CLEAR_ON_RESET);

        localSignature = Signature.getInstance(Signature.ALG_ECDSA_SHA, false);
        keyImpl = new ExampleKeyImpl();
    }

    private void generateKeyPair() {
        keyImpl.generateKeyPair();
    }

}

我最好的估计是我以某种方式错误地实现了 Secp192r1 曲线,因此如果您在我的实现中发现任何错误,请告诉我我做错了什么。提前致谢!

我发现通过更改 ExampleKeyImpl 中的构造函数解决了问题:

public ExampleKeyImpl() {
     keyPair = new KeyPair(
             (ECPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_192, false),
             (ECPrivateKey) KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE, KeyBuilder.LENGTH_EC_FP_192, false));

     Secp192r1.setCommonCurveParameters((ECKey) keyPair.getPrivate());
     Secp192r1.setCommonCurveParameters((ECKey) keyPair.getPublic());
 }

收件人:

public ExampleKeyImpl() {
     keyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_192);

     Secp192r1.setCommonCurveParameters((ECKey) keyPair.getPrivate());
     Secp192r1.setCommonCurveParameters((ECKey) keyPair.getPublic());
}

虽然我不太确定为什么会有所不同。