1 // Copyright 2013 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Package ed25519 implements the Ed25519 signature algorithm. See
6 // http://ed25519.cr.yp.to/.
9 // This code is a port of the public domain, "ref10" implementation of ed25519
17 "github.com/tendermint/ed25519/edwards25519"
26 // GenerateKey generates a public/private key pair using randomness from rand.
27 func GenerateKey(rand io.Reader) (publicKey *[PublicKeySize]byte, privateKey *[PrivateKeySize]byte, err error) {
28 privateKey = new([64]byte)
29 _, err = io.ReadFull(rand, privateKey[:32])
34 publicKey = MakePublicKey(privateKey)
38 // MakePublicKey makes a publicKey from the first half of privateKey.
39 func MakePublicKey(privateKey *[PrivateKeySize]byte) (publicKey *[PublicKeySize]byte) {
40 publicKey = new([32]byte)
43 h.Write(privateKey[:32])
50 var A edwards25519.ExtendedGroupElement
52 copy(hBytes[:], digest)
53 edwards25519.GeScalarMultBase(&A, &hBytes)
56 copy(privateKey[32:], publicKey[:])
60 // Sign signs the message with privateKey and returns a signature.
61 func Sign(privateKey *[PrivateKeySize]byte, message []byte) *[SignatureSize]byte {
63 h.Write(privateKey[:32])
65 var digest1, messageDigest, hramDigest [64]byte
66 var expandedSecretKey [32]byte
68 copy(expandedSecretKey[:], digest1[:])
69 expandedSecretKey[0] &= 248
70 expandedSecretKey[31] &= 63
71 expandedSecretKey[31] |= 64
76 h.Sum(messageDigest[:0])
78 var messageDigestReduced [32]byte
79 edwards25519.ScReduce(&messageDigestReduced, &messageDigest)
80 var R edwards25519.ExtendedGroupElement
81 edwards25519.GeScalarMultBase(&R, &messageDigestReduced)
88 h.Write(privateKey[32:])
91 var hramDigestReduced [32]byte
92 edwards25519.ScReduce(&hramDigestReduced, &hramDigest)
95 edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced)
97 signature := new([64]byte)
98 copy(signature[:], encodedR[:])
99 copy(signature[32:], s[:])
103 // Verify returns true iff sig is a valid signature of message by publicKey.
104 func Verify(publicKey *[PublicKeySize]byte, message []byte, sig *[SignatureSize]byte) bool {
105 if sig[63]&224 != 0 {
109 var A edwards25519.ExtendedGroupElement
110 if !A.FromBytes(publicKey) {
113 edwards25519.FeNeg(&A.X, &A.X)
114 edwards25519.FeNeg(&A.T, &A.T)
118 h.Write(publicKey[:])
123 var hReduced [32]byte
124 edwards25519.ScReduce(&hReduced, &digest)
126 var R edwards25519.ProjectiveGroupElement
129 edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &b)
133 return subtle.ConstantTimeCompare(sig[:32], checkR[:]) == 1