-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathhash.go
124 lines (110 loc) · 2.91 KB
/
hash.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package hydrogen
// #cgo LDFLAGS: -lhydrogen
// #include <stdlib.h>
// #include <hydrogen.h>
import "C"
import (
"unsafe"
)
const (
HashBytes int = C.hydro_hash_BYTES
HashBytesMax int = C.hydro_hash_BYTES_MAX
HashBytesMin int = C.hydro_hash_BYTES_MIN
HashContextBytes int = C.hydro_hash_CONTEXTBYTES
HashKeyBytes int = C.hydro_hash_KEYBYTES
)
// Prototype:
// void hydro_hash_keygen(uint8_t *key);
func HashKeygen() []byte {
out := make([]byte, HashKeyBytes)
C.hydro_hash_keygen((*C.uint8_t)(&out[0]))
return out
}
// Prototype:
// int hydro_hash_hash(uint8_t *out, size_t out_len, const void *in_, size_t in_len, const char ctx[hydro_hash_CONTEXTBYTES], const uint8_t *key);
func HashHash(out_len int, data []byte, ctx string, key []byte) ([]byte, int) {
CheckCtx(ctx, HashContextBytes)
CheckIntInRange(out_len, HashBytesMin, HashBytesMax, "hash out_len")
data_len := len(data)
cCtx := []byte(ctx)
out := make([]byte, out_len)
var exit int
if key != nil {
exit = int(C.hydro_hash_hash(
(*C.uint8_t)(&out[0]),
(C.size_t)(out_len),
unsafe.Pointer(&data[0]),
(C.size_t)(data_len),
(*C.char)(unsafe.Pointer(&cCtx[0])),
(*C.uint8_t)(&key[0])))
} else {
exit = int(C.hydro_hash_hash(
(*C.uint8_t)(&out[0]),
(C.size_t)(out_len),
unsafe.Pointer(&data[0]),
(C.size_t)(data_len),
(*C.char)(unsafe.Pointer(&cCtx[0])),
nil))
}
return out, exit
}
/* --------------------------------- Multi ---------------------------------- */
//
// TODO: detached methods
//
type HashState struct {
inner *C.hydro_hash_state
}
type HashHelper struct {
state HashState
context string
}
// Create a new HashState object. Does not initialize it.
func NewHashState() HashState {
buf := new(C.hydro_hash_state)
out := HashState{buf}
return out
}
// Prototype:
// int hydro_hash_init(hydro_hash_state *state, const char ctx[hydro_hash_CONTEXTBYTES], const uint8_t key[hydro_hash_KEYBYTES]);
func NewHashHelper(ctx string, key []byte) HashHelper {
CheckCtx(ctx, HashContextBytes)
cCtx := []byte(ctx)
st := NewHashState()
if key != nil {
CheckSize(key, HashKeyBytes, "hashkey")
C.hydro_hash_init(
st.inner,
(*C.char)(unsafe.Pointer(&cCtx[0])),
(*C.uint8_t)(&key[0]))
} else {
C.hydro_hash_init(
st.inner,
(*C.char)(unsafe.Pointer(&cCtx[0])),
nil)
}
return HashHelper{
state: st,
context: ctx,
}
}
// Prototype:
// int hydro_hash_update(hydro_hash_state *state, const void *in_, size_t in_len);
func (h *HashHelper) Update(m []byte) {
mlen := len(m)
C.hydro_hash_update(
h.state.inner,
unsafe.Pointer(&m[0]),
(C.size_t)(mlen))
}
// Prototype:
// int hydro_hash_final(hydro_hash_state *state, uint8_t *out, size_t out_len);
func (h *HashHelper) Final(out_len int) []byte {
CheckIntInRange(out_len, HashBytesMin, HashBytesMax, "hash out_len")
out := make([]byte, out_len)
C.hydro_hash_final(
h.state.inner,
(*C.uint8_t)(&out[0]),
(C.size_t)(out_len))
return out
}