ED25519 在 Golang 中验证登录的负载失败 Java

ED25519 Verification fails in Golang for payload signed in Java

我有两个独立的应用程序,一个用 Java 编写,另一个用 golang 编写。 Java 应用程序负责生成密钥对,其中 public 密钥与 golang 应用程序共享。每当需要对任何有效负载进行签名时,golang 应用程序都会向 Java 应用程序发送请求,并在 return 中获取 base64 编码的签名。此签名需要使用 public 密钥进行验证。 golang app 验证总是失败。但是,我能够在 Java 应用程序中成功验证。如果密钥生成和有效负载签名也使用 golang 完成,则 golang 中的验证有效。

对于 Java,我正在使用 Bouncy Castle 库,对于 golang,我使用包 https://pkg.go.dev/crypto/ed25519

生成密钥

Ed25519KeyPairGenerator keyPairGenerator = new Ed25519KeyPairGenerator();
keyPairGenerator.init(new Ed25519KeyGenerationParameters(new SecureRandom()));
AsymmetricCipherKeyPair asymmetricCipherKeyPair = keyPairGenerator.generateKeyPair();
Ed25519PrivateKeyParameters privateKey = (Ed25519PrivateKeyParameters) asymmetricCipherKeyPair.getPrivate();
Ed25519PublicKeyParameters publicKey = (Ed25519PublicKeyParameters) asymmetricCipherKeyPair.getPublic();
String privateKey = Base64.getEncoder().encodeToString(privateKey.getEncoded());
String publicKey = Base64.getEncoder().encodeToString(publicKey.getEncoded());

签署有效载荷

byte[] privateKeyContent = Base64.getDecoder().decode(privateKeyInfo);
Ed25519PrivateKeyParameters privateKeyParameters = new Ed25519PrivateKeyParameters(privateKeyContent, 0);

byte[] payload = Base64.getEncoder().encode(input.getBytes(StandardCharsets.UTF_8));
Signer signer = new Ed25519Signer();
signer.init(true, privateKeyParameters);
signer.update(payload, 0, payload.length);
byte[] signature = signer.generateSignature();
String encodedSignature = Base64.getEncoder().encodeToString(signature);

Golang 验证签名

func verifySignature(payload []byte, publicKeyStr string, signatureStr string) {
    publicKey, error := base64.StdEncoding.DecodeString(publicKeyStr)
    if error != nil {
        fmt.Println(error)
    } else {
        signature, error := base64.StdEncoding.DecodeString(signatureStr)
        if error != nil {
            fmt.Println(error)
        } else {
            isVerified := ed25519.Verify(publicKey, payload, signature)
            fmt.Println(isVerified)
        }

    }
}

Java 代码不签署消息 本身 ,而是 Base64 编码的 消息。

我怀疑您的验证失败,因为已签名的消息和已验证的消息不同。但是,这不能肯定地回答,因为你没有 post Go 端 payload 的内容。

无论如何,如果在 Java 端对消息本身进行了签名(通常是这种情况),则验证成功:

String input = "...";
byte[] payload = input.getBytes(StandardCharsets.UTF_8);

同样,如果使用未修改的 Java 代码,Go 端验证 Base64 编码的消息(这很不寻常),则验证成功:

input := "..."
payload := []byte(base64.StdEncoding.EncodeToString([]byte(input)))