src/pkg/crypto/hmac/hmac.go - The Go Programming Language

Golang

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	}