signature.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. // Copyright (C) 2015 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at https://mozilla.org/MPL/2.0/.
  6. // Package signature provides simple methods to create and verify signatures
  7. // in PEM format.
  8. package signature
  9. import (
  10. "crypto/ecdsa"
  11. "crypto/elliptic"
  12. "crypto/sha256"
  13. "crypto/x509"
  14. "encoding/asn1"
  15. "encoding/pem"
  16. "errors"
  17. "fmt"
  18. "io"
  19. "math/big"
  20. "github.com/syncthing/syncthing/lib/rand"
  21. )
  22. // GenerateKeys returns a new key pair, with the private and public key
  23. // encoded in PEM format.
  24. func GenerateKeys() (privKey []byte, pubKey []byte, err error) {
  25. // Generate a new key pair
  26. key, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
  27. if err != nil {
  28. return nil, nil, err
  29. }
  30. // Marshal the private key
  31. bs, err := x509.MarshalECPrivateKey(key)
  32. if err != nil {
  33. return nil, nil, err
  34. }
  35. // Encode it in PEM format
  36. privKey = pem.EncodeToMemory(&pem.Block{
  37. Type: "EC PRIVATE KEY",
  38. Bytes: bs,
  39. })
  40. // Marshal the public key
  41. bs, err = x509.MarshalPKIXPublicKey(&key.PublicKey)
  42. if err != nil {
  43. return nil, nil, err
  44. }
  45. // Encode it in PEM format
  46. pubKey = pem.EncodeToMemory(&pem.Block{
  47. Type: "EC PUBLIC KEY",
  48. Bytes: bs,
  49. })
  50. return
  51. }
  52. // Sign computes the hash of data and signs it with the private key, returning
  53. // a signature in PEM format.
  54. func Sign(privKeyPEM []byte, data io.Reader) ([]byte, error) {
  55. // Parse the private key
  56. key, err := loadPrivateKey(privKeyPEM)
  57. if err != nil {
  58. return nil, err
  59. }
  60. // Hash the reader data
  61. hash, err := hashReader(data)
  62. if err != nil {
  63. return nil, err
  64. }
  65. // Sign the hash
  66. r, s, err := ecdsa.Sign(rand.Reader, key, hash)
  67. if err != nil {
  68. return nil, err
  69. }
  70. // Marshal the signature using ASN.1
  71. sig, err := marshalSignature(r, s)
  72. if err != nil {
  73. return nil, err
  74. }
  75. // Encode it in a PEM block
  76. bs := pem.EncodeToMemory(&pem.Block{
  77. Type: "SIGNATURE",
  78. Bytes: sig,
  79. })
  80. return bs, nil
  81. }
  82. // Verify computes the hash of data and compares it to the signature using the
  83. // given public key. Returns nil if the signature is correct.
  84. func Verify(pubKeyPEM []byte, signature []byte, data io.Reader) error {
  85. // Parse the public key
  86. key, err := loadPublicKey(pubKeyPEM)
  87. if err != nil {
  88. return err
  89. }
  90. // Parse the signature
  91. block, _ := pem.Decode(signature)
  92. if block == nil || block.Bytes == nil {
  93. return errors.New("unsupported signature format")
  94. }
  95. r, s, err := unmarshalSignature(block.Bytes)
  96. if err != nil {
  97. return err
  98. }
  99. // Compute the hash of the data
  100. hash, err := hashReader(data)
  101. if err != nil {
  102. return err
  103. }
  104. // Verify the signature
  105. if !ecdsa.Verify(key, hash, r, s) {
  106. return errors.New("incorrect signature")
  107. }
  108. return nil
  109. }
  110. // hashReader returns the SHA256 hash of the reader
  111. func hashReader(r io.Reader) ([]byte, error) {
  112. h := sha256.New()
  113. if _, err := io.Copy(h, r); err != nil {
  114. return nil, err
  115. }
  116. hash := []byte(fmt.Sprintf("%x", h.Sum(nil)))
  117. return hash, nil
  118. }
  119. // loadPrivateKey returns the ECDSA private key structure for the given PEM
  120. // data.
  121. func loadPrivateKey(bs []byte) (*ecdsa.PrivateKey, error) {
  122. block, _ := pem.Decode(bs)
  123. return x509.ParseECPrivateKey(block.Bytes)
  124. }
  125. // loadPublicKey returns the ECDSA public key structure for the given PEM
  126. // data.
  127. func loadPublicKey(bs []byte) (*ecdsa.PublicKey, error) {
  128. // Decode and parse the public key PEM block
  129. block, _ := pem.Decode(bs)
  130. if block == nil || block.Bytes == nil {
  131. return nil, errors.New("unsupported public key format")
  132. }
  133. intf, err := x509.ParsePKIXPublicKey(block.Bytes)
  134. if err != nil {
  135. return nil, err
  136. }
  137. // It should be an ECDSA public key
  138. pk, ok := intf.(*ecdsa.PublicKey)
  139. if !ok {
  140. return nil, errors.New("unsupported public key format")
  141. }
  142. return pk, nil
  143. }
  144. // A wrapper around the signature integers so that we can marshal and
  145. // unmarshal them.
  146. type signature struct {
  147. R, S *big.Int
  148. }
  149. // marhalSignature returns ASN.1 encoded bytes for the given integers,
  150. // suitable for PEM encoding.
  151. func marshalSignature(r, s *big.Int) ([]byte, error) {
  152. sig := signature{
  153. R: r,
  154. S: s,
  155. }
  156. bs, err := asn1.Marshal(sig)
  157. if err != nil {
  158. return nil, err
  159. }
  160. return bs, nil
  161. }
  162. // unmarshalSignature returns the R and S integers from the given ASN.1
  163. // encoded signature.
  164. func unmarshalSignature(sig []byte) (r *big.Int, s *big.Int, err error) {
  165. var ts signature
  166. _, err = asn1.Unmarshal(sig, &ts)
  167. if err != nil {
  168. return nil, nil, err
  169. }
  170. return ts.R, ts.S, nil
  171. }