Я пытаюсь сгенерировать пару ключей для кривой Secp192r1, используя Javacard 2.2.1 (я также пытался использовать Javacard 2.2.2), вызывая функцию KeyPair.genKeyPair для объекта javacard Keypair.
Однако, когда во время генерации пары ключей, иногда выдается следующая ошибка: «java.lang.ArithmeticException: BigInteger not invertible». Ошибка не выдается каждый раз, а возникает примерно у 50% поколений. Если генерация ключа прошла успешно, однако, похоже, что не нужно создавать правильные пары ключей. Это связано с тем, что в этих успешных случаях я пытался использовать сгенерированный открытый ключ для создания представления открытого ключа в замке Баунти, который затем завершается ошибкой и сигнализирует о том, что открытый ключ является неправильной точкой.
I 'мы пытались отладить код дальше, но из-за отсутствия исходных файлов внутренних компонентов 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, поэтому, если вы заметите какой-либоошибка в моей реализации, пожалуйста, скажите мне, что я сделал не так. Заранее спасибо!