github.com/maenmax/kairep@v0.0.0-20210218001208-55bf3df36788/src/golang.org/x/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 // http://ed25519.cr.yp.to/. 7 // 8 // These functions are also compatible with the “Ed25519” function defined in 9 // https://tools.ietf.org/html/draft-irtf-cfrg-eddsa-05. 10 package ed25519 11 12 // This code is a port of the public domain, “ref10” implementation of ed25519 13 // from SUPERCOP. 14 15 import ( 16 "crypto" 17 cryptorand "crypto/rand" 18 "crypto/sha512" 19 "crypto/subtle" 20 "errors" 21 "io" 22 "strconv" 23 24 "golang.org/x/crypto/ed25519/internal/edwards25519" 25 ) 26 27 const ( 28 // PublicKeySize is the size, in bytes, of public keys as used in this package. 29 PublicKeySize = 32 30 // PrivateKeySize is the size, in bytes, of private keys as used in this package. 31 PrivateKeySize = 64 32 // SignatureSize is the size, in bytes, of signatures generated and verified by this package. 33 SignatureSize = 64 34 ) 35 36 // PublicKey is the type of Ed25519 public keys. 37 type PublicKey []byte 38 39 // PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer. 40 type PrivateKey []byte 41 42 // Public returns the PublicKey corresponding to priv. 43 func (priv PrivateKey) Public() crypto.PublicKey { 44 publicKey := make([]byte, PublicKeySize) 45 copy(publicKey, priv[32:]) 46 return PublicKey(publicKey) 47 } 48 49 // Sign signs the given message with priv. 50 // Ed25519 performs two passes over messages to be signed and therefore cannot 51 // handle pre-hashed messages. Thus opts.HashFunc() must return zero to 52 // indicate the message hasn't been hashed. This can be achieved by passing 53 // crypto.Hash(0) as the value for opts. 54 func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) { 55 if opts.HashFunc() != crypto.Hash(0) { 56 return nil, errors.New("ed25519: cannot sign hashed message") 57 } 58 59 return Sign(priv, message), nil 60 } 61 62 // GenerateKey generates a public/private key pair using entropy from rand. 63 // If rand is nil, crypto/rand.Reader will be used. 64 func GenerateKey(rand io.Reader) (publicKey PublicKey, privateKey PrivateKey, err error) { 65 if rand == nil { 66 rand = cryptorand.Reader 67 } 68 69 privateKey = make([]byte, PrivateKeySize) 70 publicKey = make([]byte, PublicKeySize) 71 _, err = io.ReadFull(rand, privateKey[:32]) 72 if err != nil { 73 return nil, nil, err 74 } 75 76 digest := sha512.Sum512(privateKey[:32]) 77 digest[0] &= 248 78 digest[31] &= 127 79 digest[31] |= 64 80 81 var A edwards25519.ExtendedGroupElement 82 var hBytes [32]byte 83 copy(hBytes[:], digest[:]) 84 edwards25519.GeScalarMultBase(&A, &hBytes) 85 var publicKeyBytes [32]byte 86 A.ToBytes(&publicKeyBytes) 87 88 copy(privateKey[32:], publicKeyBytes[:]) 89 copy(publicKey, publicKeyBytes[:]) 90 91 return publicKey, privateKey, nil 92 } 93 94 // Sign signs the message with privateKey and returns a signature. It will 95 // panic if len(privateKey) is not PrivateKeySize. 96 func Sign(privateKey PrivateKey, message []byte) []byte { 97 if l := len(privateKey); l != PrivateKeySize { 98 panic("ed25519: bad private key length: " + strconv.Itoa(l)) 99 } 100 101 h := sha512.New() 102 h.Write(privateKey[:32]) 103 104 var digest1, messageDigest, hramDigest [64]byte 105 var expandedSecretKey [32]byte 106 h.Sum(digest1[:0]) 107 copy(expandedSecretKey[:], digest1[:]) 108 expandedSecretKey[0] &= 248 109 expandedSecretKey[31] &= 63 110 expandedSecretKey[31] |= 64 111 112 h.Reset() 113 h.Write(digest1[32:]) 114 h.Write(message) 115 h.Sum(messageDigest[:0]) 116 117 var messageDigestReduced [32]byte 118 edwards25519.ScReduce(&messageDigestReduced, &messageDigest) 119 var R edwards25519.ExtendedGroupElement 120 edwards25519.GeScalarMultBase(&R, &messageDigestReduced) 121 122 var encodedR [32]byte 123 R.ToBytes(&encodedR) 124 125 h.Reset() 126 h.Write(encodedR[:]) 127 h.Write(privateKey[32:]) 128 h.Write(message) 129 h.Sum(hramDigest[:0]) 130 var hramDigestReduced [32]byte 131 edwards25519.ScReduce(&hramDigestReduced, &hramDigest) 132 133 var s [32]byte 134 edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced) 135 136 signature := make([]byte, SignatureSize) 137 copy(signature[:], encodedR[:]) 138 copy(signature[32:], s[:]) 139 140 return signature 141 } 142 143 // Verify reports whether sig is a valid signature of message by publicKey. It 144 // will panic if len(publicKey) is not PublicKeySize. 145 func Verify(publicKey PublicKey, message, sig []byte) bool { 146 if l := len(publicKey); l != PublicKeySize { 147 panic("ed25519: bad public key length: " + strconv.Itoa(l)) 148 } 149 150 if len(sig) != SignatureSize || sig[63]&224 != 0 { 151 return false 152 } 153 154 var A edwards25519.ExtendedGroupElement 155 var publicKeyBytes [32]byte 156 copy(publicKeyBytes[:], publicKey) 157 if !A.FromBytes(&publicKeyBytes) { 158 return false 159 } 160 edwards25519.FeNeg(&A.X, &A.X) 161 edwards25519.FeNeg(&A.T, &A.T) 162 163 h := sha512.New() 164 h.Write(sig[:32]) 165 h.Write(publicKey[:]) 166 h.Write(message) 167 var digest [64]byte 168 h.Sum(digest[:0]) 169 170 var hReduced [32]byte 171 edwards25519.ScReduce(&hReduced, &digest) 172 173 var R edwards25519.ProjectiveGroupElement 174 var b [32]byte 175 copy(b[:], sig[32:]) 176 edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &b) 177 178 var checkR [32]byte 179 R.ToBytes(&checkR) 180 return subtle.ConstantTimeCompare(sig[:32], checkR[:]) == 1 181 }