umac

package module
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 23, 2024 License: BSD-3-Clause Imports: 9 Imported by: 1

README

UMAC in Go

Go Reference

This is a Go implementation of the UMAC message authentication code used in OpenSSH.

As described in the OpenSSH UMAC draft and RFC4418, UMAC is a (kinda) fast message authentication code, that is widely used in OpenSSH clients and servers.

Benchmark

test on AWS EC2 t3.nano with full credits (actually a lightsail instance, but they are basically the same)

goos: linux
goarch: amd64
pkg: github.com/fakeboboliu/umac
cpu: Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz
BenchmarkHMACSHA256_1K
BenchmarkHMACSHA256_1K-2   	 1428729	      3614 ns/op	 283.34 MB/s
BenchmarkHMACSHA256_32
BenchmarkHMACSHA256_32-2   	10101997	       670.2 ns/op	  47.75 MB/s
BenchmarkHMACMD5_1K
BenchmarkHMACMD5_1K-2      	 2584860	      2161 ns/op	 473.94 MB/s
BenchmarkHMACMD5_32
BenchmarkHMACMD5_32-2      	14015890	       415.3 ns/op	  77.05 MB/s
BenchmarkUMAC64_1K
BenchmarkUMAC64_1K-2      	14754679	       379.2 ns/op	2700.67 MB/s
BenchmarkUMAC64_32
BenchmarkUMAC64_32-2       	42769585	       152.1 ns/op	 210.40 MB/s
BenchmarkUMAC128_1K
BenchmarkUMAC128_1K-2      	10143998	       595.2 ns/op	1720.37 MB/s
BenchmarkUMAC128_32
BenchmarkUMAC128_32-2      	36241742	       172.0 ns/op	 186.00 MB/s

The vCPU has no SHA extensions, so the performance of HMAC-SHA256 is not as good as other modern platforms.

For a CPU with SHA extensions, the performance of HMAC-SHA256 will be better than HMAC-MD5, while still way worse than UMAC.

HMAC-SHA1 will be nearly the same as HMAC-SHA256, so I didn't test it.

Usage

Unlike HMAC, UMAC has a nonce needed per message, which is a 64-bit integer.

To fit hash.Hash interface, I placed the nonce set at Sum([]byte), you should pass a buffer that contains nonce, and it will be reused to store the result.

package main

import (
    "fmt"
	
    "github.com/fakeboboliu/umac"
)

func main() {
    key := make([]byte, 16)
    mac := umac.New8(key)
    mac.Write([]byte("hello"))
	
    buf := make([]byte, 8)
    // -- set the nonce here --
	
    result := mac.Sum(buf)
    fmt.Printf("%x\n", result)
}

How to use in ssh

A patch of golang.org/x/crypto/ssh is needed, I'll provide a patch version later.

Why

I found only those secure MACs are included in golang.org/x/crypto/ssh, which obviously takes users' right to be insecure away.

I wrote this package to provide a way to users enjoy the freedom of taking their own fate becoming less secure.

There also be some TINY benchmark benefits, but freedom is the main reason.

Several naive optimizations are applied, but not as good as the original UMAC implementation.

Thanks

Documentation

Index

Constants

View Source
const (
	// STREAMS is Number of times hash is applied, 64 and 128 bits
	STREAMS8        = 2
	STREAMS16       = 4
	L1_KEY_LEN      = 1024 // Internal key bytes
	L1_KEY_SHIFT    = 16   // Toeplitz key shift between streams
	L1_PAD_BOUNDARY = 32   // pad message to boundary multiple
	HASH_BUF_BYTES  = 64   // nh_aux_hb buffer multiple
)

Variables

This section is empty.

Functions

func New16

func New16(key []byte) hash.Hash

func New8

func New8(key []byte) hash.Hash

Types

type UMAC16

type UMAC16 struct {
	// contains filtered or unexported fields
}

UMAC16 is the 16-byte output version of UMAC. also known as UMAC-128

func (*UMAC16) BlockSize

func (u *UMAC16) BlockSize() int

func (*UMAC16) Reset

func (u *UMAC16) Reset()

func (*UMAC16) Size

func (u *UMAC16) Size() int

func (*UMAC16) Sum

func (u *UMAC16) Sum(b []byte) []byte

Sum uses the argument as nonce, which should be 8 bytes long. WARNING: it's not standard hash.Hash behavior.

func (*UMAC16) Write

func (u *UMAC16) Write(p []byte) (n int, err error)

type UMAC8

type UMAC8 struct {
	// contains filtered or unexported fields
}

UMAC8 is the 8-byte output version of UMAC. also known as UMAC-64

func (*UMAC8) BlockSize

func (u *UMAC8) BlockSize() int

func (*UMAC8) Reset

func (u *UMAC8) Reset()

func (*UMAC8) Size

func (u *UMAC8) Size() int

func (*UMAC8) Sum

func (u *UMAC8) Sum(b []byte) []byte

Sum uses the argument as nonce, which should be 8 bytes long. WARNING: it's not standard hash.Hash behavior.

func (*UMAC8) Write

func (u *UMAC8) Write(p []byte) (n int, err error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL