You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

218 line
6.3 KiB

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