EDDSA Signature с Luna HSM с использованием Java - PullRequest
1 голос
/ 14 марта 2020

Я пытаюсь реализовать подпись EDDSA с помощью Luna HSM (Gemalto)

Signature signature = null;
signature = Signature.getInstance("EDDSA", "LunaProvider");
PrivateKey privateKey = getPrivateByAlias(privateKeyLabel);
signature.initSign(privateKey);
signature.update(payload);
byte[] byteArray = signature.sign();

Но после подписания размер byteArray равен 71, а размер подписи EDDSA равен 64 согласно спецификации. Я не уверен, что мне здесь не хватает. Я не смог найти ни одного документа в Интернете.

Ответы [ 2 ]

1 голос
/ 14 марта 2020

Это именно тот размер, который вы ожидаете получить для совместимой подписи X9.63, которая состоит из кодировки DER двух знаковых целых чисел с прямым порядком байтов. Если вы хотите иметь 64-байтовую подпись, вам следует преобразовать 2 целых числа внутри, используя , следующее объяснение . Реализация в Java I2OSP и OS2IP может быть найдена здесь .

Итак, шаги:

  1. синтаксический анализ подписи ASN.1;
  2. преобразовать в BigInteger значения с помощью конструктора new BigInteger(byte[]);
  3. использовать I2OSP для создания значений r и s в виде байтового массива (размер вывода 32 октета);
  4. объединить r и s для создания 64-байтовой подписи.
0 голосов
/ 16 марта 2020

Я пробовал следующим образом, но проверка не удалась (Код обновлен, и теперь он работает)

        Signature signature = Signature.getInstance("SHA512withEDDSA", "LunaProvider");
        signature.setParameter(new LunaEDDSAParameterSpec(false));
        signature.initSign(privateKey);
        signature.update(payload);
        byte[] byteArray = signature.sign();

        ASN1InputStream decoder = new ASN1InputStream(byteArray);
        DERSequence seq = (DERSequence) decoder.readObject();
        DERInteger r = (DERInteger) seq.getObjectAt(0);
        DERInteger s = (DERInteger) seq.getObjectAt(1);
        LOGGER.info("R: {}", r.getValue());
        LOGGER.info("S: {}", s.getValue());
        decoder.close();

        byte[] rByte = i2osp(r.getValue(), 32);
        byte[] sByte = i2osp(s.getValue(), 32);

        byte[] concat = Bytes.concat(rByte, sByte);

        return concat;

Не уверен, что это правильный способ

Проверка с использованием звездного java библиотека

        PublicKey publicKey = getPublicByAlias(publicKeyLabel);
        LunaPublicKeyEC lunaPublicKeyEC = (LunaPublicKeyEC) publicKey;
        byte[] pubKeySub = Arrays.copyOfRange(lunaPublicKeyEC.getP(), 2, lunaPublicKeyEC.getP().length);
        org.stellar.sdk.KeyPair keyPair = org.stellar.sdk.KeyPair.fromPublicKey(pubKeySub);
        boolean verified = keyPair.verify(payload, signatureByte);
...