1

ed25519 -javajs-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为空,但"www.example.com"如果可以使用公钥打开签名,则应作为输出。

不确定它是否会影响工作,但 Java 的字节数组是有符号的,而 js-nacl 使用 Javascript 的Uint8Array无符号字节数组。

4

1 回答 1

5

Ed25519 实现在两个方面有所不同:

  1. 私钥格式有点不同。有些使用扩展的私钥,有些则在签名时要求种子和公钥。您的 java 实现属于后一类。

    这种差异仅适用于签名功能,不适用于验证功能。它不会给您带来任何问题。

  2. 一些实现使用“签名框”,其中签名返回签名和消息 ( signedMessage.Length = 64 + message.Length) 的串联。在验证时,他们希望将签名消息作为输入。原始的 NaCl 实现和您的 javascript 实现属于这一类。

    一些实现返回一个 64 字节的签名。他们希望在验证时将明文作为单独的参数。您的 java 实现属于这一类。

    这种不匹配正在给您带来麻烦。要修复它,您需要传递concat(signature, message)crypto_sign_open.

您应该阅读 Brian Warner 的Ed25519 Keys文章以获得更详细的解释。

于 2014-04-23T11:32:53.680 回答