forked from openziti/secretstream
-
Notifications
You must be signed in to change notification settings - Fork 0
/
sodium.go
92 lines (71 loc) · 2.32 KB
/
sodium.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
// +build compat_test
package secretstream
// #cgo LDFLAGS: -lsodium
// #include <sodium.h>
// #include <sodium/crypto_secretstream_xchacha20poly1305.h>
import "C"
import (
"errors"
)
type sodiumStream struct {
state C.crypto_secretstream_xchacha20poly1305_state
}
func NewSodiumSendStream(key []byte) (Encryptor, []byte, error) {
res := &sodiumStream{}
ckey := C.CBytes(key)
defer C.free(ckey)
header := C.malloc(C.crypto_secretstream_xchacha20poly1305_HEADERBYTES)
defer C.free(header)
rc := C.crypto_secretstream_xchacha20poly1305_init_push(&res.state, (*C.uchar)(header), (*C.uchar)(ckey))
if rc != 0 {
return nil, nil, cryptoFailure
}
// fmt.Printf("sodium: %+v\n", res.state)
return res, C.GoBytes(header, C.crypto_secretstream_xchacha20poly1305_HEADERBYTES), nil
}
func NewSodiumRecvStream(key []byte, header []byte) (Decryptor, error) {
res := &sodiumStream{}
chdr := C.CBytes(header)
defer C.free(chdr)
ckey := C.CBytes(key)
defer C.free(ckey)
rc := C.crypto_secretstream_xchacha20poly1305_init_pull(&res.state, (*C.uchar)(chdr), (*C.uchar)(ckey))
if rc != 0 {
return nil, cryptoFailure
}
// fmt.Printf("receiver = %+v", res.state)
return res, nil
}
func (s *sodiumStream) Push(plaintext []byte, tag byte) ([]byte, error) {
pt := C.CBytes(plaintext)
defer C.free(pt)
cipher_len := len(plaintext) + C.crypto_secretstream_xchacha20poly1305_ABYTES
ct := C.malloc((C.size_t)(cipher_len))
defer C.free(ct)
cipher_len_ull := C.ulonglong(cipher_len)
pt_len_ull := C.ulonglong(len(plaintext))
if C.crypto_secretstream_xchacha20poly1305_push(&s.state,
(*C.uchar)(ct), &cipher_len_ull,
(*C.uchar)(pt), pt_len_ull,
nil, 0,
C.uchar(tag)) != 0 {
return nil, errors.New("sodium error")
}
return C.GoBytes(ct, C.int(cipher_len)), nil
}
func (s *sodiumStream) Pull(ciphertext []byte) ([]byte, byte, error) {
ctc := C.CBytes(ciphertext)
defer C.free(ctc)
mlen := C.ulong(len(ciphertext) - C.crypto_secretstream_xchacha20poly1305_ABYTES)
mlen_ull := C.ulonglong(mlen)
msg := C.malloc((C.size_t)(mlen))
var tag C.uchar
if C.crypto_secretstream_xchacha20poly1305_pull(&s.state,
(*C.uchar)(msg), &mlen_ull, &tag,
(*C.uchar)(ctc), C.ulonglong(len(ciphertext)),
nil, 0) != 0 {
return nil, 0, cryptoFailure
}
// fmt.Printf("receiver = %+v", s.state)
return C.GoBytes(msg, C.int(mlen)), byte(tag), nil
}