В настоящее время я работаю с шифрованием на основе ключей X25519.
Мой вопрос, в принципе, как извлечь PublicKey
из существующего X25519 PrivateKey
?
Я пробовал следующее:
protected PublicKey generatePublicKeyFromPrivate(PrivateKey privateKey) throws GeneralSecurityException {
PublicKey basePublicKey = generatePublicKey(BigInteger.valueOf(9));
KeyAgreement keyAgreement = KeyAgreement.getInstance(X25519);
keyAgreement.init(privateKey, new ECGenParameterSpec(X25519));
keyAgreement.doPhase(basePublicKey, true);
byte[] bytes = keyAgreement.generateSecret();
return generatePublicKey(new BigInteger(bytes));
}
PublicKey успешно сгенерирован. И я даже сравнил этот подход с подходом сторонней библиотеки ( Google Tink ): сгенерированное совпадение PubliKeys.
Однако, когда я пытаюсь использовать Java KeyPairGenerator
для одновременного получения PrivateKey и PubliKey, а затем пытаюсь сгенерировать PublicKey для этого PrivateKey, они различаются.
public KeyPair generateX25519KeyPair() throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(X25519);
return keyPairGenerator.generateKeyPair();
}
Iрешил поискать исходный код KeyPairGenerator
(XDHKeyPairGenerator
реализация) и нашел часть при умножении:
/**
*
* Multiply an encoded scalar with a point as a BigInteger and return an
* encoded point. The array k holding the scalar will be pruned by
* modifying it in place.
*
* @param k an encoded scalar
* @param u the u-coordinate of a point as a BigInteger
* @return the encoded product
*/
public byte[] encodedPointMultiply(byte[] k, BigInteger u) {
pruneK(k);
ImmutableIntegerModuloP elemU = field.getElement(u);
return pointMultiply(k, elemU).asByteArray(params.getBytes());
}
Однако метод, который используется для раздельной генерации PubliKey, использует другое умножение:
/**
* Compute a public key from an encoded private key. This method will
* modify the supplied array in order to prune it.
*/
public BigInteger computePublic(byte[] k) {
pruneK(k);
return pointMultiply(k, this.basePoint).asBigInteger();
}
Как видите, разница в том, что в первом случае они применяют метод asByteArray()
к результату:
* Returns the little-endian encoding of this' % 2^(8 * len), where this'
* is the canonical integer value equivalent to this.
*
* @param len the length of the desired array
* @return a byte array of length len containing the result
*/
default byte[] asByteArray(int len) {
byte[] result = new byte[len];
asByteArray(result);
return result;
}
Так что мой вопрос на самом деле: почемуони так делают? Почему эта кодировка с прямым порядком байтов применяется к PublicKey при использовании KeyPairGenerator
, но не применяется, когда PublicKey извлекается из PrivateKey отдельно.