Files
tsnet-proxy/vendor/github.com/hdevalence/ed25519consensus/ed25519.go
2024-11-01 17:43:06 +00:00

68 lines
1.9 KiB
Go

// Copyright 2016 The Go Authors. All rights reserved.
// Copyright 2016 Henry de Valence. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package ed25519consensus implements Ed25519 verification according to ZIP215.
package ed25519consensus
import (
"crypto/ed25519"
"crypto/sha512"
"filippo.io/edwards25519"
)
// Verify reports whether sig is a valid signature of message by
// publicKey, using precisely-specified validation criteria (ZIP 215) suitable
// for use in consensus-critical contexts.
func Verify(publicKey ed25519.PublicKey, message, sig []byte) bool {
if l := len(publicKey); l != ed25519.PublicKeySize {
return false
}
if len(sig) != ed25519.SignatureSize || sig[63]&224 != 0 {
return false
}
// ZIP215: this works because SetBytes does not check that encodings are canonical.
A, err := new(edwards25519.Point).SetBytes(publicKey)
if err != nil {
return false
}
A.Negate(A)
h := sha512.New()
h.Write(sig[:32])
h.Write(publicKey[:])
h.Write(message)
var digest [64]byte
h.Sum(digest[:0])
hReduced, err := new(edwards25519.Scalar).SetUniformBytes(digest[:])
if err != nil {
return false
}
// ZIP215: this works because SetBytes does not check that encodings are canonical.
checkR, err := new(edwards25519.Point).SetBytes(sig[:32])
if err != nil {
return false
}
// https://tools.ietf.org/html/rfc8032#section-5.1.7 requires that s be in
// the range [0, order) in order to prevent signature malleability.
// ZIP215: This is also required by ZIP215.
s, err := new(edwards25519.Scalar).SetCanonicalBytes(sig[32:])
if err != nil {
return false
}
R := new(edwards25519.Point).VarTimeDoubleScalarBaseMult(hReduced, A, s)
// ZIP215: We want to check [8](R - checkR) == 0
p := new(edwards25519.Point).Subtract(R, checkR) // p = R - checkR
p.MultByCofactor(p)
return p.Equal(edwards25519.NewIdentityPoint()) == 1 // p == 0
}