Взаимодействие между реализациями Java и Javascript Ed25519

Оба ed25519-java и js-nacl имеют реализацию методов крипто-подписи ed25519. Однако я получил открытый ключ и подписанное сообщение (подписанное с использованием соответствующего закрытого ключа открытого ключа) от ed25519-java и попытался проверить подписанное сообщение с помощью открытого ключа в js-nacl. Это дало значение null, т. е. подписанное сообщение нельзя было открыть с помощью открытого ключа.

Мой вопрос: нельзя ли войти в Java и проверить подпись в Javascript? Если да, а если нет, то почему?

Java-код:

public static void main(String[] args) {
    byte[] privateKey = new byte[32];
    Arrays.fill(privateKey, (byte) 0);
    byte[] publicKey = ed25519.publickey(privateKey);
    byte[] signature = ed25519.signature("www.example.com".getBytes(), privateKey, publicKey);
    System.out.println("Signature: " + Base64.encodeBase64URLSafeString(signature) + "\nPublicKey: " + Base64.encodeBase64URLSafeString(publicKey));
    try{
        System.out.println("Verification: " + ed25519.checkvalid(signature, "www.example.com".getBytes(), publicKey));
    } catch (Exception e){
        System.out.println(e.getStackTrace());
    }
}

Вызов checkvalid возвращает true.

Выходная подпись: oFMU_mC_zzZcJP2C-uTqsyUHoyLUSnwirJbhcdkSTnj2nI_p-VgKAqN5bFMPKsKYiWvyiUgHWu3s4OyB9WbKDg

Выходной открытый ключ: O2onvM62pC1io6jQKm8Nc2UyFXcd4kOmOsBIoYtZ2ik

Код JavaScript:

var signature = "oFMU_mC_zzZcJP2C-uTqsyUHoyLUSnwirJbhcdkSTnj2nI_p-VgKAqN5bFMPKsKYiWvyiUgHWu3s4OyB9WbKDg";
var pk = "O2onvM62pC1io6jQKm8Nc2UyFXcd4kOmOsBIoYtZ2ik";

var nacl_factory = require('js-nacl');
var nacl = nacl_factory.instantiate();
var b64 = require('urlsafe-base64');
var x = nacl.crypto_sign_open(Uint8Array(b64.decode(signature)), Uint8Array(b64.decode(pk)));
response.send(x);

x имеет значение null, но должно выдавать "www.example.com" в качестве вывода, если подпись можно открыть с помощью открытого ключа.

Не уверен, влияет ли это на работу, но массивы байтов Java подписаны, тогда как js-nacl использует массивы байтов Uint8Array без знака Javascript.


person RandomCoder42    schedule 15.04.2014    source источник
comment
1) Вы про шифрование (с crypto_box на базе Curve25519 + xsalsa20poly1305) или подписи (с Ed25519-SHA512)? 2) Разместите соответствующий код вместе с примером сообщения/подписи.   -  person CodesInChaos    schedule 16.04.2014
comment
Да, вы все еще говорите о методе шифрования. Затем вы говорите о подписанном сообщении. Пример кода прояснит, что вы на самом деле спрашиваете, и даже может показать нам, что идет не так.   -  person Maarten Bodewes    schedule 16.04.2014
comment
Не используйте string.getBytes() в java, он использует устаревшую кодировку, зависящую от локали. Явно укажите кодировку, желательно UTF-8.   -  person CodesInChaos    schedule 23.04.2014


Ответы (1)


Реализации Ed25519 отличаются двумя способами:

  1. Формат закрытого ключа немного отличается. Некоторые работают с расширенным закрытым ключом, другие запрашивают при подписании как начальный, так и открытый ключ. Ваша реализация Java относится ко второй категории.

    Это различие относится только к функции подписи, а не к функции проверки. Это не доставляет вам никаких проблем.

  2. В некоторых реализациях используется «поле подписи», где подпись возвращает объединение подписи и сообщения (signedMessage.Length = 64 + message.Length). При проверке они ожидают это подписанное сообщение в качестве входных данных. Исходная реализация NaCl и ваша реализация javascript попадают в эту категорию.

    Некоторые реализации возвращают 64-байтовую подпись. Они ожидают открытый текст как отдельный параметр при проверке. Ваша реализация Java попадает в эту категорию.

    Это несоответствие вызывает ваши проблемы. Чтобы исправить это, вам нужно передать concat(signature, message) в crypto_sign_open.

Вы должны прочитать статью Брайана Уорнера Ed25519 Keys для более подробного объяснения. .

person CodesInChaos    schedule 23.04.2014