Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions crypto/auth/crypto_auth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Package auth contains the libsodium bindings for secret-key authentication.
package auth

// #cgo pkg-config: libsodium
// #include <stdlib.h>
// #include <sodium.h>
import "C"
import "github.com/GoKillers/libsodium-go/support"

func init() {
C.sodium_init()
}

// Sizes of authentication tag and key, and the name of the used primitive.
const (
Bytes int = C.crypto_auth_BYTES
KeyBytes int = C.crypto_auth_KEYBYTES
Primitive string = C.crypto_auth_PRIMITIVE
)

// New returns the authentication tag for input data and a key.
func New(in []byte, key *[KeyBytes]byte) *[Bytes]byte {
support.NilPanic(key == nil, "key")

out := new([Bytes]byte)

C.crypto_auth(
(*C.uchar)(&out[0]),
(*C.uchar)(support.BytePointer(in)),
(C.ulonglong)(len(in)),
(*C.uchar)(&key[0]))

return out
}

// CheckMAC if the authentication tag is valid for input data and a key.
func CheckMAC(in []byte, h *[Bytes]byte, key *[KeyBytes]byte) (err error) {
support.NilPanic(h == nil, "hmac")
support.NilPanic(key == nil, "key")

exit := C.crypto_auth_verify(
(*C.uchar)(&h[0]),
(*C.uchar)(support.BytePointer(in)),
(C.ulonglong)(len(in)),
(*C.uchar)(&key[0]))

if exit != 0 {
err = support.VerificationError{}
}

return
}

// GenerateKey generates a secret key.
func GenerateKey() *[KeyBytes]byte {
k := new([Bytes]byte)
C.crypto_auth_keygen((*C.uchar)(&k[0]))
return k
}
62 changes: 62 additions & 0 deletions crypto/auth/crypto_auth_hmacsha256.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package auth

// #cgo pkg-config: libsodium
// #include <stdlib.h>
// #include <sodium.h>
import "C"
import (
"github.com/GoKillers/libsodium-go/crypto/auth/hmacsha256"
"github.com/GoKillers/libsodium-go/support"
"hash"
)

// hmacsha256state represents the cryptographic State for HMAC-SHA256.
type hmacsha256state C.crypto_auth_hmacsha256_state

// Write adds data to the hash state.
func (s *hmacsha256state) Write(in []byte) (n int, err error) {
C.crypto_auth_hmacsha256_update(
(*C.crypto_auth_hmacsha256_state)(s),
(*C.uchar)(support.BytePointer(in)),
C.ulonglong(len(in)))

return len(in), nil
}

// Sum returns the authentication tag appended to the data in b.
func (s *hmacsha256state) Sum(b []byte) []byte {
out := make([]byte, hmacsha256.Bytes)

C.crypto_auth_hmacsha256_final(
(*C.crypto_auth_hmacsha256_state)(s),
(*C.uchar)(&out[0]))

return append(b, out...)
}

// Reset resets the Hash to its initial state.
func (s *hmacsha256state) Reset() {
panic("HMACSHA256 cannot be reset")
}

// Size returns the size of the authentication tag.
func (s *hmacsha256state) Size() int {
return hmacsha256.Bytes
}

// BlockSize returns the block size for HMAC-SHA256.
func (s *hmacsha256state) BlockSize() int {
return 2 * hmacsha256.Bytes
}

// NewHMACSHA256 returns a new HMAC-SHA256 hash using a key.
func NewHMACSHA256(key []byte) hash.Hash {
s := new(hmacsha256state)

C.crypto_auth_hmacsha256_init(
(*C.crypto_auth_hmacsha256_state)(s),
(*C.uchar)(support.BytePointer(key)),
C.size_t(len(key)))

return s
}
62 changes: 62 additions & 0 deletions crypto/auth/crypto_auth_hmacsha256_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package auth

import (
"bytes"
"github.com/GoKillers/libsodium-go/crypto/auth/hmacsha256"
"github.com/google/gofuzz"
"testing"
)

func TestHMACSHA256(t *testing.T) {
// Check properties of HMAC
h := NewHMACSHA256(nil)

if h.Size() != hmacsha256.Bytes {
t.Errorf("Incorrect size for hash: %#v", h)
}

if h.BlockSize() != 2*hmacsha256.Bytes {
t.Errorf("Incorrect size for hash: %#v", h)
}

// Fuzzing
f := fuzz.New()

// Run tests
for i := 0; i < testCount; i++ {
var m, sk []byte
var k [hmacsha256.KeyBytes]byte

// Fuzz the test inputs
f.Fuzz(&m)
f.Fuzz(&sk)
f.Fuzz(&k)

// Create a tag
h := hmacsha256.New(m, &k)

// CheckMAC the tag
if hmacsha256.CheckMAC(m, h, &k) != nil {
t.Errorf("Verification failed for: h: %x, m: %x, k: %x", h, m, k)
}

// Authenticate the same with the prepared functions
hmac := NewHMACSHA256(k[:])
hmac.Write(m)
sh := hmac.Sum(nil)

if !bytes.Equal(sh, h[:]) {
t.Errorf("Prepared verification failed for: h: %x, m: %x, k: %x", h, m, k)
}

// Authenticate with streaming functions and an arbitrary length key
hmac = NewHMACSHA256(sk)
hmac.Write(m)
sh = hmac.Sum(nil)

// CheckMAC the tag
if len(sh) != hmacsha256.Bytes {
t.Errorf("Prepared verification failed for: h: %x, m: %x, k: %x", h, m, k)
}
}
}
62 changes: 62 additions & 0 deletions crypto/auth/crypto_auth_hmacsha512.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package auth

