Какой должна быть длина открытого ключа в ECDH?

Я работаю над проектом по реализации ECDH в приложении для Android, и моя проблема связана с реализацией Java, она генерирует более длинный открытый ключ, чем я ожидал.

// Generate ephemeral ECDH keypair
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");
kpg.initialize(256);
KeyPair kp = kpg.generateKeyPair();
byte[] ourPk = kp.getPublic().getEncoded();
System.out.println("ourPk len is " + ourPk.length);
// Display our public key
console.printf("Public Key: %s%n", printHexBinary(ourPk));

Насколько я знаю или узнаю отсюда, если это 256-битная кривая (secp256k1), ключи будут:

Public key: 32 bytes * 2 + 1 = 65 (uncompressed)
Private key: 32 bytes

Я ожидаю, что на выходе (длина нашего ПК) будет 65, но на самом деле это 91.


person Terminou    schedule 25.07.2019    source источник
comment
Здесь вы получаете информацию об открытом ключе субъекта в кодировке DER. Вам нужно будет извлечь ключ из этого объекта der.   -  person Michał Krzywański    schedule 25.07.2019
comment
см. RFC5480   -  person Michał Krzywański    schedule 25.07.2019
comment
JCE KPG{EC}.initialize(256) использует secp256R1 (он же P-256 или prime256v1, часть бывшего Suite B и широко используется для TLS) НЕ secp256K1 (используется для биткойнов). Хотя эти кривые имеют одинаковые представления размера, они несовместимы или несовместимы. Для secp256k1 используйте java.security.spec.ECGenParameterSpec (см. javadoc).   -  person dave_thompson_085    schedule 26.07.2019


Ответы (1)


Как указано в комментариях, вам следует обратиться к RFC5480 и его разделам 2 и 2.2. kp.getPublic().getEncoded() вернет информацию об открытом ключе субъекта в кодировке DER. Чтобы извлечь из него публичный ключ EC - взгляните на этот код. Я использую библиотеку BouncyCastle для обработки объектов DER:

Security.addProvider(new BouncyCastleProvider());
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");
kpg.initialize(256);
KeyPair kp = kpg.generateKeyPair();
byte[] ourPk = kp.getPublic().getEncoded();
System.out.println("ourPk len is " + ourPk.length);

ASN1Sequence sequence = DERSequence.getInstance(ourPk);

DERBitString subjectPublicKey = (DERBitString) sequence.getObjectAt(1);

byte[] subjectPublicKeyBytes = subjectPublicKey.getBytes();

System.out.println("EC key length : " + subjectPublicKeyBytes.length);

Результат:

ourPk len is 91
EC key length : 65
person Michał Krzywański    schedule 25.07.2019
comment
Или /*org.bouncycastle.asn1.x509.*/SubjectPublicKeyInfo .getInstance(ourPk) .getPublicKeyData() .getOctets(). Или опасно жить без БК, Arrays.copyOfRange(ourPk,26,ourPk.length) - person dave_thompson_085; 26.07.2019