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