/
sha.go
86 lines (71 loc) · 1.65 KB
/
sha.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
package sha
/*
#include <strings.h>
*/
import "C"
import (
"crypto/sha256"
"crypto/sha512"
"hash"
"sync"
"unsafe"
)
var store sync.Map
//export SHA256_Init
//noinspection GoSnakeCaseUsage
func SHA256_Init(c unsafe.Pointer) C.int {
return initialize(c, sha256.New)
}
//export SHA256_Update
//noinspection GoSnakeCaseUsage
func SHA256_Update(c, data unsafe.Pointer, len C.size_t) C.int {
return update(c, data, len)
}
//export SHA256_Final
//noinspection GoSnakeCaseUsage
func SHA256_Final(md *C.uchar, c unsafe.Pointer) C.int {
return final(md, c)
}
//export SHA512_Init
//noinspection GoSnakeCaseUsage
func SHA512_Init(c unsafe.Pointer) C.int {
return initialize(c, sha512.New)
}
//export SHA512_Update
//noinspection GoSnakeCaseUsage
func SHA512_Update(c, data unsafe.Pointer, len C.size_t) C.int {
return update(c, data, len)
}
//export SHA512_Final
//noinspection GoSnakeCaseUsage
func SHA512_Final(md *C.uchar, c unsafe.Pointer) C.int {
return final(md, c)
}
func initialize(c unsafe.Pointer, create func() hash.Hash) C.int {
store.Store(c, create())
return 1
}
func update(c, data unsafe.Pointer, len C.size_t) C.int {
hasher, ok := store.Load(c)
if !ok {
return 0
}
hasher.(hash.Hash).Write(slice(data, int(len)))
return 1
}
func final(md *C.uchar, c unsafe.Pointer) C.int {
obj, ok := store.Load(c)
if !ok {
return 0
}
store.Delete(c)
hasher := obj.(hash.Hash)
hasher.Sum(sliceWithCap(unsafe.Pointer(md), 0, hasher.Size()))
return 1
}
func slice(pointer unsafe.Pointer, len int) []byte {
return sliceWithCap(pointer, len, len)
}
func sliceWithCap(pointer unsafe.Pointer, len, cap int) []byte {
return (*[1<<30]byte)(pointer)[:len:cap]
}