sign.go 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. // Copyright 2018 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 sign signs small messages using public-key cryptography.
  5. //
  6. // Sign uses Ed25519 to sign messages. The length of messages is not hidden.
  7. // Messages should be small because:
  8. // 1. The whole message needs to be held in memory to be processed.
  9. // 2. Using large messages pressures implementations on small machines to process
  10. // plaintext without verifying the signature. This is very dangerous, and this API
  11. // discourages it, but a protocol that uses excessive message sizes might present
  12. // some implementations with no other choice.
  13. // 3. Performance may be improved by working with messages that fit into data caches.
  14. // Thus large amounts of data should be chunked so that each message is small.
  15. //
  16. // This package is not interoperable with the current release of NaCl
  17. // (https://nacl.cr.yp.to/sign.html), which does not support Ed25519 yet. However,
  18. // it is compatible with the NaCl fork libsodium (https://www.libsodium.org), as well
  19. // as TweetNaCl (https://tweetnacl.cr.yp.to/).
  20. package sign
  21. import (
  22. "io"
  23. "golang.org/x/crypto/ed25519"
  24. )
  25. // Overhead is the number of bytes of overhead when signing a message.
  26. const Overhead = 64
  27. // GenerateKey generates a new public/private key pair suitable for use with
  28. // Sign and Open.
  29. func GenerateKey(rand io.Reader) (publicKey *[32]byte, privateKey *[64]byte, err error) {
  30. pub, priv, err := ed25519.GenerateKey(rand)
  31. if err != nil {
  32. return nil, nil, err
  33. }
  34. publicKey, privateKey = new([32]byte), new([64]byte)
  35. copy((*publicKey)[:], pub)
  36. copy((*privateKey)[:], priv)
  37. return publicKey, privateKey, nil
  38. }
  39. // Sign appends a signed copy of message to out, which will be Overhead bytes
  40. // longer than the original and must not overlap it.
  41. func Sign(out, message []byte, privateKey *[64]byte) []byte {
  42. sig := ed25519.Sign(ed25519.PrivateKey((*privateKey)[:]), message)
  43. ret, out := sliceForAppend(out, Overhead+len(message))
  44. copy(out, sig)
  45. copy(out[Overhead:], message)
  46. return ret
  47. }
  48. // Open verifies a signed message produced by Sign and appends the message to
  49. // out, which must not overlap the signed message. The output will be Overhead
  50. // bytes smaller than the signed message.
  51. func Open(out, signedMessage []byte, publicKey *[32]byte) ([]byte, bool) {
  52. if len(signedMessage) < Overhead {
  53. return nil, false
  54. }
  55. if !ed25519.Verify(ed25519.PublicKey((*publicKey)[:]), signedMessage[Overhead:], signedMessage[:Overhead]) {
  56. return nil, false
  57. }
  58. ret, out := sliceForAppend(out, len(signedMessage)-Overhead)
  59. copy(out, signedMessage[Overhead:])
  60. return ret, true
  61. }
  62. // sliceForAppend takes a slice and a requested number of bytes. It returns a
  63. // slice with the contents of the given slice followed by that many bytes and a
  64. // second slice that aliases into it and contains only the extra bytes. If the
  65. // original slice has sufficient capacity then no allocation is performed.
  66. func sliceForAppend(in []byte, n int) (head, tail []byte) {
  67. if total := len(in) + n; cap(in) >= total {
  68. head = in[:total]
  69. } else {
  70. head = make([]byte, total)
  71. copy(head, in)
  72. }
  73. tail = head[len(in):]
  74. return
  75. }