// #cgo pkg-config: libsodium
// #include <stdlib.h>
// #include <sodium.h>
import "C"
import (
"github.com/GoKillers/libsodium-go/crypto/auth/hmacsha512"
"github.com/GoKillers/libsodium-go/support"
"hash"
)

// hmacsha512state represents the cryptographic State for HMAC-SHA512.
type hmacsha512state C.crypto_auth_hmacsha512_state

// Write adds data to the hash state.
func (s *hmacsha512state) Write(in []byte) (n int, err error) {
C.crypto_auth_hmacsha512_update(
(*C.crypto_auth_hmacsha512_state)(s),
(*C.uchar)(support.BytePointer(in)),
C.ulonglong(len(in)))

return len(in), nil
}

// Sum returns the authentication tag appended to the data in b.
func (s *hmacsha512state) Sum(b []byte) []byte {
out := make([]byte, hmacsha512.Bytes)

C.crypto_auth_hmacsha512_final(
(*C.crypto_auth_hmacsha512_state)(s),
(*C.uchar)(&out[0]))

return append(b, out...)
}

// Reset resets the Hash to its initial state.
func (s *hmacsha512state) Reset() {
panic("HMACSHA512 cannot be reset")
}

// Size returns the size of the authentication tag.
func (s *hmacsha512state) Size() int {
return hmacsha512.Bytes
}

// BlockSize returns the block size for HMAC-SHA512.
func (s *hmacsha512state) BlockSize() int {
return 2 * hmacsha512.Bytes
}

// NewHMACSHA512 returns a new HMAC-SHA512 hash using a key.
func NewHMACSHA512(key []byte) hash.Hash {
s := new(hmacsha512state)

C.crypto_auth_hmacsha512_init(
(*C.crypto_auth_hmacsha512_state)(s),
(*C.uchar)(support.BytePointer(key)),
C.size_t(len(key)))

return s
}
62 changes: 62 additions & 0 deletions crypto/auth/crypto_auth_hmacsha512256.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package auth

// #cgo pkg-config: libsodium
// #include <stdlib.h>
// #include <sodium.h>
import "C"
import (
"github.com/GoKillers/libsodium-go/crypto/auth/hmacsha512256"
"github.com/GoKillers/libsodium-go/support"
"hash"
)

// hmacsha512256state represents the cryptographic State for HMAC-SHA512256.
type hmacsha512256state C.crypto_auth_hmacsha512256_state

// Write adds data to the hash state.
func (s *hmacsha512256state) Write(in []byte) (n int, err error) {
C.crypto_auth_hmacsha512256_update(
(*C.crypto_auth_hmacsha512256_state)(s),
(*C.uchar)(support.BytePointer(in)),
C.ulonglong(len(in)))

return len(in), nil
}

// Sum returns the authentication tag appended to the data in b.
func (s *hmacsha512256state) Sum(b []byte) []byte {
out := make([]byte, hmacsha512256.Bytes)

C.crypto_auth_hmacsha512256_final(
(*C.crypto_auth_hmacsha512256_state)(s),
(*C.uchar)(&out[0]))

return append(b, out...)
}

// Reset resets the Hash to its initial state.
func (s *hmacsha512256state) Reset() {
panic("HMACSHA512256 cannot be reset")
}

// Size returns the size of the authentication tag.
func (s *hmacsha512256state) Size() int {
return hmacsha512256.Bytes
}

// BlockSize returns the block size for HMAC-SHA512256.
func (s *hmacsha512256state) BlockSize() int {
return 2 * hmacsha512256.Bytes
}

// NewHMACSHA512256 returns a new HMAC-SHA512256 hash using a key.
func NewHMACSHA512256(key []byte) hash.Hash {
s := new(hmacsha512256state)

C.crypto_auth_hmacsha512256_init(
(*C.crypto_auth_hmacsha512256_state)(s),
(*C.uchar)(support.BytePointer(key)),
C.size_t(len(key)))

return s
}
62 changes: 62 additions & 0 deletions crypto/auth/crypto_auth_hmacsha512256_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package auth

import (
"bytes"
"github.com/GoKillers/libsodium-go/crypto/auth/hmacsha512256"
"github.com/google/gofuzz"
"testing"
)

func TestHMACSHA512256(t *testing.T) {
// Check properties of HMAC
h := NewHMACSHA512256(nil)

if h.Size() != hmacsha512256.Bytes {
t.Errorf("Incorrect size for hash: %#v", h)
}

if h.BlockSize() != 2*hmacsha512256.Bytes {
t.Errorf("Incorrect size for hash: %#v", h)
}

// Fuzzing
f := fuzz.New()

// Run tests
for i := 0; i < testCount; i++ {
var m, sk []byte
var k [hmacsha512256.KeyBytes]byte

// Fuzz the test inputs
f.Fuzz(&m)
f.Fuzz(&sk)
f.Fuzz(&k)

// Create a tag
h := hmacsha512256.New(m, &k)

// CheckMAC the tag
if hmacsha512256.CheckMAC(m, h, &k) != nil {
t.Errorf("Verification failed for: h: %x, m: %x, k: %x", h, m, k)
}

// Authenticate the same with the prepared functions
hmac := NewHMACSHA512256(k[:])
hmac.Write(m)
sh := hmac.Sum(nil)

if !bytes.Equal(sh, h[:]) {
t.Errorf("Prepared verification failed for: h: %x, m: %x, k: %x", h, m, k)
}

// Authenticate with streaming functions and an arbitrary length key
hmac = NewHMACSHA512256(sk)
hmac.Write(m)
sh = hmac.Sum(nil)

// CheckMAC the tag
if len(sh) != hmacsha512256.Bytes {
t.Errorf("Prepared verification failed for: h: %x, m: %x, k: %x", h, m, k)
}
}
}
Loading