github.com/geraldss/go/src@v0.0.0-20210511222824-ac7d0ebfc235/crypto/ed25519/ed25519.go (about) 1 // Copyright 2016 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. 4 5 // Package ed25519 implements the Ed25519 signature algorithm. See 6 // https://ed25519.cr.yp.to/. 7 // 8 // These functions are also compatible with the “Ed25519” function defined in 9 // RFC 8032. However, unlike RFC 8032's formulation, this package's private key 10 // representation includes a public key suffix to make multiple signing 11 // operations with the same key more efficient. This package refers to the RFC 12 // 8032 private key as the “seed”. 13 package ed25519 14 15 // This code is a port of the public domain, “ref10” implementation of ed25519 16 // from SUPERCOP. 17 18 import ( 19 "bytes" 20 "crypto" 21 "crypto/ed25519/internal/edwards25519" 22 cryptorand "crypto/rand" 23 "crypto/sha512" 24 "errors" 25 "io" 26 "strconv" 27 ) 28 29 const ( 30 // PublicKeySize is the size, in bytes, of public keys as used in this package. 31 PublicKeySize = 32 32 // PrivateKeySize is the size, in bytes, of private keys as used in this package. 33 PrivateKeySize = 64 34 // SignatureSize is the size, in bytes, of signatures generated and verified by this package. 35 SignatureSize = 64 36 // SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032. 37 SeedSize = 32 38 ) 39 40 // PublicKey is the type of Ed25519 public keys. 41 type PublicKey []byte 42 43 // Any methods implemented on PublicKey might need to also be implemented on 44 // PrivateKey, as the latter embeds the former and will expose its methods. 45 46 // Equal reports whether pub and x have the same value. 47 func (pub PublicKey) Equal(x crypto.PublicKey) bool { 48 xx, ok := x.(PublicKey) 49 if !ok { 50 return false 51 } 52 return bytes.Equal(pub, xx) 53 } 54 55 // PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer. 56 type PrivateKey []byte 57 58 // Public returns the PublicKey corresponding to priv. 59 func (priv PrivateKey) Public() crypto.PublicKey { 60 publicKey := make([]byte, PublicKeySize) 61 copy(publicKey, priv[32:]) 62 return PublicKey(publicKey) 63 } 64 65 // Equal reports whether priv and x have the same value. 66 func (priv PrivateKey) Equal(x crypto.PrivateKey) bool { 67 xx, ok := x.(PrivateKey) 68 if !ok { 69 return false 70 } 71 return bytes.Equal(priv, xx) 72 } 73 74 // Seed returns the private key seed corresponding to priv. It is provided for 75 // interoperability with RFC 8032. RFC 8032's private keys correspond to seeds 76 // in this package. 77 func (priv PrivateKey) Seed() []byte { 78 seed := make([]byte, SeedSize) 79 copy(seed, priv[:32]) 80 return seed 81 } 82 83 // Sign signs the given message with priv. 84 // Ed25519 performs two passes over messages to be signed and therefore cannot 85 // handle pre-hashed messages. Thus opts.HashFunc() must return zero to 86 // indicate the message hasn't been hashed. This can be achieved by passing 87 // crypto.Hash(0) as the value for opts. 88 func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) { 89 if opts.HashFunc() != crypto.Hash(0) { 90 return nil, errors.New("ed25519: cannot sign hashed message") 91 } 92 93 return Sign(priv, message), nil 94 } 95 96 // GenerateKey generates a public/private key pair using entropy from rand. 97 // If rand is nil, crypto/rand.Reader will be used. 98 func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) { 99 if rand == nil { 100 rand = cryptorand.Reader 101 } 102 103 seed := make([]byte, SeedSize) 104 if _, err := io.ReadFull(rand, seed); err != nil { 105 return nil, nil, err 106 } 107 108 privateKey := NewKeyFromSeed(seed) 109 publicKey := make([]byte, PublicKeySize) 110 copy(publicKey, privateKey[32:]) 111 112 return publicKey, privateKey, nil 113 } 114 115 // NewKeyFromSeed calculates a private key from a seed. It will panic if 116 // len(seed) is not SeedSize. This function is provided for interoperability 117 // with RFC 8032. RFC 8032's private keys correspond to seeds in this 118 // package. 119 func NewKeyFromSeed(seed []byte) PrivateKey { 120 // Outline the function body so that the returned key can be stack-allocated. 121 privateKey := make([]byte, PrivateKeySize) 122 newKeyFromSeed(privateKey, seed) 123 return privateKey 124 } 125 126 func newKeyFromSeed(privateKey, seed []byte) { 127 if l := len(seed); l != SeedSize { 128 panic("ed25519: bad seed length: " + strconv.Itoa(l)) 129 } 130 131 digest := sha512.Sum512(seed) 132 digest[0] &= 248 133 digest[31] &= 127 134 digest[31] |= 64 135 136 var A edwards25519.ExtendedGroupElement 137 var hBytes [32]byte 138 copy(hBytes[:], digest[:]) 139 edwards25519.GeScalarMultBase(&A, &hBytes) 140 var publicKeyBytes [32]byte 141 A.ToBytes(&publicKeyBytes) 142 143 copy(privateKey, seed) 144 copy(privateKey[32:], publicKeyBytes[:]) 145 } 146 147 // Sign signs the message with privateKey and returns a signature. It will 148 // panic if len(privateKey) is not PrivateKeySize. 149 func Sign(privateKey PrivateKey, message []byte) []byte { 150 // Outline the function body so that the returned signature can be 151 // stack-allocated. 152 signature := make([]byte, SignatureSize) 153 sign(signature, privateKey, message) 154 return signature 155 } 156 157 func sign(signature, privateKey, message []byte) { 158 if l := len(privateKey); l != PrivateKeySize { 159 panic("ed25519: bad private key length: " + strconv.Itoa(l)) 160 } 161 162 h := sha512.New() 163 h.Write(privateKey[:32]) 164 165 var digest1, messageDigest, hramDigest [64]byte 166 var expandedSecretKey [32]byte 167 h.Sum(digest1[:0]) 168 copy(expandedSecretKey[:], digest1[:]) 169 expandedSecretKey[0] &= 248 170 expandedSecretKey[31] &= 63 171 expandedSecretKey[31] |= 64 172 173 h.Reset() 174 h.Write(digest1[32:]) 175 h.Write(message) 176 h.Sum(messageDigest[:0]) 177 178 var messageDigestReduced [32]byte 179 edwards25519.ScReduce(&messageDigestReduced, &messageDigest) 180 var R edwards25519.ExtendedGroupElement 181 edwards25519.GeScalarMultBase(&R, &messageDigestReduced) 182 183 var encodedR [32]byte 184 R.ToBytes(&encodedR) 185 186 h.Reset() 187 h.Write(encodedR[:]) 188 h.Write(privateKey[32:]) 189 h.Write(message) 190 h.Sum(hramDigest[:0]) 191 var hramDigestReduced [32]byte 192 edwards25519.ScReduce(&hramDigestReduced, &hramDigest) 193 194 var s [32]byte 195 edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced) 196 197 copy(signature[:], encodedR[:]) 198 copy(signature[32:], s[:]) 199 } 200 201 // Verify reports whether sig is a valid signature of message by publicKey. It 202 // will panic if len(publicKey) is not PublicKeySize. 203 func Verify(publicKey PublicKey, message, sig []byte) bool { 204 if l := len(publicKey); l != PublicKeySize { 205 panic("ed25519: bad public key length: " + strconv.Itoa(l)) 206 } 207 208 if len(sig) != SignatureSize || sig[63]&224 != 0 { 209 return false 210 } 211 212 var A edwards25519.ExtendedGroupElement 213 var publicKeyBytes [32]byte 214 copy(publicKeyBytes[:], publicKey) 215 if !A.FromBytes(&publicKeyBytes) { 216 return false 217 } 218 edwards25519.FeNeg(&A.X, &A.X) 219 edwards25519.FeNeg(&A.T, &A.T) 220 221 h := sha512.New() 222 h.Write(sig[:32]) 223 h.Write(publicKey[:]) 224 h.Write(message) 225 var digest [64]byte 226 h.Sum(digest[:0]) 227 228 var hReduced [32]byte 229 edwards25519.ScReduce(&hReduced, &digest) 230 231 var R edwards25519.ProjectiveGroupElement 232 var s [32]byte 233 copy(s[:], sig[32:]) 234 235 // https://tools.ietf.org/html/rfc8032#section-5.1.7 requires that s be in 236 // the range [0, order) in order to prevent signature malleability. 237 if !edwards25519.ScMinimal(&s) { 238 return false 239 } 240 241 edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &s) 242 243 var checkR [32]byte 244 R.ToBytes(&checkR) 245 return bytes.Equal(sig[:32], checkR[:]) 246 }