github.com/c12o16h1/go/src@v0.0.0-20200114212001-5a151c0f00ed/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 // PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer. 44 type PrivateKey []byte 45 46 // Public returns the PublicKey corresponding to priv. 47 func (priv PrivateKey) Public() crypto.PublicKey { 48 publicKey := make([]byte, PublicKeySize) 49 copy(publicKey, priv[32:]) 50 return PublicKey(publicKey) 51 } 52 53 // Seed returns the private key seed corresponding to priv. It is provided for 54 // interoperability with RFC 8032. RFC 8032's private keys correspond to seeds 55 // in this package. 56 func (priv PrivateKey) Seed() []byte { 57 seed := make([]byte, SeedSize) 58 copy(seed, priv[:32]) 59 return seed 60 } 61 62 // Sign signs the given message with priv. 63 // Ed25519 performs two passes over messages to be signed and therefore cannot 64 // handle pre-hashed messages. Thus opts.HashFunc() must return zero to 65 // indicate the message hasn't been hashed. This can be achieved by passing 66 // crypto.Hash(0) as the value for opts. 67 func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) { 68 if opts.HashFunc() != crypto.Hash(0) { 69 return nil, errors.New("ed25519: cannot sign hashed message") 70 } 71 72 return Sign(priv, message), nil 73 } 74 75 // GenerateKey generates a public/private key pair using entropy from rand. 76 // If rand is nil, crypto/rand.Reader will be used. 77 func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) { 78 if rand == nil { 79 rand = cryptorand.Reader 80 } 81 82 seed := make([]byte, SeedSize) 83 if _, err := io.ReadFull(rand, seed); err != nil { 84 return nil, nil, err 85 } 86 87 privateKey := NewKeyFromSeed(seed) 88 publicKey := make([]byte, PublicKeySize) 89 copy(publicKey, privateKey[32:]) 90 91 return publicKey, privateKey, nil 92 } 93 94 // NewKeyFromSeed calculates a private key from a seed. It will panic if 95 // len(seed) is not SeedSize. This function is provided for interoperability 96 // with RFC 8032. RFC 8032's private keys correspond to seeds in this 97 // package. 98 func NewKeyFromSeed(seed []byte) PrivateKey { 99 // Outline the function body so that the returned key can be stack-allocated. 100 privateKey := make([]byte, PrivateKeySize) 101 newKeyFromSeed(privateKey, seed) 102 return privateKey 103 } 104 105 func newKeyFromSeed(privateKey, seed []byte) { 106 if l := len(seed); l != SeedSize { 107 panic("ed25519: bad seed length: " + strconv.Itoa(l)) 108 } 109 110 digest := sha512.Sum512(seed) 111 digest[0] &= 248 112 digest[31] &= 127 113 digest[31] |= 64 114 115 var A edwards25519.ExtendedGroupElement 116 var hBytes [32]byte 117 copy(hBytes[:], digest[:]) 118 edwards25519.GeScalarMultBase(&A, &hBytes) 119 var publicKeyBytes [32]byte 120 A.ToBytes(&publicKeyBytes) 121 122 copy(privateKey, seed) 123 copy(privateKey[32:], publicKeyBytes[:]) 124 } 125 126 // Sign signs the message with privateKey and returns a signature. It will 127 // panic if len(privateKey) is not PrivateKeySize. 128 func Sign(privateKey PrivateKey, message []byte) []byte { 129 // Outline the function body so that the returned signature can be 130 // stack-allocated. 131 signature := make([]byte, SignatureSize) 132 sign(signature, privateKey, message) 133 return signature 134 } 135 136 func sign(signature, privateKey, message []byte) { 137 if l := len(privateKey); l != PrivateKeySize { 138 panic("ed25519: bad private key length: " + strconv.Itoa(l)) 139 } 140 141 h := sha512.New() 142 h.Write(privateKey[:32]) 143 144 var digest1, messageDigest, hramDigest [64]byte 145 var expandedSecretKey [32]byte 146 h.Sum(digest1[:0]) 147 copy(expandedSecretKey[:], digest1[:]) 148 expandedSecretKey[0] &= 248 149 expandedSecretKey[31] &= 63 150 expandedSecretKey[31] |= 64 151 152 h.Reset() 153 h.Write(digest1[32:]) 154 h.Write(message) 155 h.Sum(messageDigest[:0]) 156 157 var messageDigestReduced [32]byte 158 edwards25519.ScReduce(&messageDigestReduced, &messageDigest) 159 var R edwards25519.ExtendedGroupElement 160 edwards25519.GeScalarMultBase(&R, &messageDigestReduced) 161 162 var encodedR [32]byte 163 R.ToBytes(&encodedR) 164 165 h.Reset() 166 h.Write(encodedR[:]) 167 h.Write(privateKey[32:]) 168 h.Write(message) 169 h.Sum(hramDigest[:0]) 170 var hramDigestReduced [32]byte 171 edwards25519.ScReduce(&hramDigestReduced, &hramDigest) 172 173 var s [32]byte 174 edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced) 175 176 copy(signature[:], encodedR[:]) 177 copy(signature[32:], s[:]) 178 } 179 180 // Verify reports whether sig is a valid signature of message by publicKey. It 181 // will panic if len(publicKey) is not PublicKeySize. 182 func Verify(publicKey PublicKey, message, sig []byte) bool { 183 if l := len(publicKey); l != PublicKeySize { 184 panic("ed25519: bad public key length: " + strconv.Itoa(l)) 185 } 186 187 if len(sig) != SignatureSize || sig[63]&224 != 0 { 188 return false 189 } 190 191 var A edwards25519.ExtendedGroupElement 192 var publicKeyBytes [32]byte 193 copy(publicKeyBytes[:], publicKey) 194 if !A.FromBytes(&publicKeyBytes) { 195 return false 196 } 197 edwards25519.FeNeg(&A.X, &A.X) 198 edwards25519.FeNeg(&A.T, &A.T) 199 200 h := sha512.New() 201 h.Write(sig[:32]) 202 h.Write(publicKey[:]) 203 h.Write(message) 204 var digest [64]byte 205 h.Sum(digest[:0]) 206 207 var hReduced [32]byte 208 edwards25519.ScReduce(&hReduced, &digest) 209 210 var R edwards25519.ProjectiveGroupElement 211 var s [32]byte 212 copy(s[:], sig[32:]) 213 214 // https://tools.ietf.org/html/rfc8032#section-5.1.7 requires that s be in 215 // the range [0, order) in order to prevent signature malleability. 216 if !edwards25519.ScMinimal(&s) { 217 return false 218 } 219 220 edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &s) 221 222 var checkR [32]byte 223 R.ToBytes(&checkR) 224 return bytes.Equal(sig[:32], checkR[:]) 225 }