{"record":{"id":"71e0d6cbbdbf549e","repo":"golang/go","slug":"ed25519-verification-failure","errorCode":null,"errorMessage":"Ed25519 verification failure","messagePattern":"Ed25519 verification failure","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/tls/auth.go","lineNumber":47,"sourceCode":"\t\th.Write(signed)\n\t\tsigned = h.Sum(nil)\n\t}\n\tswitch sigType {\n\tcase signatureECDSA:\n\t\tpubKey, ok := pubkey.(*ecdsa.PublicKey)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"expected an ECDSA public key, got %T\", pubkey)\n\t\t}\n\t\tif !ecdsa.VerifyASN1(pubKey, signed, sig) {\n\t\t\treturn errors.New(\"ECDSA verification failure\")\n\t\t}\n\tcase signatureEd25519:\n\t\tpubKey, ok := pubkey.(ed25519.PublicKey)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"expected an Ed25519 public key, got %T\", pubkey)\n\t\t}\n\t\tif !ed25519.Verify(pubKey, signed, sig) {\n\t\t\treturn errors.New(\"Ed25519 verification failure\")\n\t\t}\n\tcase signatureMLDSA:\n\t\tpubKey, ok := pubkey.(*mldsa.PublicKey)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"expected an ML-DSA public key, got %T\", pubkey)\n\t\t}\n\t\tif err := mldsa.Verify(pubKey, signed, sig, nil); err != nil {\n\t\t\treturn fmt.Errorf(\"ML-DSA verification failure: %w\", err)\n\t\t}\n\tcase signaturePKCS1v15:\n\t\tpubKey, ok := pubkey.(*rsa.PublicKey)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"expected an RSA public key, got %T\", pubkey)\n\t\t}\n\t\tif err := rsa.VerifyPKCS1v15(pubKey, hashFunc, signed, sig); err != nil {\n\t\t\treturn err\n\t\t}\n\tcase signatureRSAPSS:","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/tls/auth.go#L29-L65","documentation":"Thrown by tls verifyHandshakeSignature when ed25519.Verify returns false for an Ed25519 signature. The pubkey was confirmed to be an ed25519.PublicKey, so the failure is a true signature mismatch: the signature does not authenticate the signed data under that key.","triggerScenarios":"During a TLS handshake the peer presents an Ed25519-signed handshake message whose signature fails ed25519.Verify(pub, signed, sig). Path: signatureEd25519 in verifyHandshakeSignature.","commonSituations":"Wrong public key associated with the certificate; signature computed over different transcript bytes (e.g., a MITM altering messages); truncated or altered signature on the wire; an Ed25519 implementation that deviates from RFC 8032.","solutions":["Confirm the certificate's Ed25519 public key matches the key that produced the signature.","Trace the exact signed bytes on both sides to rule out transcript divergence.","Validate the 64-byte signature length and encoding before verification.","Use crypto/ed25519 for both signing and verifying to guarantee RFC 8032 conformance."],"exampleFix":"// before\nok := ed25519.Verify(pub, wrongMessage, sig) // different bytes\n\n// after\nok := ed25519.Verify(pub, handshakeTranscript, sig)\nif !ok { return errors.New(\"bad ed25519 signature\") }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"func isEd25519PubKey(k any) bool {\n    _, ok := k.(ed25519.PublicKey)\n    return ok\n}","tryCatchPattern":"if err := tlsConn.VerifyHostname(name); err != nil {\n    if strings.Contains(err.Error(), \"Ed25519 verification failure\") {\n        // likely wrong key, tampered signature, or transcript divergence\n    }\n}","preventionTips":["Use crypto/ed25519 on both ends to guarantee RFC 8032 semantics.","Confirm the certificate's Ed25519 public key matches the signer.","Check signature length is 64 bytes before verifying.","Trace the signed bytes on both sides when diagnosing failures."],"tags":["crypto","tls","ed25519","signature","go"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T08:17:17.861Z"}