hmac computation

nosocat
Jean-Louis Huynen 2019-01-10 16:33:39 +01:00
parent 6457bd2089
commit d6e85dc6db
1 changed files with 119 additions and 82 deletions

View File

@ -2,6 +2,8 @@ package main
import ( import (
"bytes" "bytes"
"crypto/hmac"
"crypto/sha256"
"encoding/binary" "encoding/binary"
"flag" "flag"
"fmt" "fmt"
@ -37,25 +39,26 @@ type (
// A d4 writer implements the io.Writer Interface by implementing Write() and Close() // A d4 writer implements the io.Writer Interface by implementing Write() and Close()
// it accepts an io.Writer as sink // it accepts an io.Writer as sink
d4Writer struct { d4Writer struct {
w io.Writer w io.Writer
key []byte
d4header []byte
payload []byte
} }
d4S struct { d4S struct {
src io.Reader src io.Reader
dst io.Writer dst d4Writer
confdir string confdir string
d4error uint8 d4error uint8
errnoCopy uint8 errnoCopy uint8
debug bool
conf d4params conf d4params
//header d4Header
d4header []byte
payload []byte
} }
d4params struct { d4params struct {
uuid []byte uuid []byte
snaplen uint32 snaplen uint32
key string key []byte
version uint8 version uint8
source string source string
destination string destination string
@ -75,10 +78,6 @@ var (
debug = flag.Bool("v", false, "Set to True, true, TRUE, 1, or t to enable verbose output on stdout") debug = flag.Bool("v", false, "Set to True, true, TRUE, 1, or t to enable verbose output on stdout")
) )
func newD4Writer(writer io.Writer) *d4Writer {
return &d4Writer{w: writer}
}
func main() { func main() {
var d4 d4S var d4 d4S
@ -113,17 +112,18 @@ func main() {
flag.Usage() flag.Usage()
os.Exit(1) os.Exit(1)
} }
d4.confdir = *confdir
// Output logging before closing if debug is enabled // Output logging before closing if debug is enabled
if *debug == true { if *debug == true {
d4.debug = true
defer fmt.Print(&buf) defer fmt.Print(&buf)
} }
d4.confdir = *confdir
//var d4 = d4loadConfig(confdir)
if d4loadConfig(d4p) == true { if d4loadConfig(d4p) == true {
initHeader(d4p) if d4.dst.initHeader(d4p) == true {
//d4transfer(d4p) d4transfer(d4p)
}
} }
} }
@ -156,7 +156,7 @@ func d4loadConfig(d4 *d4S) bool {
// parse snaplen to uint32 // parse snaplen to uint32
tmp, _ := strconv.ParseUint(string(readConfFile(d4, "snaplen")), 10, 32) tmp, _ := strconv.ParseUint(string(readConfFile(d4, "snaplen")), 10, 32)
(*d4).conf.snaplen = uint32(tmp) (*d4).conf.snaplen = uint32(tmp)
(*d4).conf.key = string(readConfFile(d4, "key")) (*d4).conf.key = readConfFile(d4, "key")
// parse version to uint8 // parse version to uint8
tmp, _ = strconv.ParseUint(string(readConfFile(d4, "version")), 10, 8) tmp, _ = strconv.ParseUint(string(readConfFile(d4, "version")), 10, 8)
(*d4).conf.version = uint8(tmp) (*d4).conf.version = uint8(tmp)
@ -166,7 +166,11 @@ func d4loadConfig(d4 *d4S) bool {
return d4checkConfig(d4) return d4checkConfig(d4)
} }
// QUICK IMPLEM, REVISE func newD4Writer(writer io.Writer, key []byte) d4Writer {
return d4Writer{w: writer, key: key}
}
// TODO QUICK IMPLEM, REVISE
func d4checkConfig(d4 *d4S) bool { func d4checkConfig(d4 *d4S) bool {
//TODO implement other destination file, fifo unix_socket ... //TODO implement other destination file, fifo unix_socket ...
@ -180,10 +184,10 @@ func d4checkConfig(d4 *d4S) bool {
switch (*d4).conf.destination { switch (*d4).conf.destination {
case "stdout": case "stdout":
(*d4).dst = newD4Writer(os.Stdout) (*d4).dst = newD4Writer(os.Stdout, (*d4).conf.key)
case "file": case "file":
f, _ := os.Create("test.txt") f, _ := os.Create("test.txt")
(*d4).dst = newD4Writer(f) (*d4).dst = newD4Writer(f, (*d4).conf.key)
} }
if len((*d4).conf.uuid) == 0 { if len((*d4).conf.uuid) == 0 {
@ -210,30 +214,108 @@ func generateUUIDv4() []byte {
return []byte(uuid[:]) return []byte(uuid[:])
} }
//TODO turn this ugly mess into a Framer func d4transfer(d4 *d4S) {
func initHeader(d4 *d4S) bool { src := (*d4).src
// zero out the header dst := (*d4).dst
(*d4).d4header = make([]byte, HDR_SIZE) buf := make([]byte, (*d4).conf.snaplen)
// put version a type into the header varybuf := make([]byte, 0)
(*d4).d4header[0] = (*d4).conf.version
(*d4).d4header[1] = (*d4).conf.ttype for {
// put uuid into the header // Take a slice of snaplen
ps := 2 nread, err := src.Read(buf)
pe := ps + UUID_SIZE if err != nil {
copy((*d4).d4header[ps:pe], (*d4).conf.uuid) // if EOF, we just wait for more data
// timestamp if err != io.EOF {
log.Fatal(err)
} else if (*d4).debug {
log.Fatal(err)
}
}
// And push it into the d4writer -> sink chain
switch {
case uint32(nread) == (*d4).conf.snaplen:
dst.Write(buf)
case nread > 0 && uint32(nread) < (*d4).conf.snaplen:
varybuf = append(buf[:nread])
dst.Write(varybuf)
}
}
}
func (d4w *d4Writer) Write(bs []byte) (int, error) {
d4w.updateHeader(bs)
d4w.payload = bs
d4w.updateHMAC()
// Eventually write in the sink
d4w.w.Write(append(d4w.d4header, d4w.payload...))
return len(bs), nil
}
// TODO write go idiomatic err return values
func (d4w *d4Writer) updateHeader(bs []byte) bool {
// zero out moving parts
copy(d4w.d4header[18:], make([]byte, 44))
timeUnix := time.Now().UnixNano() timeUnix := time.Now().UnixNano()
ps = pe ps := 18
pe = ps + TIMESTAMP_SIZE pe := ps + TIMESTAMP_SIZE
binary.LittleEndian.PutUint64((*d4).d4header[ps:pe], uint64(timeUnix)) binary.LittleEndian.PutUint64(d4w.d4header[ps:pe], uint64(timeUnix))
// hmac is set to zero during hmac operations, so leave it alone // hmac is set to zero during hmac operations, so leave it alone
// still, we move the pointers // still, we move the pointers
ps = pe ps = pe
pe = ps + HMAC_SIZE pe = ps + HMAC_SIZE
ps = pe ps = pe
pe = ps + 4 pe = ps + 4
// TODO put nread size instead of snaplen // Set payload size
binary.LittleEndian.PutUint32((*d4).d4header[ps:pe], (*d4).conf.snaplen) binary.LittleEndian.PutUint32(d4w.d4header[ps:pe], uint32(len(bs)))
return true
}
func (d4w *d4Writer) updateHMAC() bool {
h := hmac.New(sha256.New, d4w.key)
// version
h.Write(d4w.d4header[0:1])
// type
h.Write(d4w.d4header[1:2])
// uuid
h.Write(d4w.d4header[2:18])
// timestamp
h.Write(d4w.d4header[18:26])
// hmac (0)
h.Write(d4w.d4header[26:58])
// size
h.Write(d4w.d4header[58:])
// payload
h.Write(d4w.payload)
// final hmac
copy(d4w.d4header[26:58], h.Sum(nil))
return true
}
func (d4w *d4Writer) initHeader(d4 *d4S) bool {
// zero out the header
d4w.d4header = make([]byte, HDR_SIZE)
// put version a type into the header
d4w.d4header[0] = (*d4).conf.version
d4w.d4header[1] = (*d4).conf.ttype
// put uuid into the header
ps := 2
pe := ps + UUID_SIZE
copy(d4w.d4header[ps:pe], (*d4).conf.uuid)
// timestamp
timeUnix := time.Now().UnixNano()
ps = pe
pe = ps + TIMESTAMP_SIZE
binary.LittleEndian.PutUint64(d4w.d4header[ps:pe], uint64(timeUnix))
// hmac is set to zero during hmac operations, so leave it alone
// still, we move the pointers
ps = pe
pe = ps + HMAC_SIZE
ps = pe
pe = ps + 4
// init size of payload at 0
binary.LittleEndian.PutUint32(d4w.d4header[ps:pe], uint32(0))
// LittleEndian // LittleEndian
// toto := append(make([]byte, 0), byte((*d4).conf.snaplen), byte((*d4).conf.snaplen>>8), byte((*d4).conf.snaplen>>16), byte((*d4).conf.snaplen>>24)) // toto := append(make([]byte, 0), byte((*d4).conf.snaplen), byte((*d4).conf.snaplen>>8), byte((*d4).conf.snaplen>>16), byte((*d4).conf.snaplen>>24))
@ -242,53 +324,8 @@ func initHeader(d4 *d4S) bool {
// tmpi := binary.BigEndian.Uint32(toto) // tmpi := binary.BigEndian.Uint32(toto)
// tmpt := binary.LittleEndian.Uint32(others) // tmpt := binary.LittleEndian.Uint32(others)
// fmt.Println(tmpi) // fmt.Println(tmpi)
fmt.Println((*d4).d4header) infof(fmt.Sprintf("Initialized a %d bytes header:\n", len(d4w.d4header)))
infof(fmt.Sprintf("%b\n", d4w.d4header))
return true return true
} }
func d4transfer(d4 *d4S) {
src := (*d4).src
dst := (*d4).dst
buf := make([]byte, (*d4).conf.snaplen)
//for {
//n, _ := src.Read(buf)
_, _ = src.Read(buf)
dst.Write(buf)
// if n > 0 {
// update the header
// timestamp
/* h := hmac.New(sha256.New, []byte((*d4).conf.key))
h.Write((*d4).header.version)
h.Write((*d4).header.ttype)
h.Write((*d4).header.uuid)
h.Write((*d4).header.timestamp)
h.Write((*d4).header.hhmac)
h.Write((*d4).header.size)
h.Write([]byte(buf))
*/ //Add it to the header
// fmt.Println(base64.StdEncoding.EncodeToString(h.Sum(nil)))
// Write the packet in the sink
//}
//fmt.Println(n)
//fmt.Println(string(buf))
//}
//io.Copy((*d4).dst, (*d4).src)
}
func (d4w *d4Writer) Write(bs []byte) (int, error) {
d4w.w.Write(bs)
return len(bs), nil
}
func (d4w *d4Writer) Close() error {
// nothing ATM
return nil
}