poly1305.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. // Copyright 2012 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 poly1305 implements Poly1305 one-time message authentication code as
  5. // specified in https://cr.yp.to/mac/poly1305-20050329.pdf.
  6. //
  7. // Poly1305 is a fast, one-time authentication function. It is infeasible for an
  8. // attacker to generate an authenticator for a message without the key. However, a
  9. // key must only be used for a single message. Authenticating two different
  10. // messages with the same key allows an attacker to forge authenticators for other
  11. // messages with the same key.
  12. //
  13. // Poly1305 was originally coupled with AES in order to make Poly1305-AES. AES was
  14. // used with a fixed key in order to generate one-time keys from an nonce.
  15. // However, in this package AES isn't used and the one-time key is specified
  16. // directly.
  17. package poly1305
  18. import "crypto/subtle"
  19. // TagSize is the size, in bytes, of a poly1305 authenticator.
  20. const TagSize = 16
  21. // Sum generates an authenticator for msg using a one-time key and puts the
  22. // 16-byte result into out. Authenticating two different messages with the same
  23. // key allows an attacker to forge messages at will.
  24. func Sum(out *[16]byte, m []byte, key *[32]byte) {
  25. h := New(key)
  26. h.Write(m)
  27. h.Sum(out[:0])
  28. }
  29. // Verify returns true if mac is a valid authenticator for m with the given key.
  30. func Verify(mac *[16]byte, m []byte, key *[32]byte) bool {
  31. var tmp [16]byte
  32. Sum(&tmp, m, key)
  33. return subtle.ConstantTimeCompare(tmp[:], mac[:]) == 1
  34. }
  35. // New returns a new MAC computing an authentication
  36. // tag of all data written to it with the given key.
  37. // This allows writing the message progressively instead
  38. // of passing it as a single slice. Common users should use
  39. // the Sum function instead.
  40. //
  41. // The key must be unique for each message, as authenticating
  42. // two different messages with the same key allows an attacker
  43. // to forge messages at will.
  44. func New(key *[32]byte) *MAC {
  45. m := &MAC{}
  46. initialize(key, &m.macState)
  47. return m
  48. }
  49. // MAC is an io.Writer computing an authentication tag
  50. // of the data written to it.
  51. //
  52. // MAC cannot be used like common hash.Hash implementations,
  53. // because using a poly1305 key twice breaks its security.
  54. // Therefore writing data to a running MAC after calling
  55. // Sum or Verify causes it to panic.
  56. type MAC struct {
  57. mac // platform-dependent implementation
  58. finalized bool
  59. }
  60. // Size returns the number of bytes Sum will return.
  61. func (h *MAC) Size() int { return TagSize }
  62. // Write adds more data to the running message authentication code.
  63. // It never returns an error.
  64. //
  65. // It must not be called after the first call of Sum or Verify.
  66. func (h *MAC) Write(p []byte) (n int, err error) {
  67. if h.finalized {
  68. panic("poly1305: write to MAC after Sum or Verify")
  69. }
  70. return h.mac.Write(p)
  71. }
  72. // Sum computes the authenticator of all data written to the
  73. // message authentication code.
  74. func (h *MAC) Sum(b []byte) []byte {
  75. var mac [TagSize]byte
  76. h.mac.Sum(&mac)
  77. h.finalized = true
  78. return append(b, mac[:]...)
  79. }
  80. // Verify returns whether the authenticator of all data written to
  81. // the message authentication code matches the expected value.
  82. func (h *MAC) Verify(expected []byte) bool {
  83. var mac [TagSize]byte
  84. h.mac.Sum(&mac)
  85. h.finalized = true
  86. return subtle.ConstantTimeCompare(expected, mac[:]) == 1
  87. }