Source file src/pkg/crypto/hmac/hmac.go
1 // Copyright 2009 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 hmac implements the Keyed-Hash Message Authentication Code (HMAC) as 6 // defined in U.S. Federal Information Processing Standards Publication 198. 7 // An HMAC is a cryptographic hash that uses a key to sign a message. 8 // The receiver verifies the hash by recomputing it using the same key. 9 package hmac 10 11 import ( 12 "hash" 13 ) 14 15 // FIPS 198: 16 // http://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf 17 18 // key is zero padded to the block size of the hash function 19 // ipad = 0x36 byte repeated for key length 20 // opad = 0x5c byte repeated for key length 21 // hmac = H([key ^ opad] H([key ^ ipad] text)) 22 23 type hmac struct { 24 size int 25 blocksize int 26 key, tmp []byte 27 outer, inner hash.Hash 28 } 29 30 func (h *hmac) tmpPad(xor byte) { 31 for i, k := range h.key { 32 h.tmp[i] = xor ^ k 33 } 34 for i := len(h.key); i < h.blocksize; i++ { 35 h.tmp[i] = xor 36 } 37 } 38 39 func (h *hmac) Sum(in []byte) []byte { 40 origLen := len(in) 41 in = h.inner.Sum(in) 42 h.tmpPad(0x5c) 43 copy(h.tmp[h.blocksize:], in[origLen:]) 44 h.outer.Reset() 45 h.outer.Write(h.tmp) 46 return h.outer.Sum(in[:origLen]) 47 } 48 49 func (h *hmac) Write(p []byte) (n int, err error) { 50 return h.inner.Write(p) 51 } 52 53 func (h *hmac) Size() int { return h.size } 54 55 func (h *hmac) BlockSize() int { return h.blocksize } 56 57 func (h *hmac) Reset() { 58 h.inner.Reset() 59 h.tmpPad(0x36) 60 h.inner.Write(h.tmp[0:h.blocksize]) 61 } 62 63 // New returns a new HMAC hash using the given hash.Hash type and key. 64 func New(h func() hash.Hash, key []byte) hash.Hash { 65 hm := new(hmac) 66 hm.outer = h() 67 hm.inner = h() 68 hm.size = hm.inner.Size() 69 hm.blocksize = hm.inner.BlockSize() 70 hm.tmp = make([]byte, hm.blocksize+hm.size) 71 if len(key) > hm.blocksize { 72 // If key is too big, hash it. 73 hm.outer.Write(key) 74 key = hm.outer.Sum(nil) 75 } 76 hm.key = make([]byte, len(key)) 77 copy(hm.key, key) 78 hm.Reset() 79 return hm 80 }