Как сгенерировать PublicKey для PrivateKey в X25519? - PullRequest
0 голосов
/ 27 октября 2019

В настоящее время я работаю с шифрованием на основе ключей 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 отдельно.

1 Ответ

2 голосов
/ 27 октября 2019

Открытый ключ вычисляется путем умножения базовой точки на «зажатый» секретный скаляр и возврата закодированной координаты X.

Зажим означает маскирование 3 младших значащих битов, маскирование старшего бита и установкувторой верхний бит.

Подробнее см. RFC7748 .

Но похоже, что это больше вопрос программирования, и реальная проблема может не иметь ничего общего с X25519,Для заданного секрета сравните вывод, полученный из этого кода, с той же операцией, реализованной в другой библиотеке. Если открытые ключи совпадают, проблема заключается в другом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...