英文:
ED25519 Verification fails in Golang for payload signed in Java
问题
我有两个独立的应用程序,一个是用Java编写的,另一个是用golang编写的。Java应用程序负责生成密钥对,其中公钥与golang应用程序共享。每当需要对任何有效负载进行签名时,golang应用程序会向Java应用程序发送请求,并获得base64编码的签名作为返回结果。需要使用公钥验证此签名。但是,在golang应用程序中验证始终失败。然而,我能够在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)
}
}
}
英文:
I've two separate applications one written in Java and the other in golang. Java application is responsible to generate keypair out of which public key is shared with golang app. Whenever, there's a need to sign any payload golang app sends a request to Java app and gets the base64 encoded signature in return. This signature needs to be verified using the public key. The verification always fails in golang app. However, I'm able to successfully verify in Java app. Verification in golang works if key generation and signing the payload is also done using golang.
For Java, I'm using Bouncy Castle library and for golang using package https://pkg.go.dev/crypto/ed25519.
Generate Key
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());
Sign Payload
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 Verify Signature
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)
}
}
}
答案1
得分: 2
Java代码不对消息本身进行签名,而是对Base64编码的消息进行签名。
我怀疑你的验证失败是因为签名和验证的消息不同。然而,由于你没有在Go端发布payload
的内容,无法确定这一点。
无论如何,如果在Java端签名消息本身(通常情况下),验证将成功:
String input = "...";
byte[] payload = input.getBytes(StandardCharsets.UTF_8);
同样,如果使用未修改的Java代码,Go端验证Base64编码的消息也将成功(这可能相对不常见):
input := "..."
payload := []byte(base64.StdEncoding.EncodeToString([]byte(input)))
英文:
The Java code does not sign the message itself, but the Base64 encoded message.
I suspect that verification fails for you because signed and verified message are different. However, this cannot be answered for sure, since you did not post the content of payload
on the Go side.
In any case, verification is successful if on the Java side the message itself is signed (which is usually the case):
String input = "...";
byte[] payload = input.getBytes(StandardCharsets.UTF_8);
Similarly, verification is successful if, with unmodified Java code, the Go side verifies the Base64 encoded message (which would be rather unusual):
input := "..."
payload := []byte(base64.StdEncoding.EncodeToString([]byte(input)))
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论