Skip to content

Commit

Permalink
HMAC functions
Browse files Browse the repository at this point in the history
Resolves spacemonkeygo#35

Author:    Scott Kidder <[email protected]>
Date:      Fri May 22 10:41:35 2015 -0700

	First commit of HMAC functions
	Renamed HMAC Update function to Write
	Eliminate debug logging
	Compare the HMAC result
	Call Reset function in Final return statement
  • Loading branch information
Scott Kidder authored and Jeff Wendling committed Mar 3, 2017
1 parent 2980c58 commit 535a60b
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 5 deletions.
14 changes: 9 additions & 5 deletions cert.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,14 @@ func (c *Certificate) Sign(privKey PrivateKey, digest EVP_MD) error {
}

func (c *Certificate) insecureSign(privKey PrivateKey, digest EVP_MD) error {
var md *C.EVP_MD
var md *C.EVP_MD = getDigestFunction(digest)
if C.X509_sign(c.x, privKey.evpPKey(), md) <= 0 {
return errors.New("failed to sign certificate")
}
return nil
}

func getDigestFunction(digest EVP_MD) (md *C.EVP_MD) {
switch digest {
// please don't use these digest functions
case EVP_NULL:
Expand All @@ -297,10 +304,7 @@ func (c *Certificate) insecureSign(privKey PrivateKey, digest EVP_MD) error {
case EVP_SHA512:
md = C.EVP_sha512()
}
if C.X509_sign(c.x, privKey.evpPKey(), md) <= 0 {
return errors.New("failed to sign certificate")
}
return nil
return
}

// Add an extension to a certificate.
Expand Down
81 changes: 81 additions & 0 deletions hmac.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright (C) 2014 Space Monkey, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// +build cgo

package openssl

/*
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "openssl/evp.h"
#include "openssl/hmac.h"
*/
import "C"

import (
"runtime"
"unsafe"
)

type HMAC struct {
ctx C.HMAC_CTX
engine *Engine
md *C.EVP_MD
}

func NewHMAC(key []byte, digestAlgorithm EVP_MD) (*HMAC, error) {
return NewHMACWithEngine(key, digestAlgorithm, nil)
}

func NewHMACWithEngine(key []byte, digestAlgorithm EVP_MD, e *Engine) (*HMAC, error) {
var md *C.EVP_MD = getDigestFunction(digestAlgorithm)
hmac := &HMAC{engine: e, md: md}
C.HMAC_CTX_init(&hmac.ctx)
C.HMAC_Init_ex(&hmac.ctx,
unsafe.Pointer(&key[0]),
C.int(len(key)),
md,
nil)

runtime.SetFinalizer(hmac, func(hmac *HMAC) { hmac.Close() })
return hmac, nil
}

func (h *HMAC) Close() {
C.HMAC_CTX_cleanup(&h.ctx)
}

func (s *HMAC) Write(data []byte) (n int, err error) {
if len(data) == 0 {
return 0, nil
}
C.HMAC_Update(&s.ctx, (*C.uchar)(unsafe.Pointer(&data[0])), C.size_t(len(data)))
return len(data), nil
}

func (h *HMAC) Reset() error {
C.HMAC_Init_ex(&h.ctx, nil, 0, nil, nil)
return nil
}

func (h *HMAC) Final() (result []byte, err error) {
mdLength := C.EVP_MD_size(h.md)
result = make([]byte, mdLength)
C.HMAC_Final(&h.ctx, (*C.uchar)(unsafe.Pointer(&result[0])), (*C.uint)(unsafe.Pointer(&mdLength)))
return result, h.Reset()
}
60 changes: 60 additions & 0 deletions hmac_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright (C) 2014 Space Monkey, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// +build cgo

package openssl

import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"testing"
)

func TestSHA256HMAC(t *testing.T) {
key := []byte("d741787cc61851af045ccd37")
data := []byte("5912EEFD-59EC-43E3-ADB8-D5325AEC3271")
h, _ := NewHMAC(key, EVP_SHA256)
h.Write(data)

var err error
var actualHMACBytes []byte
if actualHMACBytes, err = h.Final(); err != nil {
t.Fatalf("Error while finalizing HMAC: %s", err)
}
actualString := hex.EncodeToString(actualHMACBytes)

// generate HMAC with built-in crypto lib
mac := hmac.New(sha256.New, key)
mac.Write(data)
expectedString := hex.EncodeToString(mac.Sum(nil))

if expectedString != actualString {
t.Errorf("HMAC was incorrect: expected=%s, actual=%s", expectedString, actualString)
}
}

func BenchmarkSHA256HMAC(b *testing.B) {
h, _ := NewHMAC([]byte("d741787cc61851af045ccd37"), EVP_SHA256)
b.ResetTimer()
for i := 0; i < b.N; i++ {
h.Write([]byte("5912EEFD-59EC-43E3-ADB8-D5325AEC3271"))

var err error
if _, err = h.Final(); err != nil {
b.Fatalf("Error while finalizing HMAC: %s", err)
}
}
}

0 comments on commit 535a60b

Please sign in to comment.