github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/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 import ( 16 "bytes" 17 "crypto" 18 "crypto/internal/edwards25519" 19 cryptorand "crypto/rand" 20 "crypto/sha512" 21 "errors" 22 "io" 23 "strconv" 24 ) 25 26 const ( 27 // PublicKeySize is the size, in bytes, of public keys as used in this package. 28 PublicKeySize = 32 29 // PrivateKeySize is the size, in bytes, of private keys as used in this package. 30 PrivateKeySize = 64 31 // SignatureSize is the size, in bytes, of signatures generated and verified by this package. 32 SignatureSize = 64 33 // SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032. 34 SeedSize = 32 35 ) 36 37 // PublicKey is the type of Ed25519 public keys. 38 type PublicKey []byte 39 40 // Any methods implemented on PublicKey might need to also be implemented on 41 // PrivateKey, as the latter embeds the former and will expose its methods. 42 43 // Equal reports whether pub and x have the same value. 44 func (pub PublicKey) Equal(x crypto.PublicKey) bool { 45 xx, ok := x.(PublicKey) 46 if !ok { 47 return false 48 } 49 return bytes.Equal(pub, xx) 50 } 51 52 // PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer. 53 type PrivateKey []byte 54 55 // Public returns the PublicKey corresponding to priv. 56 func (priv PrivateKey) Public() crypto.PublicKey { 57 publicKey := make([]byte, PublicKeySize) 58 copy(publicKey, priv[32:]) 59 return PublicKey(publicKey) 60 } 61 62 // Equal reports whether priv and x have the same value. 63 func (priv PrivateKey) Equal(x crypto.PrivateKey) bool { 64 xx, ok := x.(PrivateKey) 65 if !ok { 66 return false 67 } 68 return bytes.Equal(priv, xx) 69 } 70 71 // Seed returns the private key seed corresponding to priv. It is provided for 72 // interoperability with RFC 8032. RFC 8032's private keys correspond to seeds 73 // in this package. 74 func (priv PrivateKey) Seed() []byte { 75 return bytes.Clone(priv[:SeedSize]) 76 } 77 78 // Sign signs the given message with priv. 79 // Ed25519 performs two passes over messages to be signed and therefore cannot 80 // handle pre-hashed messages. Thus opts.HashFunc() must return zero to 81 // indicate the message hasn't been hashed. This can be achieved by passing 82 // crypto.Hash(0) as the value for opts. 83 func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) { 84 if opts.HashFunc() != crypto.Hash(0) { 85 return nil, errors.New("ed25519: cannot sign hashed message") 86 } 87 88 return Sign(priv, message), nil 89 } 90 91 // GenerateKey generates a public/private key pair using entropy from rand. 92 // If rand is nil, crypto/rand.Reader will be used. 93 func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) { 94 if rand == nil { 95 rand = cryptorand.Reader 96 } 97 98 seed := make([]byte, SeedSize) 99 if _, err := io.ReadFull(rand, seed); err != nil { 100 return nil, nil, err 101 } 102 103 privateKey := NewKeyFromSeed(seed) 104 publicKey := make([]byte, PublicKeySize) 105 copy(publicKey, privateKey[32:]) 106 107 return publicKey, privateKey, nil 108 } 109 110 // NewKeyFromSeed calculates a private key from a seed. It will panic if 111 // len(seed) is not SeedSize. This function is provided for interoperability 112 // with RFC 8032. RFC 8032's private keys correspond to seeds in this 113 // package. 114 func NewKeyFromSeed(seed []byte) PrivateKey { 115 // Outline the function body so that the returned key can be stack-allocated. 116 privateKey := make([]byte, PrivateKeySize) 117 newKeyFromSeed(privateKey, seed) 118 return privateKey 119 } 120 121 func newKeyFromSeed(privateKey, seed []byte) { 122 if l := len(seed); l != SeedSize { 123 panic("ed25519: bad seed length: " + strconv.Itoa(l)) 124 } 125 126 h := sha512.Sum512(seed) 127 s, err := edwards25519.NewScalar().SetBytesWithClamping(h[:32]) 128 if err != nil { 129 panic("ed25519: internal error: setting scalar failed") 130 } 131 A := (&edwards25519.Point{}).ScalarBaseMult(s) 132 133 publicKey := A.Bytes() 134 135 copy(privateKey, seed) 136 copy(privateKey[32:], publicKey) 137 } 138 139 // Sign signs the message with privateKey and returns a signature. It will 140 // panic if len(privateKey) is not PrivateKeySize. 141 func Sign(privateKey PrivateKey, message []byte) []byte { 142 // Outline the function body so that the returned signature can be 143 // stack-allocated. 144 signature := make([]byte, SignatureSize) 145 sign(signature, privateKey, message) 146 return signature 147 } 148 149 func sign(signature, privateKey, message []byte) { 150 if l := len(privateKey); l != PrivateKeySize { 151 panic("ed25519: bad private key length: " + strconv.Itoa(l)) 152 } 153 seed, publicKey := privateKey[:SeedSize], privateKey[SeedSize:] 154 155 h := sha512.Sum512(seed) 156 s, err := edwards25519.NewScalar().SetBytesWithClamping(h[:32]) 157 if err != nil { 158 panic("ed25519: internal error: setting scalar failed") 159 } 160 prefix := h[32:] 161 162 mh := sha512.New() 163 mh.Write(prefix) 164 mh.Write(message) 165 messageDigest := make([]byte, 0, sha512.Size) 166 messageDigest = mh.Sum(messageDigest) 167 r, err := edwards25519.NewScalar().SetUniformBytes(messageDigest) 168 if err != nil { 169 panic("ed25519: internal error: setting scalar failed") 170 } 171 172 R := (&edwards25519.Point{}).ScalarBaseMult(r) 173 174 kh := sha512.New() 175 kh.Write(R.Bytes()) 176 kh.Write(publicKey) 177 kh.Write(message) 178 hramDigest := make([]byte, 0, sha512.Size) 179 hramDigest = kh.Sum(hramDigest) 180 k, err := edwards25519.NewScalar().SetUniformBytes(hramDigest) 181 if err != nil { 182 panic("ed25519: internal error: setting scalar failed") 183 } 184 185 S := edwards25519.NewScalar().MultiplyAdd(k, s, r) 186 187 copy(signature[:32], R.Bytes()) 188 copy(signature[32:], S.Bytes()) 189 } 190 191 // Verify reports whether sig is a valid signature of message by publicKey. It 192 // will panic if len(publicKey) is not PublicKeySize. 193 func Verify(publicKey PublicKey, message, sig []byte) bool { 194 if l := len(publicKey); l != PublicKeySize { 195 panic("ed25519: bad public key length: " + strconv.Itoa(l)) 196 } 197 198 if len(sig) != SignatureSize || sig[63]&224 != 0 { 199 return false 200 } 201 202 A, err := (&edwards25519.Point{}).SetBytes(publicKey) 203 if err != nil { 204 return false 205 } 206 207 kh := sha512.New() 208 kh.Write(sig[:32]) 209 kh.Write(publicKey) 210 kh.Write(message) 211 hramDigest := make([]byte, 0, sha512.Size) 212 hramDigest = kh.Sum(hramDigest) 213 k, err := edwards25519.NewScalar().SetUniformBytes(hramDigest) 214 if err != nil { 215 panic("ed25519: internal error: setting scalar failed") 216 } 217 218 S, err := edwards25519.NewScalar().SetCanonicalBytes(sig[32:]) 219 if err != nil { 220 return false 221 } 222 223 // [S]B = R + [k]A --> [k](-A) + [S]B = R 224 minusA := (&edwards25519.Point{}).Negate(A) 225 R := (&edwards25519.Point{}).VarTimeDoubleScalarBaseMult(k, minusA, S) 226 227 return bytes.Equal(sig[:32], R.Bytes()) 228 }