--- /dev/null
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+# DO NOT EDIT. Automatically generated by gobuild.
+# gobuild -m >Makefile
+
+D=/crypto/
+
+O_arm=5
+O_amd64=6
+O_386=8
+OS=568vq
+
+O=$(O_$(GOARCH))
+GC=$(O)g -I_obj
+CC=$(O)c -FVw
+AS=$(O)a
+AR=6ar
+
+default: packages
+
+clean:
+ rm -rf *.[$(OS)] *.a [$(OS)].out _obj
+
+test: packages
+ gotest
+
+coverage: packages
+ gotest
+ 6cov -g `pwd` | grep -v '_test\.go:'
+
+%.$O: %.go
+ $(GC) $*.go
+
+%.$O: %.c
+ $(CC) $*.c
+
+%.$O: %.s
+ $(AS) $*.s
+
+O1=\
+ hmac.$O\
+
+
+phases: a1
+_obj$D/hmac.a: phases
+
+a1: $(O1)
+ $(AR) grc _obj$D/hmac.a hmac.$O
+ rm -f $(O1)
+
+
+newpkg: clean
+ mkdir -p _obj$D
+ $(AR) grc _obj$D/hmac.a
+
+$(O1): newpkg
+$(O2): a1
+
+nuke: clean
+ rm -f $(GOROOT)/pkg$D/hmac.a
+
+packages: _obj$D/hmac.a
+
+install: packages
+ test -d $(GOROOT)/pkg && mkdir -p $(GOROOT)/pkg$D
+ cp _obj$D/hmac.a $(GOROOT)/pkg$D/hmac.a
--- /dev/null
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// TODO(rsc): comments
+
+package hmac
+
+import (
+ "hash";
+ "os";
+)
+
+// k0 = key
+// ipad = 0x36 byte repeated to key len
+// opad = 0x5c byte repeated to key len
+// hmac =
+// H((k0 ^ opad) || H((k0 ^ ipad) || text))
+
+const (
+ padSize = 64;
+)
+
+type hmac struct {
+ size int;
+ key []byte;
+ tmp []byte;
+ inner hash.Hash;
+}
+
+func (h *hmac) tmpPad(xor byte) {
+ for i, k := range h.key {
+ h.tmp[i] = xor ^ k;
+ }
+ for i := len(h.key); i < padSize; i++ {
+ h.tmp[i] = xor;
+ }
+}
+
+func (h *hmac) init() {
+ h.tmpPad(0x36);
+ h.inner.Write(h.tmp[0:padSize]);
+}
+
+func (h *hmac) Sum() []byte {
+ h.tmpPad(0x5c);
+ sum := h.inner.Sum();
+ for i, b := range sum {
+ h.tmp[padSize + i] = b;
+ }
+ h.inner.Reset();
+ h.inner.Write(h.tmp);
+ return h.inner.Sum();
+}
+
+func (h *hmac) Write(p []byte) (n int, err os.Error) {
+ return h.inner.Write(p);
+}
+
+func (h *hmac) Size() int {
+ return h.size;
+}
+
+func (h *hmac) Reset() {
+ h.inner.Reset();
+ h.init();
+}
+
+func HMAC(h hash.Hash, key []byte) hash.Hash {
+ hm := new(hmac);
+ hm.inner = h;
+ hm.size = h.Size();
+ hm.key = make([]byte, len(key));
+ for i, k := range key {
+ hm.key[i] = k;
+ }
+ hm.tmp = make([]byte, padSize + hm.size);
+ hm.init();
+ return hm;
+}
--- /dev/null
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package hmac
+
+// TODO(rsc): better test
+
+import (
+ "crypto/hmac";
+ "crypto/md5";
+ "io";
+ "fmt";
+ "testing";
+)
+
+func TestHMAC_MD5(t *testing.T) {
+ // presotto's test
+ inner := md5.New();
+ h := HMAC(inner, io.StringBytes("Jefe"));
+ io.WriteString(h, "what do ya want for nothing?");
+ s := fmt.Sprintf("%x", h.Sum());
+ answer := "750c783e6ab0b503eaa86e310a5db738";
+ if s != answer {
+ t.Error("have", s, "\nwant", answer);
+ }
+}