├── LICENSE
├── README.md
├── build.bat
├── build.sh
├── crypto
└── aead
│ ├── aes256gcm
│ ├── crypto_aead_aes256gcm.go
│ └── crypto_aead_aes256gcm_test.go
│ ├── chacha20poly1305
│ ├── crypto_aead_chacha20poly1305.go
│ └── crypto_aead_chacha20poly1305_test.go
│ ├── chacha20poly1305ietf
│ ├── crypto_aead_chacha20poly1305_ietf.go
│ └── crypto_aead_chacha20poly1305_ietf_test.go
│ ├── crypto_aead.go
│ ├── crypto_aead_aes256gcm.go
│ ├── crypto_aead_aes256gcm_test.go
│ └── xchacha20poly1305ietf
│ ├── crypto_aead_xchacha20poly1305_ietf.go
│ └── crypto_aead_xchacha20poly1305_ietf_test.go
├── cryptoaead
├── crypto_aead_aes256gcm.go
└── crypto_aead_aes256gcm_test.go
├── cryptoauth
├── crypto_auth.go
├── hmacsha256
│ └── authHMAC256Api.go
└── hmacsha512
│ ├── authHMAC512Api.go
│ └── cp
│ └── hmacHMACSHA512.go
├── cryptobox
├── crypto_box.go
├── crypto_box_easy.go
├── crypto_box_seal.go
└── crypto_box_seal_test.go
├── cryptogenerichash
└── crypto_generichash.go
├── cryptohash
└── crypto_hash.go
├── cryptokdf
└── crypto_kdf.go
├── cryptosecretbox
├── crypto_secretbox.go
└── crypto_secretbox_easy.go
├── cryptosign
└── crypto_sign.go
├── cryptostream
├── crypto_stream.go
├── crypto_stream_chacha20.go
├── crypto_stream_salsa20.go
├── crypto_stream_salsa2012.go
├── crypto_stream_salsa208.go
├── crypto_stream_xchacha20.go
└── crypto_stream_xsalsa20.go
├── randombytes
└── randombytes.go
├── scalarmult
└── crypto_scalarmult.go
├── sodium
├── core.go
├── runtime.go
├── utils.go
├── version.go
└── version_test.go
└── support
├── error.go
└── support.go
/LICENSE:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015
3 | * GoKillers
4 | *
5 | * Permission to use, copy, modify, and/or distribute this software for any
6 | * purpose with or without fee is hereby granted, provided that the above
7 | * copyright notice and this permission notice appear in all copies.
8 | *
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | */
17 |
18 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | !This code requires an independent audit check!
2 |
3 | libsodium-go
4 | ============
5 | A binding library made in Go for the popular portable cryptography library [Sodium](https://download.libsodium.org/doc/).
6 |
7 |
8 | Purpose
9 | -------
10 | The goal of this binding library is to make use of Sodium in a more Go friendly matter. And of course making it easier to make secure software.
11 |
12 | Team (as of now...)
13 | ----------------
14 |
15 | - Stephen Chavez (@redragonx)
16 | - Graham Smith (@neuegram)
17 |
18 |
19 | Contributors
20 | ------------
21 | Silkeh
22 |
23 | How to build
24 | ------------
25 | For linux, this should be easy since there's pkg-config support. Please make sure libsodium is installed on your system first.
26 |
27 | Pre-setup:
28 | 1. Please install Libsodium here https://download.libsodium.org/doc/installation/index.html
29 | 2. `sudo ldconfig`
30 | 3. `sudo apt-get install pkg-config`
31 |
32 | Install libsodium-go:
33 | 1. `go get -d github.com/GoKillers/libsodium-go`
34 | 2. `cd $GOPATH/src/github.com/GoKillers/libsodium-go`
35 | 3. `./build.sh`
36 |
37 | For Windows, this requires a little more work.
38 |
39 | 1. Download and install pkg-config for [win32](http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/) or [win64](http://ftp.gnome.org/pub/gnome/binaries/win64/dependencies/)
40 | 2. Add a system or user variable PKG_CONFIG_PATH pointing to a folder containing pkg-config files, including libsodium
41 | 3. `go get -d github.com/GoKillers/libsodium-go`
42 | 4. `cd %GOPATH%/src/github.com/GoKillers/libsodium-go`
43 | 5. `build.bat`
44 |
45 | License
46 | ---------
47 | Copyright 2015 - GoKillers
48 |
--------------------------------------------------------------------------------
/build.bat:
--------------------------------------------------------------------------------
1 | go build ./...
--------------------------------------------------------------------------------
/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | exec go build ./...
--------------------------------------------------------------------------------
/crypto/aead/aes256gcm/crypto_aead_aes256gcm.go:
--------------------------------------------------------------------------------
1 | // Package aes256gcm contains the libsodium bindings for AES256-GCM.
2 | package aes256gcm
3 |
4 | // #cgo pkg-config: libsodium
5 | // #include
6 | // #include
7 | import "C"
8 | import "github.com/GoKillers/libsodium-go/support"
9 |
10 | // Sodium should always be initialised
11 | func init() {
12 | C.sodium_init()
13 | }
14 |
15 | // Sizes of nonces, key and mac.
16 | const (
17 | KeyBytes int = C.crypto_aead_aes256gcm_KEYBYTES // Size of a secret key in bytes
18 | NSecBytes int = C.crypto_aead_aes256gcm_NSECBYTES // Size of a secret nonce in bytes
19 | NonceBytes int = C.crypto_aead_aes256gcm_NPUBBYTES // Size of a nonce in bytes
20 | ABytes int = C.crypto_aead_aes256gcm_ABYTES // Size of an authentication tag in bytes
21 | )
22 |
23 | // IsAvailable returns true if AES256 is available on the current CPU
24 | func IsAvailable() bool {
25 | return C.crypto_aead_aes256gcm_is_available() != 0
26 | }
27 |
28 | // GenerateKey generates a secret key
29 | func GenerateKey() *[KeyBytes]byte {
30 | k := new([KeyBytes]byte)
31 | C.crypto_aead_aes256gcm_keygen((*C.uchar)(&k[0]))
32 | return k
33 | }
34 |
35 | // Encrypt a message `m` with additional data `ad` using a nonce `npub` and a secret key `k`.
36 | // A ciphertext (including authentication tag) and encryption status are returned.
37 | func Encrypt(m, ad []byte, nonce *[NonceBytes]byte, k *[KeyBytes]byte) (c []byte) {
38 | support.NilPanic(k == nil, "secret key")
39 | support.NilPanic(nonce == nil, "nonce")
40 |
41 | c = make([]byte, len(m)+ABytes)
42 |
43 | C.crypto_aead_aes256gcm_encrypt(
44 | (*C.uchar)(support.BytePointer(c)),
45 | (*C.ulonglong)(nil),
46 | (*C.uchar)(support.BytePointer(m)),
47 | (C.ulonglong)(len(m)),
48 | (*C.uchar)(support.BytePointer(ad)),
49 | (C.ulonglong)(len(ad)),
50 | (*C.uchar)(nil),
51 | (*C.uchar)(&nonce[0]),
52 | (*C.uchar)(&k[0]))
53 |
54 | return
55 | }
56 |
57 | // Decrypt and verify a ciphertext `c` using additional data `ad`, nonce `npub` and secret key `k`.
58 | // Returns the decrypted message and verification status.
59 | func Decrypt(c, ad []byte, nonce *[NonceBytes]byte, k *[KeyBytes]byte) (m []byte, err error) {
60 | support.NilPanic(k == nil, "secret key")
61 | support.NilPanic(nonce == nil, "nonce")
62 | support.CheckSizeMin(c, ABytes, "ciphertext")
63 |
64 | m = make([]byte, len(c)-ABytes)
65 |
66 | exit := C.crypto_aead_aes256gcm_decrypt(
67 | (*C.uchar)(support.BytePointer(m)),
68 | (*C.ulonglong)(nil),
69 | (*C.uchar)(nil),
70 | (*C.uchar)(&c[0]),
71 | (C.ulonglong)(len(c)),
72 | (*C.uchar)(support.BytePointer(ad)),
73 | (C.ulonglong)(len(ad)),
74 | (*C.uchar)(&nonce[0]),
75 | (*C.uchar)(&k[0]))
76 |
77 | if exit != 0 {
78 | err = &support.VerificationError{}
79 | }
80 |
81 | return
82 | }
83 |
84 | // EncryptDetached encrypts a message `m` with additional data `ad` using
85 | // a nonce `npub` and a secret key `k`.
86 | // A ciphertext, authentication tag and encryption status are returned.
87 | func EncryptDetached(m, ad []byte, nonce *[NonceBytes]byte, k *[KeyBytes]byte) (c, mac []byte) {
88 | support.NilPanic(k == nil, "secret key")
89 | support.NilPanic(nonce == nil, "nonce")
90 |
91 | c = make([]byte, len(m))
92 | mac = make([]byte, ABytes)
93 |
94 | C.crypto_aead_aes256gcm_encrypt_detached(
95 | (*C.uchar)(support.BytePointer(c)),
96 | (*C.uchar)(&mac[0]),
97 | (*C.ulonglong)(nil),
98 | (*C.uchar)(support.BytePointer(m)),
99 | (C.ulonglong)(len(m)),
100 | (*C.uchar)(support.BytePointer(ad)),
101 | (C.ulonglong)(len(ad)),
102 | (*C.uchar)(nil),
103 | (*C.uchar)(&nonce[0]),
104 | (*C.uchar)(&k[0]))
105 |
106 | return
107 | }
108 |
109 | // DecryptDetached decrypts and verifies a ciphertext `c` with authentication tag `mac`
110 | // using additional data `ad`, nonce `npub` and secret key `k`.
111 | // Returns the decrypted message and verification status.
112 | func DecryptDetached(c, mac, ad []byte, nonce *[NonceBytes]byte, k *[KeyBytes]byte) (m []byte, err error) {
113 | support.NilPanic(k == nil, "secret key")
114 | support.NilPanic(nonce == nil, "nonce")
115 | support.CheckSize(mac, ABytes, "mac")
116 |
117 | m = make([]byte, len(c))
118 |
119 | exit := C.crypto_aead_aes256gcm_decrypt_detached(
120 | (*C.uchar)(support.BytePointer(m)),
121 | (*C.uchar)(nil),
122 | (*C.uchar)(support.BytePointer(c)),
123 | (C.ulonglong)(len(c)),
124 | (*C.uchar)(&mac[0]),
125 | (*C.uchar)(support.BytePointer(ad)),
126 | (C.ulonglong)(len(ad)),
127 | (*C.uchar)(&nonce[0]),
128 | (*C.uchar)(&k[0]))
129 |
130 | if exit != 0 {
131 | err = &support.VerificationError{}
132 | }
133 |
134 | return
135 | }
136 |
--------------------------------------------------------------------------------
/crypto/aead/aes256gcm/crypto_aead_aes256gcm_test.go:
--------------------------------------------------------------------------------
1 | package aes256gcm
2 |
3 | import (
4 | "bytes"
5 | "github.com/google/gofuzz"
6 | "testing"
7 | )
8 |
9 | var testCount = 100000
10 |
11 | type TestData struct {
12 | Message []byte
13 | Ad []byte
14 | Key [KeyBytes]byte
15 | Nonce [NonceBytes]byte
16 | }
17 |
18 | func Test(t *testing.T) {
19 | // Skip the test if unsupported on this platform
20 | if !IsAvailable() {
21 | t.Skip("The CPU does not support this implementation of AES256GCM.")
22 | }
23 |
24 | // Test the key generation
25 | if *GenerateKey() == ([KeyBytes]byte{}) {
26 | t.Error("Generated key is zero")
27 | }
28 |
29 | // Test the length of NSecBytes
30 | if NSecBytes != 0 {
31 | t.Errorf("NSecBytes is %v but should be %v", NSecBytes, 0)
32 | }
33 |
34 | // Fuzzing
35 | f := fuzz.New()
36 |
37 | // Run tests
38 | for i := 0; i < testCount; i++ {
39 | var c, m, ec, mac []byte
40 | var err error
41 | var test TestData
42 |
43 | // Fuzz the test struct
44 | f.Fuzz(&test)
45 |
46 | // Detached encryption test
47 | c, mac = EncryptDetached(test.Message, test.Ad, &test.Nonce, &test.Key)
48 |
49 | // Encryption test
50 | ec = Encrypt(test.Message, test.Ad, &test.Nonce, &test.Key)
51 | if !bytes.Equal(ec, append(c, mac...)) {
52 | t.Errorf("Encryption failed for %+v", test)
53 | t.FailNow()
54 | }
55 |
56 | // Detached decryption test
57 | m, err = DecryptDetached(c, mac, test.Ad, &test.Nonce, &test.Key)
58 | if err != nil || !bytes.Equal(m, test.Message) {
59 | t.Errorf("Detached decryption failed for %+v", test)
60 | t.FailNow()
61 | }
62 |
63 | // Decryption test
64 | m, err = Decrypt(ec, test.Ad, &test.Nonce, &test.Key)
65 | if err != nil || !bytes.Equal(m, test.Message) {
66 | t.Errorf("Decryption failed for %+v", test)
67 | t.FailNow()
68 | }
69 |
70 | // Failed detached decryption test
71 | mac = make([]byte, ABytes)
72 | m, err = DecryptDetached(c, mac, test.Ad, &test.Nonce, &test.Key)
73 | if err == nil {
74 | t.Errorf("Detached decryption unexpectedly succeeded for %+v", test)
75 | t.FailNow()
76 | }
77 |
78 | // Failed decryption test
79 | copy(ec[len(m):], mac)
80 | m, err = Decrypt(ec, test.Ad, &test.Nonce, &test.Key)
81 | if err == nil {
82 | t.Errorf("Decryption unexpectedly succeeded for %+v", test)
83 | t.FailNow()
84 | }
85 | }
86 | t.Logf("Completed %v tests", testCount)
87 | }
88 |
--------------------------------------------------------------------------------
/crypto/aead/chacha20poly1305/crypto_aead_chacha20poly1305.go:
--------------------------------------------------------------------------------
1 | // Package chacha20poly1305 contains the libsodium bindings for ChaCha20-Poly1305.
2 | package chacha20poly1305
3 |
4 | // #cgo pkg-config: libsodium
5 | // #include
6 | // #include
7 | import "C"
8 | import "github.com/GoKillers/libsodium-go/support"
9 |
10 | // Sodium should always be initialised
11 | func init() {
12 | C.sodium_init()
13 | }
14 |
15 | // Sizes of nonces, key and mac.
16 | const (
17 | KeyBytes int = C.crypto_aead_chacha20poly1305_KEYBYTES // Size of a secret key in bytes
18 | NSecBytes int = C.crypto_aead_chacha20poly1305_NSECBYTES // Size of a secret nonce in bytes
19 | NonceBytes int = C.crypto_aead_chacha20poly1305_NPUBBYTES // Size of a nonce in bytes
20 | ABytes int = C.crypto_aead_chacha20poly1305_ABYTES // Size of an authentication tag in bytes
21 | )
22 |
23 | // GenerateKey generates a secret key
24 | func GenerateKey() *[KeyBytes]byte {
25 | k := new([KeyBytes]byte)
26 | C.crypto_aead_chacha20poly1305_keygen((*C.uchar)(&k[0]))
27 | return k
28 | }
29 |
30 | // Encrypt a message `m` with additional data `ad` using a nonce `npub` and a secret key `k`.
31 | // A ciphertext (including authentication tag) and encryption status are returned.
32 | func Encrypt(m, ad []byte, nonce *[NonceBytes]byte, k *[KeyBytes]byte) (c []byte) {
33 | support.NilPanic(k == nil, "secret key")
34 | support.NilPanic(nonce == nil, "nonce")
35 |
36 | c = make([]byte, len(m)+ABytes)
37 |
38 | C.crypto_aead_chacha20poly1305_encrypt(
39 | (*C.uchar)(support.BytePointer(c)),
40 | (*C.ulonglong)(nil),
41 | (*C.uchar)(support.BytePointer(m)),
42 | (C.ulonglong)(len(m)),
43 | (*C.uchar)(support.BytePointer(ad)),
44 | (C.ulonglong)(len(ad)),
45 | (*C.uchar)(nil),
46 | (*C.uchar)(&nonce[0]),
47 | (*C.uchar)(&k[0]))
48 |
49 | return
50 | }
51 |
52 | // Decrypt and verify a ciphertext `c` using additional data `ad`, nonce `npub` and secret key `k`.
53 | // Returns the decrypted message and verification status.
54 | func Decrypt(c, ad []byte, nonce *[NonceBytes]byte, k *[KeyBytes]byte) (m []byte, err error) {
55 | support.NilPanic(k == nil, "secret key")
56 | support.NilPanic(nonce == nil, "nonce")
57 | support.CheckSizeMin(c, ABytes, "ciphertext")
58 |
59 | m = make([]byte, len(c)-ABytes)
60 |
61 | exit := C.crypto_aead_chacha20poly1305_decrypt(
62 | (*C.uchar)(support.BytePointer(m)),
63 | (*C.ulonglong)(nil),
64 | (*C.uchar)(nil),
65 | (*C.uchar)(&c[0]),
66 | (C.ulonglong)(len(c)),
67 | (*C.uchar)(support.BytePointer(ad)),
68 | (C.ulonglong)(len(ad)),
69 | (*C.uchar)(&nonce[0]),
70 | (*C.uchar)(&k[0]))
71 |
72 | if exit != 0 {
73 | err = &support.VerificationError{}
74 | }
75 |
76 | return
77 | }
78 |
79 | // EncryptDetached encrypts a message `m` with additional data `ad` using
80 | // a nonce `npub` and a secret key `k`.
81 | // A ciphertext, authentication tag and encryption status are returned.
82 | func EncryptDetached(m, ad []byte, nonce *[NonceBytes]byte, k *[KeyBytes]byte) (c, mac []byte) {
83 | support.NilPanic(k == nil, "secret key")
84 | support.NilPanic(nonce == nil, "nonce")
85 |
86 | c = make([]byte, len(m))
87 | mac = make([]byte, ABytes)
88 |
89 | C.crypto_aead_chacha20poly1305_encrypt_detached(
90 | (*C.uchar)(support.BytePointer(c)),
91 | (*C.uchar)(&mac[0]),
92 | (*C.ulonglong)(nil),
93 | (*C.uchar)(support.BytePointer(m)),
94 | (C.ulonglong)(len(m)),
95 | (*C.uchar)(support.BytePointer(ad)),
96 | (C.ulonglong)(len(ad)),
97 | (*C.uchar)(nil),
98 | (*C.uchar)(&nonce[0]),
99 | (*C.uchar)(&k[0]))
100 |
101 | return
102 | }
103 |
104 | // DecryptDetached decrypts and verifies a ciphertext `c` with authentication tag `mac`
105 | // using additional data `ad`, nonce `npub` and secret key `k`.
106 | // Returns the decrypted message and verification status.
107 | func DecryptDetached(c, mac, ad []byte, nonce *[NonceBytes]byte, k *[KeyBytes]byte) (m []byte, err error) {
108 | support.NilPanic(k == nil, "secret key")
109 | support.NilPanic(nonce == nil, "nonce")
110 | support.CheckSize(mac, ABytes, "mac")
111 |
112 | m = make([]byte, len(c))
113 |
114 | exit := C.crypto_aead_chacha20poly1305_decrypt_detached(
115 | (*C.uchar)(support.BytePointer(m)),
116 | (*C.uchar)(nil),
117 | (*C.uchar)(support.BytePointer(c)),
118 | (C.ulonglong)(len(c)),
119 | (*C.uchar)(&mac[0]),
120 | (*C.uchar)(support.BytePointer(ad)),
121 | (C.ulonglong)(len(ad)),
122 | (*C.uchar)(&nonce[0]),
123 | (*C.uchar)(&k[0]))
124 |
125 | if exit != 0 {
126 | err = &support.VerificationError{}
127 | }
128 |
129 | return
130 | }
131 |
--------------------------------------------------------------------------------
/crypto/aead/chacha20poly1305/crypto_aead_chacha20poly1305_test.go:
--------------------------------------------------------------------------------
1 | package chacha20poly1305
2 |
3 | import (
4 | "bytes"
5 | "github.com/google/gofuzz"
6 | "testing"
7 | )
8 |
9 | var testCount = 100000
10 |
11 | type TestData struct {
12 | Message []byte
13 | Ad []byte
14 | Key [KeyBytes]byte
15 | Nonce [NonceBytes]byte
16 | }
17 |
18 | func Test(t *testing.T) {
19 | // Test the key generation
20 | if *GenerateKey() == ([KeyBytes]byte{}) {
21 | t.Error("Generated key is zero")
22 | }
23 |
24 | // Test the length of NSecBytes
25 | if NSecBytes != 0 {
26 | t.Errorf("NSecBytes is %v but should be %v", NSecBytes, 0)
27 | }
28 |
29 | // Fuzzing
30 | f := fuzz.New()
31 |
32 | // Run tests
33 | for i := 0; i < testCount; i++ {
34 | var c, m, ec, mac []byte
35 | var err error
36 | var test TestData
37 |
38 | // Fuzz the test struct
39 | f.Fuzz(&test)
40 |
41 | // Detached encryption test
42 | c, mac = EncryptDetached(test.Message, test.Ad, &test.Nonce, &test.Key)
43 |
44 | // Encryption test
45 | ec = Encrypt(test.Message, test.Ad, &test.Nonce, &test.Key)
46 | if !bytes.Equal(ec, append(c, mac...)) {
47 | t.Errorf("Encryption failed for %+v", test)
48 | t.FailNow()
49 | }
50 |
51 | // Detached decryption test
52 | m, err = DecryptDetached(c, mac, test.Ad, &test.Nonce, &test.Key)
53 | if err != nil || !bytes.Equal(m, test.Message) {
54 | t.Errorf("Detached decryption failed for %+v", test)
55 | t.FailNow()
56 | }
57 |
58 | // Decryption test
59 | m, err = Decrypt(ec, test.Ad, &test.Nonce, &test.Key)
60 | if err != nil || !bytes.Equal(m, test.Message) {
61 | t.Errorf("Decryption failed for %+v", test)
62 | t.FailNow()
63 | }
64 |
65 | // Failed detached decryption test
66 | mac = make([]byte, ABytes)
67 | m, err = DecryptDetached(c, mac, test.Ad, &test.Nonce, &test.Key)
68 | if err == nil {
69 | t.Errorf("Detached decryption unexpectedly succeeded for %+v", test)
70 | t.FailNow()
71 | }
72 |
73 | // Failed decryption test
74 | copy(ec[len(m):], mac)
75 | m, err = Decrypt(ec, test.Ad, &test.Nonce, &test.Key)
76 | if err == nil {
77 | t.Errorf("Decryption unexpectedly succeeded for %+v", test)
78 | t.FailNow()
79 | }
80 | }
81 | t.Logf("Completed %v tests", testCount)
82 | }
83 |
--------------------------------------------------------------------------------
/crypto/aead/chacha20poly1305ietf/crypto_aead_chacha20poly1305_ietf.go:
--------------------------------------------------------------------------------
1 | // Package chacha20poly1305ietf contains the libsodium bindings for the IETF variant of ChaCha20-Poly1305.
2 | package chacha20poly1305ietf
3 |
4 | // #cgo pkg-config: libsodium
5 | // #include
6 | // #include
7 | import "C"
8 | import "github.com/GoKillers/libsodium-go/support"
9 |
10 | // Sodium should always be initialised
11 | func init() {
12 | C.sodium_init()
13 | }
14 |
15 | // Sizes of nonces, key and mac.
16 | const (
17 | KeyBytes int = C.crypto_aead_chacha20poly1305_ietf_KEYBYTES // Size of a secret key in bytes
18 | NSecBytes int = C.crypto_aead_chacha20poly1305_ietf_NSECBYTES // Size of a secret nonce in bytes
19 | NonceBytes int = C.crypto_aead_chacha20poly1305_ietf_NPUBBYTES // Size of a nonce in bytes
20 | ABytes int = C.crypto_aead_chacha20poly1305_ietf_ABYTES // Size of an authentication tag in bytes
21 | )
22 |
23 | // GenerateKey generates a secret key
24 | func GenerateKey() *[KeyBytes]byte {
25 | k := new([KeyBytes]byte)
26 | C.crypto_aead_chacha20poly1305_ietf_keygen((*C.uchar)(&k[0]))
27 | return k
28 | }
29 |
30 | // Encrypt a message `m` with additional data `ad` using a nonce `npub` and a secret key `k`.
31 | // A ciphertext (including authentication tag) and encryption status are returned.
32 | func Encrypt(m, ad []byte, nonce *[NonceBytes]byte, k *[KeyBytes]byte) (c []byte) {
33 | support.NilPanic(k == nil, "secret key")
34 | support.NilPanic(nonce == nil, "nonce")
35 |
36 | c = make([]byte, len(m)+ABytes)
37 |
38 | C.crypto_aead_chacha20poly1305_ietf_encrypt(
39 | (*C.uchar)(support.BytePointer(c)),
40 | (*C.ulonglong)(nil),
41 | (*C.uchar)(support.BytePointer(m)),
42 | (C.ulonglong)(len(m)),
43 | (*C.uchar)(support.BytePointer(ad)),
44 | (C.ulonglong)(len(ad)),
45 | (*C.uchar)(nil),
46 | (*C.uchar)(&nonce[0]),
47 | (*C.uchar)(&k[0]))
48 |
49 | return
50 | }
51 |
52 | // Decrypt and verify a ciphertext `c` using additional data `ad`, nonce `npub` and secret key `k`.
53 | // Returns the decrypted message and verification status.
54 | func Decrypt(c, ad []byte, nonce *[NonceBytes]byte, k *[KeyBytes]byte) (m []byte, err error) {
55 | support.NilPanic(k == nil, "secret key")
56 | support.NilPanic(nonce == nil, "nonce")
57 | support.CheckSizeMin(c, ABytes, "ciphertext")
58 |
59 | m = make([]byte, len(c)-ABytes)
60 |
61 | exit := C.crypto_aead_chacha20poly1305_ietf_decrypt(
62 | (*C.uchar)(support.BytePointer(m)),
63 | (*C.ulonglong)(nil),
64 | (*C.uchar)(nil),
65 | (*C.uchar)(&c[0]),
66 | (C.ulonglong)(len(c)),
67 | (*C.uchar)(support.BytePointer(ad)),
68 | (C.ulonglong)(len(ad)),
69 | (*C.uchar)(&nonce[0]),
70 | (*C.uchar)(&k[0]))
71 |
72 | if exit != 0 {
73 | err = &support.VerificationError{}
74 | }
75 |
76 | return
77 | }
78 |
79 | // EncryptDetached encrypts a message `m` with additional data `ad` using
80 | // a nonce `npub` and a secret key `k`.
81 | // A ciphertext, authentication tag and encryption status are returned.
82 | func EncryptDetached(m, ad []byte, nonce *[NonceBytes]byte, k *[KeyBytes]byte) (c, mac []byte) {
83 | support.NilPanic(k == nil, "secret key")
84 | support.NilPanic(nonce == nil, "nonce")
85 |
86 | c = make([]byte, len(m))
87 | mac = make([]byte, ABytes)
88 |
89 | C.crypto_aead_chacha20poly1305_ietf_encrypt_detached(
90 | (*C.uchar)(support.BytePointer(c)),
91 | (*C.uchar)(&mac[0]),
92 | (*C.ulonglong)(nil),
93 | (*C.uchar)(support.BytePointer(m)),
94 | (C.ulonglong)(len(m)),
95 | (*C.uchar)(support.BytePointer(ad)),
96 | (C.ulonglong)(len(ad)),
97 | (*C.uchar)(nil),
98 | (*C.uchar)(&nonce[0]),
99 | (*C.uchar)(&k[0]))
100 |
101 | return
102 | }
103 |
104 | // DecryptDetached decrypts and verifies a ciphertext `c` with authentication tag `mac`
105 | // using additional data `ad`, nonce `npub` and secret key `k`.
106 | // Returns the decrypted message and verification status.
107 | func DecryptDetached(c, mac, ad []byte, nonce *[NonceBytes]byte, k *[KeyBytes]byte) (m []byte, err error) {
108 | support.NilPanic(k == nil, "secret key")
109 | support.NilPanic(nonce == nil, "nonce")
110 | support.CheckSize(mac, ABytes, "mac")
111 |
112 | m = make([]byte, len(c))
113 |
114 | exit := C.crypto_aead_chacha20poly1305_ietf_decrypt_detached(
115 | (*C.uchar)(support.BytePointer(m)),
116 | (*C.uchar)(nil),
117 | (*C.uchar)(support.BytePointer(c)),
118 | (C.ulonglong)(len(c)),
119 | (*C.uchar)(&mac[0]),
120 | (*C.uchar)(support.BytePointer(ad)),
121 | (C.ulonglong)(len(ad)),
122 | (*C.uchar)(&nonce[0]),
123 | (*C.uchar)(&k[0]))
124 |
125 | if exit != 0 {
126 | err = &support.VerificationError{}
127 | }
128 |
129 | return
130 | }
131 |
--------------------------------------------------------------------------------
/crypto/aead/chacha20poly1305ietf/crypto_aead_chacha20poly1305_ietf_test.go:
--------------------------------------------------------------------------------
1 | package chacha20poly1305ietf
2 |
3 | import (
4 | "bytes"
5 | "github.com/google/gofuzz"
6 | "testing"
7 | )
8 |
9 | var testCount = 100000
10 |
11 | type TestData struct {
12 | Message []byte
13 | Ad []byte
14 | Key [KeyBytes]byte
15 | Nonce [NonceBytes]byte
16 | }
17 |
18 | func Test(t *testing.T) {
19 | // Test the key generation
20 | if *GenerateKey() == ([KeyBytes]byte{}) {
21 | t.Error("Generated key is zero")
22 | }
23 |
24 | // Test the length of NSecBytes
25 | if NSecBytes != 0 {
26 | t.Errorf("NSecBytes is %v but should be %v", NSecBytes, 0)
27 | }
28 |
29 | // Fuzzing
30 | f := fuzz.New()
31 |
32 | // Run tests
33 | for i := 0; i < testCount; i++ {
34 | var c, m, ec, mac []byte
35 | var err error
36 | var test TestData
37 |
38 | // Fuzz the test struct
39 | f.Fuzz(&test)
40 |
41 | // Detached encryption test
42 | c, mac = EncryptDetached(test.Message, test.Ad, &test.Nonce, &test.Key)
43 |
44 | // Encryption test
45 | ec = Encrypt(test.Message, test.Ad, &test.Nonce, &test.Key)
46 | if !bytes.Equal(ec, append(c, mac...)) {
47 | t.Errorf("Encryption failed for %+v", test)
48 | t.FailNow()
49 | }
50 |
51 | // Detached decryption test
52 | m, err = DecryptDetached(c, mac, test.Ad, &test.Nonce, &test.Key)
53 | if err != nil || !bytes.Equal(m, test.Message) {
54 | t.Errorf("Detached decryption failed for %+v", test)
55 | t.FailNow()
56 | }
57 |
58 | // Decryption test
59 | m, err = Decrypt(ec, test.Ad, &test.Nonce, &test.Key)
60 | if err != nil || !bytes.Equal(m, test.Message) {
61 | t.Errorf("Decryption failed for %+v", test)
62 | t.FailNow()
63 | }
64 |
65 | // Failed detached decryption test
66 | mac = make([]byte, ABytes)
67 | m, err = DecryptDetached(c, mac, test.Ad, &test.Nonce, &test.Key)
68 | if err == nil {
69 | t.Errorf("Detached decryption unexpectedly succeeded for %+v", test)
70 | t.FailNow()
71 | }
72 |
73 | // Failed decryption test
74 | copy(ec[len(m):], mac)
75 | m, err = Decrypt(ec, test.Ad, &test.Nonce, &test.Key)
76 | if err == nil {
77 | t.Errorf("Decryption unexpectedly succeeded for %+v", test)
78 | t.FailNow()
79 | }
80 | }
81 | t.Logf("Completed %v tests", testCount)
82 | }
83 |
--------------------------------------------------------------------------------
/crypto/aead/crypto_aead.go:
--------------------------------------------------------------------------------
1 | // Package aead contains bindings for authenticated encryption with additional data.
2 | package aead
3 |
4 | // #cgo pkg-config: libsodium
5 | // #include
6 | // #include
7 | import "C"
8 | import "crypto/cipher"
9 |
10 | // Sodium should always be initialised
11 | func init() {
12 | C.sodium_init()
13 | }
14 |
15 | // AEAD is and extended version of cipher.AEAD
16 | type AEAD interface {
17 | cipher.AEAD
18 |
19 | // SealDetached encrypts and authenticates plaintext, authenticates the
20 | // additional data and appends the result to dst, returning the updated
21 | // slice and the authentication code (mac) separately.
22 | // The nonce must be NonceSize() bytes long and unique for all time, for a given key.
23 | // The mac is Overhead() bytes long.
24 | //
25 | // The plaintext and dst may alias exactly or not at all. To reuse
26 | // plaintext's storage for the encrypted output, use plaintext[:0] as dst.
27 | SealDetached(dst, nonce, plaintext, additionalData []byte) ([]byte, []byte)
28 |
29 | // OpenDetached decrypts a ciphertext, authenticates the additional data using
30 | // the autentication code (mac) and, if successful, appends the resulting plaintext
31 | // to dst, returning the updated slice. The nonce must be NonceSize()
32 | // bytes long and both it and the additional data must match the
33 | // value passed to Seal.
34 | //
35 | // The ciphertext and dst may alias exactly or not at all. To reuse
36 | // ciphertext's storage for the decrypted output, use ciphertext[:0] as dst.
37 | //
38 | // Even if the function fails, the contents of dst, up to its capacity,
39 | // may be overwritten.
40 | OpenDetached(dst, nonce, ciphertext, mac, additionalData []byte) ([]byte, error)
41 | }
42 |
43 | // appendSlices appends a slice with a number of empty bytes and
44 | // returns the new slice and a slice pointing to the empty data.
45 | func appendSlices(in []byte, n int) ([]byte, []byte) {
46 | slice := append(in, make([]byte, n)...)
47 | return slice, slice[len(in):]
48 | }
49 |
--------------------------------------------------------------------------------
/crypto/aead/crypto_aead_aes256gcm.go:
--------------------------------------------------------------------------------
1 | package aead
2 |
3 | // #cgo pkg-config: libsodium
4 | // #include
5 | // #include
6 | import "C"
7 | import (
8 | "github.com/GoKillers/libsodium-go/crypto/aead/aes256gcm"
9 | "github.com/GoKillers/libsodium-go/support"
10 | "unsafe"
11 | )
12 |
13 | // AES256GCM state struct
14 | type AES256GCM struct {
15 | // Represents crypto_aead_aes256gcm_state, which must be 16 byte aligned.
16 | // This is not enforced by Go, so 16 extra bytes are allocated and
17 | // the 512 aligned bytes in them are used.
18 | state1 [512 + 16]byte
19 | }
20 |
21 | // NewAES256GCM returns a AES256GCM cipher for an AES256 key.
22 | func NewAES256GCM(k *[aes256gcm.KeyBytes]byte) AEAD {
23 | support.NilPanic(k == nil, "key")
24 |
25 | ctx := new(AES256GCM)
26 |
27 | C.crypto_aead_aes256gcm_beforenm(
28 | ctx.state(),
29 | (*C.uchar)(&k[0]))
30 |
31 | return ctx
32 | }
33 |
34 | // state returns a pointer to the space allocated for the state
35 | func (a *AES256GCM) state() *C.crypto_aead_aes256gcm_state {
36 | var offset uintptr
37 | mod := uintptr(unsafe.Pointer(&a.state1)) % 16
38 |
39 | if mod == 0 {
40 | offset = mod
41 | } else {
42 | offset = 16 - mod
43 | }
44 |
45 | return (*C.crypto_aead_aes256gcm_state)(unsafe.Pointer(&a.state1[offset]))
46 | }
47 |
48 | // NonceSize returns the size of the nonce for Seal() and Open()
49 | func (a *AES256GCM) NonceSize() int {
50 | return aes256gcm.NonceBytes
51 | }
52 |
53 | // Overhead returns the size of the MAC overhead for Seal() and Open()
54 | func (a *AES256GCM) Overhead() int {
55 | return aes256gcm.ABytes
56 | }
57 |
58 | // Seal encrypts plaintext using nonce and additional data and appends it to a destination.
59 | // See aead.AEAD for details.
60 | func (a *AES256GCM) Seal(dst, nonce, plaintext, additionalData []byte) (ret []byte) {
61 | support.CheckSize(nonce, a.NonceSize(), "nonce")
62 |
63 | ret, c := appendSlices(dst, len(plaintext)+a.Overhead())
64 |
65 | C.crypto_aead_aes256gcm_encrypt_afternm(
66 | (*C.uchar)(&c[0]),
67 | (*C.ulonglong)(nil),
68 | (*C.uchar)(support.BytePointer(plaintext)),
69 | (C.ulonglong)(len(plaintext)),
70 | (*C.uchar)(support.BytePointer(additionalData)),
71 | (C.ulonglong)(len(additionalData)),
72 | (*C.uchar)(nil),
73 | (*C.uchar)(&nonce[0]),
74 | a.state())
75 |
76 | return
77 | }
78 |
79 | // Open decrypts a ciphertext using a nonce and additional data and appends the result to a destination.
80 | // See aead.AEAD for details.
81 | func (a *AES256GCM) Open(dst, nonce, ciphertext, additionalData []byte) (ret []byte, err error) {
82 | support.CheckSize(nonce, a.NonceSize(), "nonce")
83 | support.CheckSizeMin(ciphertext, a.Overhead(), "ciphertext")
84 |
85 | ret, m := appendSlices(dst, len(ciphertext)-a.Overhead())
86 |
87 | exit := C.crypto_aead_aes256gcm_decrypt_afternm(
88 | (*C.uchar)(support.BytePointer(m)),
89 | (*C.ulonglong)(nil),
90 | (*C.uchar)(nil),
91 | (*C.uchar)(&ciphertext[0]),
92 | (C.ulonglong)(len(ciphertext)),
93 | (*C.uchar)(support.BytePointer(additionalData)),
94 | (C.ulonglong)(len(additionalData)),
95 | (*C.uchar)(&nonce[0]),
96 | a.state())
97 |
98 | if exit != 0 {
99 | err = &support.VerificationError{}
100 | }
101 |
102 | return
103 | }
104 |
105 | // SealDetached encrypts plaintext using nonce and additional data and appends it to a destination.
106 | // See aead.AEAD for details.
107 | func (a *AES256GCM) SealDetached(dst, nonce, plaintext, additionalData []byte) (ret, mac []byte) {
108 | support.CheckSize(nonce, a.NonceSize(), "nonce")
109 |
110 | ret, c := appendSlices(dst, len(plaintext))
111 | mac = make([]byte, a.Overhead())
112 |
113 | C.crypto_aead_aes256gcm_encrypt_detached_afternm(
114 | (*C.uchar)(support.BytePointer(c)),
115 | (*C.uchar)(&mac[0]),
116 | (*C.ulonglong)(nil),
117 | (*C.uchar)(support.BytePointer(plaintext)),
118 | (C.ulonglong)(len(plaintext)),
119 | (*C.uchar)(support.BytePointer(additionalData)),
120 | (C.ulonglong)(len(additionalData)),
121 | (*C.uchar)(nil),
122 | (*C.uchar)(&nonce[0]),
123 | a.state())
124 |
125 | return
126 | }
127 |
128 | // OpenDetached decrypts a ciphertext using a nonce, mac and additional data and appends the result to a destination.
129 | // See aead.AEAD for details.
130 | func (a *AES256GCM) OpenDetached(dst, nonce, ciphertext, mac, additionalData []byte) (ret []byte, err error) {
131 | support.CheckSize(nonce, a.NonceSize(), "nonce")
132 | support.CheckSize(mac, a.Overhead(), "mac")
133 |
134 | ret, m := appendSlices(dst, len(ciphertext))
135 |
136 | exit := C.crypto_aead_aes256gcm_decrypt_detached_afternm(
137 | (*C.uchar)(support.BytePointer(m)),
138 | (*C.uchar)(nil),
139 | (*C.uchar)(support.BytePointer(ciphertext)),
140 | (C.ulonglong)(len(ciphertext)),
141 | (*C.uchar)(&mac[0]),
142 | (*C.uchar)(support.BytePointer(additionalData)),
143 | (C.ulonglong)(len(additionalData)),
144 | (*C.uchar)(&nonce[0]),
145 | a.state())
146 |
147 | if exit != 0 {
148 | err = &support.VerificationError{}
149 | }
150 |
151 | return
152 | }
153 |
--------------------------------------------------------------------------------
/crypto/aead/crypto_aead_aes256gcm_test.go:
--------------------------------------------------------------------------------
1 | package aead
2 |
3 | import (
4 | "bytes"
5 | "github.com/GoKillers/libsodium-go/crypto/aead/aes256gcm"
6 | "github.com/google/gofuzz"
7 | "testing"
8 | )
9 |
10 | var testCount = 100000
11 |
12 | type TestData struct {
13 | Message []byte
14 | Ad []byte
15 | Dst []byte
16 | Key [aes256gcm.KeyBytes]byte
17 | Nonce [aes256gcm.NonceBytes]byte
18 | }
19 |
20 | func Test(t *testing.T) {
21 | // Skip the test if unsupported on this platform
22 | if !aes256gcm.IsAvailable() {
23 | t.Skip("The CPU does not support this implementation of AES256GCM.")
24 | }
25 |
26 | // Fuzzing
27 | f := fuzz.New()
28 |
29 | // Run tests
30 | for i := 0; i < testCount; i++ {
31 | var c, m, ec, mac []byte
32 | var err error
33 | var test TestData
34 |
35 | // Fuzz the test struct
36 | f.Fuzz(&test)
37 |
38 | // Create a key context
39 | ctx := NewAES256GCM(&test.Key)
40 |
41 | // Detached encryption test
42 | c, mac = ctx.SealDetached(test.Dst, test.Nonce[:], test.Message, test.Ad)
43 |
44 | // Check if dst was prepended
45 | if !bytes.Equal(c[:len(test.Dst)], test.Dst) {
46 | t.Error("dst was not prepended")
47 | t.FailNow()
48 | }
49 |
50 | // Encryption test
51 | ec = ctx.Seal(test.Dst, test.Nonce[:], test.Message, test.Ad)
52 | if !bytes.Equal(ec, append(c, mac...)) {
53 | t.Errorf("Encryption failed for %+v", test)
54 | t.FailNow()
55 | }
56 |
57 | // Detached decryption test
58 | m, err = ctx.OpenDetached(test.Dst, test.Nonce[:], c[len(test.Dst):], mac, test.Ad)
59 | if err != nil || !bytes.Equal(m[len(test.Dst):], test.Message) {
60 | t.Errorf("Detached decryption failed for %+v", test)
61 | t.FailNow()
62 | }
63 |
64 | // Check if dst was prepended
65 | if !bytes.Equal(m[:len(test.Dst)], test.Dst) {
66 | t.Error("dst was not prepended")
67 | t.FailNow()
68 | }
69 |
70 | // Decryption test
71 | m, err = ctx.Open(test.Dst, test.Nonce[:], ec[len(test.Dst):], test.Ad)
72 | if err != nil || !bytes.Equal(m[len(test.Dst):], test.Message) {
73 | t.Errorf("Decryption failed for %+v", test)
74 | t.FailNow()
75 | }
76 |
77 | // Failed detached decryption test
78 | mac = make([]byte, ctx.Overhead())
79 | m, err = ctx.OpenDetached(test.Dst, test.Nonce[:], c[len(test.Dst):], mac, test.Ad)
80 | if err == nil {
81 | t.Errorf("Detached decryption unexpectedly succeeded for %+v", test)
82 | t.FailNow()
83 | }
84 |
85 | // Failed decryption test
86 | copy(ec[len(test.Dst)+len(m):], mac)
87 | m, err = ctx.Open(test.Dst, test.Nonce[:], ec[len(test.Dst):], test.Ad)
88 | if err == nil {
89 | t.Errorf("Decryption unexpectedly succeeded for %+v", test)
90 | t.FailNow()
91 | }
92 | }
93 |
94 | t.Logf("Completed %v tests", testCount)
95 | }
96 |
--------------------------------------------------------------------------------
/crypto/aead/xchacha20poly1305ietf/crypto_aead_xchacha20poly1305_ietf.go:
--------------------------------------------------------------------------------
1 | // Package xchacha20poly1305ietf contains the libsodium bindings for the IETF variant of XChaCha20-Poly1305.
2 | package xchacha20poly1305ietf
3 |
4 | // #cgo pkg-config: libsodium
5 | // #include
6 | // #include
7 | import "C"
8 | import "github.com/GoKillers/libsodium-go/support"
9 |
10 | // Sodium should always be initialised
11 | func init() {
12 | C.sodium_init()
13 | }
14 |
15 | // Sizes of nonces, key and mac.
16 | const (
17 | KeyBytes int = C.crypto_aead_xchacha20poly1305_ietf_KEYBYTES // Size of a secret key in bytes
18 | NSecBytes int = C.crypto_aead_xchacha20poly1305_ietf_NSECBYTES // Size of a secret nonce in bytes
19 | NonceBytes int = C.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES // Size of a nonce in bytes
20 | ABytes int = C.crypto_aead_xchacha20poly1305_ietf_ABYTES // Size of an authentication tag in bytes
21 | )
22 |
23 | // GenerateKey generates a secret key
24 | func GenerateKey() *[KeyBytes]byte {
25 | k := new([KeyBytes]byte)
26 | C.crypto_aead_xchacha20poly1305_ietf_keygen((*C.uchar)(&k[0]))
27 | return k
28 | }
29 |
30 | // Encrypt a message `m` with additional data `ad` using a nonce `npub` and a secret key `k`.
31 | // A ciphertext (including authentication tag) and encryption status are returned.
32 | func Encrypt(m, ad []byte, nonce *[NonceBytes]byte, k *[KeyBytes]byte) (c []byte) {
33 | support.NilPanic(k == nil, "secret key")
34 | support.NilPanic(nonce == nil, "nonce")
35 |
36 | c = make([]byte, len(m)+ABytes)
37 |
38 | C.crypto_aead_xchacha20poly1305_ietf_encrypt(
39 | (*C.uchar)(support.BytePointer(c)),
40 | (*C.ulonglong)(nil),
41 | (*C.uchar)(support.BytePointer(m)),
42 | (C.ulonglong)(len(m)),
43 | (*C.uchar)(support.BytePointer(ad)),
44 | (C.ulonglong)(len(ad)),
45 | (*C.uchar)(nil),
46 | (*C.uchar)(&nonce[0]),
47 | (*C.uchar)(&k[0]))
48 |
49 | return
50 | }
51 |
52 | // Decrypt and verify a ciphertext `c` using additional data `ad`, nonce `npub` and secret key `k`.
53 | // Returns the decrypted message and verification status.
54 | func Decrypt(c, ad []byte, nonce *[NonceBytes]byte, k *[KeyBytes]byte) (m []byte, err error) {
55 | support.NilPanic(k == nil, "secret key")
56 | support.NilPanic(nonce == nil, "nonce")
57 | support.CheckSizeMin(c, ABytes, "ciphertext")
58 |
59 | m = make([]byte, len(c)-ABytes)
60 |
61 | exit := C.crypto_aead_xchacha20poly1305_ietf_decrypt(
62 | (*C.uchar)(support.BytePointer(m)),
63 | (*C.ulonglong)(nil),
64 | (*C.uchar)(nil),
65 | (*C.uchar)(&c[0]),
66 | (C.ulonglong)(len(c)),
67 | (*C.uchar)(support.BytePointer(ad)),
68 | (C.ulonglong)(len(ad)),
69 | (*C.uchar)(&nonce[0]),
70 | (*C.uchar)(&k[0]))
71 |
72 | if exit != 0 {
73 | err = &support.VerificationError{}
74 | }
75 |
76 | return
77 | }
78 |
79 | // EncryptDetached encrypts a message `m` with additional data `ad` using
80 | // a nonce `npub` and a secret key `k`.
81 | // A ciphertext, authentication tag and encryption status are returned.
82 | func EncryptDetached(m, ad []byte, nonce *[NonceBytes]byte, k *[KeyBytes]byte) (c, mac []byte) {
83 | support.NilPanic(k == nil, "secret key")
84 | support.NilPanic(nonce == nil, "nonce")
85 |
86 | c = make([]byte, len(m))
87 | mac = make([]byte, ABytes)
88 |
89 | C.crypto_aead_xchacha20poly1305_ietf_encrypt_detached(
90 | (*C.uchar)(support.BytePointer(c)),
91 | (*C.uchar)(&mac[0]),
92 | (*C.ulonglong)(nil),
93 | (*C.uchar)(support.BytePointer(m)),
94 | (C.ulonglong)(len(m)),
95 | (*C.uchar)(support.BytePointer(ad)),
96 | (C.ulonglong)(len(ad)),
97 | (*C.uchar)(nil),
98 | (*C.uchar)(&nonce[0]),
99 | (*C.uchar)(&k[0]))
100 |
101 | return
102 | }
103 |
104 | // DecryptDetached decrypts and verifies a ciphertext `c` with authentication tag `mac`
105 | // using additional data `ad`, nonce `npub` and secret key `k`.
106 | // Returns the decrypted message and verification status.
107 | func DecryptDetached(c, mac, ad []byte, nonce *[NonceBytes]byte, k *[KeyBytes]byte) (m []byte, err error) {
108 | support.NilPanic(k == nil, "secret key")
109 | support.NilPanic(nonce == nil, "nonce")
110 | support.CheckSize(mac, ABytes, "mac")
111 |
112 | m = make([]byte, len(c))
113 |
114 | exit := C.crypto_aead_xchacha20poly1305_ietf_decrypt_detached(
115 | (*C.uchar)(support.BytePointer(m)),
116 | (*C.uchar)(nil),
117 | (*C.uchar)(support.BytePointer(c)),
118 | (C.ulonglong)(len(c)),
119 | (*C.uchar)(&mac[0]),
120 | (*C.uchar)(support.BytePointer(ad)),
121 | (C.ulonglong)(len(ad)),
122 | (*C.uchar)(&nonce[0]),
123 | (*C.uchar)(&k[0]))
124 |
125 | if exit != 0 {
126 | err = &support.VerificationError{}
127 | }
128 |
129 | return
130 | }
131 |
--------------------------------------------------------------------------------
/crypto/aead/xchacha20poly1305ietf/crypto_aead_xchacha20poly1305_ietf_test.go:
--------------------------------------------------------------------------------
1 | package xchacha20poly1305ietf
2 |
3 | import (
4 | "bytes"
5 | "github.com/google/gofuzz"
6 | "testing"
7 | )
8 |
9 | var testCount = 100000
10 |
11 | type TestData struct {
12 | Message []byte
13 | Ad []byte
14 | Key [KeyBytes]byte
15 | Nonce [NonceBytes]byte
16 | }
17 |
18 | func Test(t *testing.T) {
19 | // Test the key generation
20 | if *GenerateKey() == ([KeyBytes]byte{}) {
21 | t.Error("Generated key is zero")
22 | }
23 |
24 | // Test the length of NSecBytes
25 | if NSecBytes != 0 {
26 | t.Errorf("NSecBytes is %v but should be %v", NSecBytes, 0)
27 | }
28 |
29 | // Fuzzing
30 | f := fuzz.New()
31 |
32 | // Run tests
33 | for i := 0; i < testCount; i++ {
34 | var c, m, ec, mac []byte
35 | var err error
36 | var test TestData
37 |
38 | // Fuzz the test struct
39 | f.Fuzz(&test)
40 |
41 | // Detached encryption test
42 | c, mac = EncryptDetached(test.Message, test.Ad, &test.Nonce, &test.Key)
43 |
44 | // Encryption test
45 | ec = Encrypt(test.Message, test.Ad, &test.Nonce, &test.Key)
46 | if !bytes.Equal(ec, append(c, mac...)) {
47 | t.Errorf("Encryption failed for %+v", test)
48 | t.FailNow()
49 | }
50 |
51 | // Detached decryption test
52 | m, err = DecryptDetached(c, mac, test.Ad, &test.Nonce, &test.Key)
53 | if err != nil || !bytes.Equal(m, test.Message) {
54 | t.Errorf("Detached decryption failed for %+v", test)
55 | t.FailNow()
56 | }
57 |
58 | // Decryption test
59 | m, err = Decrypt(ec, test.Ad, &test.Nonce, &test.Key)
60 | if err != nil || !bytes.Equal(m, test.Message) {
61 | t.Errorf("Decryption failed for %+v", test)
62 | t.FailNow()
63 | }
64 |
65 | // Failed detached decryption test
66 | mac = make([]byte, ABytes)
67 | m, err = DecryptDetached(c, mac, test.Ad, &test.Nonce, &test.Key)
68 | if err == nil {
69 | t.Errorf("Detached decryption unexpectedly succeeded for %+v", test)
70 | t.FailNow()
71 | }
72 |
73 | // Failed decryption test
74 | copy(ec[len(m):], mac)
75 | m, err = Decrypt(ec, test.Ad, &test.Nonce, &test.Key)
76 | if err == nil {
77 | t.Errorf("Decryption unexpectedly succeeded for %+v", test)
78 | t.FailNow()
79 | }
80 | }
81 | t.Logf("Completed %v tests", testCount)
82 | }
83 |
--------------------------------------------------------------------------------
/cryptoaead/crypto_aead_aes256gcm.go:
--------------------------------------------------------------------------------
1 | package cryptoaead
2 |
3 | // #cgo pkg-config: libsodium
4 | // #include
5 | // #include
6 | import "C"
7 | import (
8 | "github.com/GoKillers/libsodium-go/support"
9 | "unsafe"
10 | )
11 |
12 | func CryptoAEADAES256GCMIsAvailable() bool {
13 | C.sodium_init()
14 | return int(C.crypto_aead_aes256gcm_is_available()) != 0
15 | }
16 |
17 | func CryptoAEADAES256GCMKeyBytes() int {
18 | return int(C.crypto_aead_aes256gcm_keybytes())
19 | }
20 |
21 | func CryptoAEADAES256GCMNSecBytes() int {
22 | return int(C.crypto_aead_aes256gcm_nsecbytes())
23 | }
24 |
25 | func CryptoAEADAES256GCMNPubBytes() int {
26 | return int(C.crypto_aead_aes256gcm_npubbytes())
27 | }
28 |
29 | func CryptoAEADAES256GCMABytes() int {
30 | return int(C.crypto_aead_aes256gcm_abytes())
31 | }
32 |
33 | func CryptoAEADAES256GCMStateBytes() int {
34 | return int(C.crypto_aead_aes256gcm_statebytes())
35 | }
36 |
37 | func CryptoAEADAES256GCMEncrypt(m, ad, npub, k []byte) ([]byte, int) {
38 | support.CheckSize(k, CryptoAEADAES256GCMKeyBytes(), "secret key")
39 | support.CheckSize(npub, CryptoAEADAES256GCMNPubBytes(), "public nonce")
40 |
41 | c := make([]byte, len(m)+CryptoAEADAES256GCMABytes())
42 | cLen := C.ulonglong(len(c))
43 |
44 | exit := int(C.crypto_aead_aes256gcm_encrypt(
45 | (*C.uchar)(support.BytePointer(c)),
46 | (*C.ulonglong)(&cLen),
47 | (*C.uchar)(support.BytePointer(m)),
48 | (C.ulonglong)(len(m)),
49 | (*C.uchar)(support.BytePointer(ad)),
50 | (C.ulonglong)(len(ad)),
51 | (*C.uchar)(nil),
52 | (*C.uchar)(&npub[0]),
53 | (*C.uchar)(&k[0])))
54 |
55 | return c, exit
56 | }
57 |
58 | func CryptoAEADAES256GCMDecrypt(c, ad, npub, k []byte) ([]byte, int) {
59 | support.CheckSize(k, CryptoAEADAES256GCMKeyBytes(), "secret key")
60 | support.CheckSize(npub, CryptoAEADAES256GCMNPubBytes(), "public nonce")
61 | support.CheckSizeMin(c, CryptoAEADAES256GCMABytes(), "ciphertext")
62 |
63 | m := make([]byte, len(c)-CryptoAEADAES256GCMABytes())
64 | mLen := (C.ulonglong)(len(m))
65 |
66 | exit := int(C.crypto_aead_aes256gcm_decrypt(
67 | (*C.uchar)(support.BytePointer(m)),
68 | (*C.ulonglong)(&mLen),
69 | (*C.uchar)(nil),
70 | (*C.uchar)(&c[0]),
71 | (C.ulonglong)(len(c)),
72 | (*C.uchar)(support.BytePointer(ad)),
73 | (C.ulonglong)(len(ad)),
74 | (*C.uchar)(&npub[0]),
75 | (*C.uchar)(&k[0])))
76 |
77 | return m, exit
78 | }
79 |
80 | func CryptoAEADAES256GCMEncryptDetached(m, ad, npub, k []byte) ([]byte, []byte, int) {
81 | support.CheckSize(k, CryptoAEADAES256GCMKeyBytes(), "secret key")
82 | support.CheckSize(npub, CryptoAEADAES256GCMNPubBytes(), "public nonce")
83 |
84 | c := make([]byte, len(m))
85 | mac := make([]byte , CryptoAEADAES256GCMABytes())
86 | macLen := C.ulonglong(len(c))
87 |
88 | exit := int(C.crypto_aead_aes256gcm_encrypt_detached(
89 | (*C.uchar)(support.BytePointer(c)),
90 | (*C.uchar)(&mac[0]),
91 | (*C.ulonglong)(&macLen),
92 | (*C.uchar)(support.BytePointer(m)),
93 | (C.ulonglong)(len(m)),
94 | (*C.uchar)(support.BytePointer(ad)),
95 | (C.ulonglong)(len(ad)),
96 | (*C.uchar)(nil),
97 | (*C.uchar)(&npub[0]),
98 | (*C.uchar)(&k[0])))
99 |
100 | return c, mac, exit
101 | }
102 |
103 | func CryptoAEADAES256GCMDecryptDetached(c, mac, ad, npub, k []byte) ([]byte, int) {
104 | support.CheckSize(k, CryptoAEADAES256GCMKeyBytes(), "secret key")
105 | support.CheckSize(npub, CryptoAEADAES256GCMNPubBytes(), "public nonce")
106 | support.CheckSize(mac, CryptoAEADAES256GCMABytes(), "mac")
107 |
108 | m := make([]byte, len(c))
109 |
110 | exit := int(C.crypto_aead_aes256gcm_decrypt_detached(
111 | (*C.uchar)(support.BytePointer(m)),
112 | (*C.uchar)(nil),
113 | (*C.uchar)(support.BytePointer(c)),
114 | (C.ulonglong)(len(c)),
115 | (*C.uchar)(&mac[0]),
116 | (*C.uchar)(support.BytePointer(ad)),
117 | (C.ulonglong)(len(ad)),
118 | (*C.uchar)(&npub[0]),
119 | (*C.uchar)(&k[0])))
120 |
121 | return m, exit
122 | }
123 |
124 | func CryptoAEADAES256GCMBeforeNM(k []byte) ([]byte, int) {
125 | support.CheckSize(k, CryptoAEADAES256GCMKeyBytes(), "secret key")
126 |
127 | ctx := support.AlignedSlice(CryptoAEADAES256GCMStateBytes(), 16)
128 |
129 | exit := int(C.crypto_aead_aes256gcm_beforenm(
130 | (*C.crypto_aead_aes256gcm_state)(unsafe.Pointer(&ctx[0])),
131 | (*C.uchar)(&k[0])))
132 |
133 | return ctx, exit
134 | }
135 |
136 | func CryptoAEADAES256GCMEncryptAfterNM(m, ad, npub, ctx []byte) ([]byte, int) {
137 | support.CheckSize(ctx, CryptoAEADAES256GCMStateBytes(), "context")
138 | support.CheckSize(npub, CryptoAEADAES256GCMNPubBytes(), "public nonce")
139 |
140 | c := make([]byte, len(m)+CryptoAEADAES256GCMABytes())
141 | cLen := C.ulonglong(len(c))
142 |
143 | exit := int(C.crypto_aead_aes256gcm_encrypt_afternm(
144 | (*C.uchar)(support.BytePointer(c)),
145 | (*C.ulonglong)(&cLen),
146 | (*C.uchar)(support.BytePointer(m)),
147 | (C.ulonglong)(len(m)),
148 | (*C.uchar)(support.BytePointer(ad)),
149 | (C.ulonglong)(len(ad)),
150 | (*C.uchar)(nil),
151 | (*C.uchar)(&npub[0]),
152 | (*[512]C.uchar)(unsafe.Pointer(&ctx[0]))))
153 |
154 | return c, exit
155 | }
156 |
157 | func CryptoAEADAES256GCMDecryptAfterNM(c, ad, npub, ctx []byte) ([]byte, int) {
158 | support.CheckSize(ctx, CryptoAEADAES256GCMStateBytes(), "context")
159 | support.CheckSize(npub, CryptoAEADAES256GCMNPubBytes(), "public nonce")
160 | support.CheckSizeMin(c, CryptoAEADAES256GCMABytes(), "ciphertext")
161 |
162 | m := make([]byte, len(c)-CryptoAEADAES256GCMABytes())
163 | mLen := (C.ulonglong)(len(m))
164 |
165 | exit := int(C.crypto_aead_aes256gcm_decrypt_afternm(
166 | (*C.uchar)(support.BytePointer(m)),
167 | (*C.ulonglong)(&mLen),
168 | (*C.uchar)(nil),
169 | (*C.uchar)(&c[0]),
170 | (C.ulonglong)(len(c)),
171 | (*C.uchar)(support.BytePointer(ad)),
172 | (C.ulonglong)(len(ad)),
173 | (*C.uchar)(&npub[0]),
174 | (*[512]C.uchar)(unsafe.Pointer(&ctx[0]))))
175 |
176 | return m, exit
177 | }
178 |
179 | func CryptoAEADAES256GCMEncryptDetachedAfterNM(m, ad, npub, ctx []byte) ([]byte, []byte, int) {
180 | support.CheckSize(ctx, CryptoAEADAES256GCMStateBytes(), "context")
181 | support.CheckSize(npub, CryptoAEADAES256GCMNPubBytes(), "public nonce")
182 |
183 | c := make([]byte, len(m))
184 | mac := make([]byte , CryptoAEADAES256GCMABytes())
185 | macLen := C.ulonglong(len(c))
186 |
187 | exit := int(C.crypto_aead_aes256gcm_encrypt_detached_afternm(
188 | (*C.uchar)(support.BytePointer(c)),
189 | (*C.uchar)(&mac[0]),
190 | (*C.ulonglong)(&macLen),
191 | (*C.uchar)(support.BytePointer(m)),
192 | (C.ulonglong)(len(m)),
193 | (*C.uchar)(support.BytePointer(ad)),
194 | (C.ulonglong)(len(ad)),
195 | (*C.uchar)(nil),
196 | (*C.uchar)(&npub[0]),
197 | (*[512]C.uchar)(unsafe.Pointer(&ctx[0]))))
198 |
199 | return c, mac, exit
200 | }
201 |
202 | func CryptoAEADAES256GCMDecryptDetachedAfterNM(c, mac, ad, npub, ctx []byte) ([]byte, int) {
203 | support.CheckSize(ctx, CryptoAEADAES256GCMStateBytes(), "context")
204 | support.CheckSize(npub, CryptoAEADAES256GCMNPubBytes(), "public nonce")
205 | support.CheckSize(mac, CryptoAEADAES256GCMABytes(), "mac")
206 |
207 | m := make([]byte, len(c))
208 |
209 | exit := int(C.crypto_aead_aes256gcm_decrypt_detached_afternm(
210 | (*C.uchar)(support.BytePointer(m)),
211 | (*C.uchar)(nil),
212 | (*C.uchar)(support.BytePointer(c)),
213 | (C.ulonglong)(len(c)),
214 | (*C.uchar)(&mac[0]),
215 | (*C.uchar)(support.BytePointer(ad)),
216 | (C.ulonglong)(len(ad)),
217 | (*C.uchar)(&npub[0]),
218 | (*[512]C.uchar)(unsafe.Pointer(&ctx[0]))))
219 |
220 | return m, exit
221 | }
222 |
223 | func CryptoAEADAES256GCMKeyGen() []byte {
224 | k := make([]byte, CryptoAEADAES256GCMKeyBytes())
225 | C.crypto_aead_aes256gcm_keygen((*C.uchar)(&k[0]))
226 | return k
227 | }
228 |
--------------------------------------------------------------------------------
/cryptoaead/crypto_aead_aes256gcm_test.go:
--------------------------------------------------------------------------------
1 | package cryptoaead
2 |
3 | import (
4 | "testing"
5 | "bytes"
6 | "github.com/google/gofuzz"
7 | )
8 |
9 | var testCount = 100000
10 |
11 | type Test struct {
12 | Message []byte
13 | Ad []byte
14 | Key [32]byte
15 | Nonce [12]byte
16 | Ciphertext []byte
17 | Mac []byte
18 | }
19 |
20 | func TestCryptoAEADAES256GCM(t *testing.T) {
21 | // Skip the test if unsupported on this platform
22 | if !CryptoAEADAES256GCMIsAvailable() {
23 | t.Skip("The CPU does not support this implementation of AES256GCM.")
24 | }
25 |
26 | // Test the key generation
27 | if len(CryptoAEADAES256GCMKeyGen()) != CryptoAEADAES256GCMKeyBytes() {
28 | t.Error("Generated key has the wrong length")
29 | }
30 |
31 | // Test the length of NSecBytes
32 | if CryptoAEADAES256GCMNSecBytes() != 0 {
33 | t.Errorf("CryptoAEADAES256GCMNSecBytes is %v but should be %v", CryptoAEADAES256GCMNSecBytes(), 0)
34 | }
35 |
36 | // Fuzzing
37 | f := fuzz.New()
38 |
39 | // Run tests
40 | for i := 0; i < testCount; i++ {
41 | var c, m, ec, mac []byte
42 | var err int
43 | var test Test
44 |
45 | // Fuzz the test struct
46 | f.Fuzz(&test)
47 |
48 | // Create a key context
49 | ctx, err := CryptoAEADAES256GCMBeforeNM(test.Key[:])
50 | if err != 0 {
51 | t.Error("Context creation failed for %+v", test)
52 | }
53 |
54 | // Detached encryption test
55 | test.Ciphertext, test.Mac, err = CryptoAEADAES256GCMEncryptDetached(test.Message, test.Ad, test.Nonce[:], test.Key[:])
56 | if err != 0 {
57 | t.Errorf("Detached encryption failed for %+v", test)
58 | }
59 |
60 | // Detached encryption with context
61 | c, mac, err = CryptoAEADAES256GCMEncryptDetachedAfterNM(test.Message, test.Ad, test.Nonce[:], ctx)
62 | if err != 0 || !bytes.Equal(c, test.Ciphertext) || !bytes.Equal(mac, test.Mac) {
63 | t.Errorf("Detached encryption with context failed for %+v", test)
64 | }
65 |
66 | // Encryption test
67 | ec, err = CryptoAEADAES256GCMEncrypt(test.Message, test.Ad, test.Nonce[:], test.Key[:])
68 | if err != 0 || !bytes.Equal(ec, append(test.Ciphertext, test.Mac...)) {
69 | t.Errorf("Encryption failed for %+v", test)
70 | }
71 |
72 | // Encryption with context
73 | ec, err = CryptoAEADAES256GCMEncryptAfterNM(test.Message, test.Ad, test.Nonce[:], ctx)
74 | if err != 0 || !bytes.Equal(ec, append(test.Ciphertext, test.Mac...)) {
75 | t.Errorf("Encryption with context failed for %+v", test)
76 | }
77 |
78 | // Detached decryption test
79 | m, err = CryptoAEADAES256GCMDecryptDetached(c, mac, test.Ad, test.Nonce[:], test.Key[:])
80 | if err != 0 || !bytes.Equal(m, test.Message) {
81 | t.Errorf("Detached decryption failed for %+v", test)
82 | }
83 |
84 | // Detached decryption with context test
85 | m, err = CryptoAEADAES256GCMDecryptDetachedAfterNM(c, mac, test.Ad, test.Nonce[:], ctx)
86 | if err != 0 || !bytes.Equal(m, test.Message) {
87 | t.Errorf("Detached decryption with context failed for %+v", test)
88 | }
89 |
90 | // Decryption test
91 | m, err = CryptoAEADAES256GCMDecrypt(ec, test.Ad, test.Nonce[:], test.Key[:])
92 | if err != 0 || !bytes.Equal(m, test.Message) {
93 | t.Errorf("Decryption failed for %+v", test)
94 | }
95 |
96 | // Decryption with context test
97 | m, err = CryptoAEADAES256GCMDecryptAfterNM(ec, test.Ad, test.Nonce[:], ctx)
98 | if err != 0 || !bytes.Equal(m, test.Message) {
99 | t.Errorf("Decryption with context failed for %+v", test)
100 | }
101 | }
102 | t.Logf("Completed %v tests", testCount)
103 | }
104 |
--------------------------------------------------------------------------------
/cryptoauth/crypto_auth.go:
--------------------------------------------------------------------------------
1 | package cryptoauth
2 |
3 | // #cgo pkg-config: libsodium
4 | // #include
5 | // #include
6 | import "C"
7 | import "github.com/GoKillers/libsodium-go/support"
8 |
9 | func CryptoAuthBytes() int {
10 | return int(C.crypto_auth_bytes())
11 | }
12 |
13 | func CryptoAuthKeyBytes() int {
14 | return int(C.crypto_auth_keybytes())
15 | }
16 |
17 | func CryptoAuthPrimitive() string {
18 | return C.GoString(C.crypto_auth_primitive())
19 | }
20 |
21 | func CryptoAuth(in []byte, key []byte) ([]byte, int) {
22 | support.CheckSize(key, CryptoAuthKeyBytes(), "key")
23 | inlen := len(in)
24 | out := make([]byte, inlen + CryptoAuthBytes())
25 |
26 | exit := int(C.crypto_auth(
27 | (*C.uchar)(&out[0]),
28 | (*C.uchar)(&in[0]),
29 | (C.ulonglong)(inlen),
30 | (*C.uchar)(&key[0])))
31 |
32 | return out, exit
33 | }
34 |
35 | func CryptoAuthVerify(hmac []byte, in []byte, key []byte) int {
36 | support.CheckSize(key, CryptoAuthKeyBytes(), "key")
37 | inlen := len(in)
38 |
39 | exit := int(C.crypto_auth_verify(
40 | (*C.uchar)(&hmac[0]),
41 | (*C.uchar)(&in[0]),
42 | (C.ulonglong)(inlen),
43 | (*C.uchar)(&key[0])))
44 |
45 | return exit
46 | }
47 |
--------------------------------------------------------------------------------
/cryptoauth/hmacsha256/authHMAC256Api.go:
--------------------------------------------------------------------------------
1 | package authhmac256api
2 |
3 | // #cgo pkg-config: libsodium
4 | // #include
5 | // #include
6 | import "C"
7 |
8 | func CryptoAuthHMAC256Bytes() int {
9 | return int(C.crypto_auth_hmacsha256_bytes())
10 | }
11 |
12 | func CryptoAuthHMAC256BKeyBytes() int {
13 | return int(C.crypto_auth_hmacsha256_keybytes())
14 | }
15 |
16 | func CryptoAuthHMAC256StateBytes() int {
17 | return int(C.crypto_auth_hmacsha256_statebytes())
18 | }
19 |
--------------------------------------------------------------------------------
/cryptoauth/hmacsha512/authHMAC512Api.go:
--------------------------------------------------------------------------------
1 | package authhmac512api
2 |
3 | // #cgo pkg-config: libsodium
4 | // #include
5 | // #include
6 | import "C"
7 |
8 | func CryptoAuthHMAC512Bytes() int {
9 | return int(C.crypto_auth_hmacsha512_bytes())
10 | }
11 |
12 | func CryptoAuthHMAC512BKeyBytes() int {
13 | return int(C.crypto_auth_hmacsha512_keybytes())
14 | }
15 |
16 | func CryptoAuthHMAC512StateBytes() int {
17 | return int(C.crypto_auth_hmacsha512_statebytes())
18 | }
19 |
--------------------------------------------------------------------------------
/cryptoauth/hmacsha512/cp/hmacHMACSHA512.go:
--------------------------------------------------------------------------------
1 | package hmachmacsha512
2 |
3 | // #cgo pkg-config: libsodium
4 | // #include
5 | // #include
6 | import "C"
7 |
8 | func CryptoAuthHMACSHA512Init(state *C.struct_crypto_auth_hmacsha512_state, key []byte, keylen int) (*C.struct_crypto_auth_hmacsha512_state, int) {
9 | exit := int(C.crypto_auth_hmacsha512_init(
10 | (state),
11 | (*C.uchar)(&key[0]),
12 | (C.size_t)(keylen)))
13 |
14 | return state, exit
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/cryptobox/crypto_box.go:
--------------------------------------------------------------------------------
1 | package cryptobox
2 |
3 | // #cgo pkg-config: libsodium
4 | // #include
5 | // #include
6 | import "C"
7 | import "github.com/GoKillers/libsodium-go/support"
8 |
9 | func CryptoBoxSeedBytes() int {
10 | return int(C.crypto_box_seedbytes())
11 | }
12 |
13 | func CryptoBoxPublicKeyBytes() int {
14 | return int(C.crypto_box_publickeybytes())
15 | }
16 |
17 | func CryptoBoxSecretKeyBytes() int {
18 | return int(C.crypto_box_secretkeybytes())
19 | }
20 |
21 | func CryptoBoxNonceBytes() int {
22 | return int(C.crypto_box_noncebytes())
23 | }
24 |
25 | func CryptoBoxMacBytes() int {
26 | return int(C.crypto_box_macbytes())
27 | }
28 |
29 | func CryptoBoxPrimitive() string {
30 | return C.GoString(C.crypto_box_primitive())
31 | }
32 |
33 | func CryptoBoxBeforeNmBytes() int {
34 | return int(C.crypto_box_beforenmbytes())
35 | }
36 |
37 | func CryptoBoxZeroBytes() int {
38 | return int(C.crypto_box_zerobytes())
39 | }
40 |
41 | func CryptoBoxBoxZeroBytes() int {
42 | return int(C.crypto_box_boxzerobytes())
43 | }
44 |
45 | func CryptoBoxSeedKeyPair(seed []byte) ([]byte, []byte, int) {
46 | support.CheckSize(seed, CryptoBoxSeedBytes(), "seed")
47 | sk := make([]byte, CryptoBoxSecretKeyBytes())
48 | pk := make([]byte, CryptoBoxPublicKeyBytes())
49 | exit := int(C.crypto_box_seed_keypair(
50 | (*C.uchar)(&pk[0]),
51 | (*C.uchar)(&sk[0]),
52 | (*C.uchar)(&seed[0])))
53 |
54 | return sk, pk, exit
55 | }
56 |
57 | func CryptoBoxKeyPair() ([]byte, []byte, int) {
58 | sk := make([]byte, CryptoBoxSecretKeyBytes())
59 | pk := make([]byte, CryptoBoxPublicKeyBytes())
60 | exit := int(C.crypto_box_keypair(
61 | (*C.uchar)(&pk[0]),
62 | (*C.uchar)(&sk[0])))
63 |
64 | return sk, pk, exit
65 | }
66 |
67 | func CryptoBoxBeforeNm(pk []byte, sk []byte) ([]byte, int) {
68 | support.CheckSize(pk, CryptoBoxPublicKeyBytes(), "public key")
69 | support.CheckSize(sk, CryptoBoxSecretKeyBytes(), "sender's secret key")
70 | k := make([]byte, CryptoBoxBeforeNmBytes())
71 | exit := int(C.crypto_box_beforenm(
72 | (*C.uchar)(&k[0]),
73 | (*C.uchar)(&pk[0]),
74 | (*C.uchar)(&sk[0])))
75 |
76 | return k, exit
77 | }
78 |
79 | func CryptoBox(m []byte, n []byte, pk []byte, sk []byte) ([]byte, int) {
80 | support.CheckSize(n, CryptoBoxNonceBytes(), "nonce")
81 | support.CheckSize(pk, CryptoBoxPublicKeyBytes(), "public key")
82 | support.CheckSize(sk, CryptoBoxSecretKeyBytes(), "sender's secret key")
83 | c := make([]byte, len(m))
84 | exit := int(C.crypto_box(
85 | (*C.uchar)(&c[0]),
86 | (*C.uchar)(&m[0]),
87 | (C.ulonglong)(len(m)),
88 | (*C.uchar)(&n[0]),
89 | (*C.uchar)(&pk[0]),
90 | (*C.uchar)(&sk[0])))
91 |
92 | return c, exit
93 | }
94 |
95 | func CryptoBoxOpen(c []byte, n []byte, pk []byte, sk []byte) ([]byte, int) {
96 | support.CheckSize(n, CryptoBoxNonceBytes(), "nonce")
97 | support.CheckSize(pk, CryptoBoxPublicKeyBytes(), "public key")
98 | support.CheckSize(sk, CryptoBoxPublicKeyBytes(), "secret key")
99 | m := make([]byte, len(c))
100 | exit := int(C.crypto_box_open(
101 | (*C.uchar)(&m[0]),
102 | (*C.uchar)(&c[0]),
103 | (C.ulonglong)(len(c)),
104 | (*C.uchar)(&n[0]),
105 | (*C.uchar)(&pk[0]),
106 | (*C.uchar)(&sk[0])))
107 |
108 | return m, exit
109 | }
110 |
111 | func CryptoBoxAfterNm(m []byte, n []byte, k []byte) ([]byte, int) {
112 | support.CheckSize(n, CryptoBoxNonceBytes(), "nonce")
113 | support.CheckSize(k, CryptoBoxBeforeNmBytes(), "shared secret key")
114 | c := make([]byte, len(m))
115 | exit := int(C.crypto_box_afternm(
116 | (*C.uchar)(&c[0]),
117 | (*C.uchar)(&m[0]),
118 | (C.ulonglong)(len(m)),
119 | (*C.uchar)(&n[0]),
120 | (*C.uchar)(&k[0])))
121 |
122 | return c, exit
123 | }
124 |
125 | func CryptoBoxOpenAfterNm(c []byte, n []byte, k []byte) ([]byte, int) {
126 | support.CheckSize(n, CryptoBoxNonceBytes(), "nonce")
127 | support.CheckSize(k, CryptoBoxBeforeNmBytes(), "shared secret key")
128 | m := make([]byte, len(c))
129 | exit := int(C.crypto_box_open_afternm(
130 | (*C.uchar)(&m[0]),
131 | (*C.uchar)(&c[0]),
132 | (C.ulonglong)(len(c)),
133 | (*C.uchar)(&n[0]),
134 | (*C.uchar)(&k[0])))
135 |
136 | return m, exit
137 | }
138 |
--------------------------------------------------------------------------------
/cryptobox/crypto_box_easy.go:
--------------------------------------------------------------------------------
1 | package cryptobox
2 |
3 | // #cgo pkg-config: libsodium
4 | // #include
5 | // #include
6 | import "C"
7 | import "github.com/GoKillers/libsodium-go/support"
8 |
9 | func CryptoBoxDetachedAfterNm(mac []byte, m []byte, n []byte, k []byte) ([]byte, int) {
10 | support.CheckSize(mac, CryptoBoxMacBytes(), "mac")
11 | support.CheckSize(n, CryptoBoxNonceBytes(), "nonce")
12 | support.CheckSize(k, CryptoBoxBeforeNmBytes(), "shared secret key")
13 | c := make([]byte, len(m)+CryptoBoxMacBytes())
14 | exit := int(C.crypto_box_detached_afternm(
15 | (*C.uchar)(&c[0]),
16 | (*C.uchar)(&mac[0]),
17 | (*C.uchar)(&m[0]),
18 | (C.ulonglong)(len(m)),
19 | (*C.uchar)(&n[0]),
20 | (*C.uchar)(&k[0])))
21 |
22 | return c, exit
23 | }
24 |
25 | func CryptoBoxDetached(mac []byte, m []byte, n []byte, pk []byte, sk []byte) ([]byte, int) {
26 | support.CheckSize(mac, CryptoBoxMacBytes(), "mac")
27 | support.CheckSize(n, CryptoBoxNonceBytes(), "nonce")
28 | support.CheckSize(pk, CryptoBoxPublicKeyBytes(), "public key")
29 | support.CheckSize(sk, CryptoBoxSecretKeyBytes(), "sender's secret key")
30 | c := make([]byte, len(m)+CryptoBoxMacBytes())
31 | exit := int(C.crypto_box_detached(
32 | (*C.uchar)(&c[0]),
33 | (*C.uchar)(&mac[0]),
34 | (*C.uchar)(&m[0]),
35 | (C.ulonglong)(len(m)),
36 | (*C.uchar)(&n[0]),
37 | (*C.uchar)(&pk[0]),
38 | (*C.uchar)(&sk[0])))
39 |
40 | return c, exit
41 | }
42 |
43 | func CryptoBoxEasyAfterNm(m []byte, n []byte, k []byte) ([]byte, int) {
44 | support.CheckSize(n, CryptoBoxNonceBytes(), "nonce")
45 | support.CheckSize(k, CryptoBoxBeforeNmBytes(), "shared secret key")
46 | c := make([]byte, len(m)+CryptoBoxMacBytes())
47 | exit := int(C.crypto_box_easy_afternm(
48 | (*C.uchar)(&c[0]),
49 | (*C.uchar)(&m[0]),
50 | (C.ulonglong)(len(m)),
51 | (*C.uchar)(&n[0]),
52 | (*C.uchar)(&k[0])))
53 |
54 | return c, exit
55 | }
56 |
57 | func CryptoBoxEasy(m []byte, n []byte, pk []byte, sk []byte) ([]byte, int) {
58 | support.CheckSize(n, CryptoBoxNonceBytes(), "nonce")
59 | support.CheckSize(pk, CryptoBoxPublicKeyBytes(), "public key")
60 | support.CheckSize(sk, CryptoBoxSecretKeyBytes(), "secret key")
61 | c := make([]byte, len(m)+CryptoBoxMacBytes())
62 | exit := int(C.crypto_box_easy(
63 | (*C.uchar)(&c[0]),
64 | (*C.uchar)(&m[0]),
65 | (C.ulonglong)(len(m)),
66 | (*C.uchar)(&n[0]),
67 | (*C.uchar)(&pk[0]),
68 | (*C.uchar)(&sk[0])))
69 |
70 | return c, exit
71 | }
72 |
73 | func CryptoBoxOpenDetachedAfterNm(c []byte, mac []byte, n []byte, k []byte) ([]byte, int) {
74 | support.CheckSize(mac, CryptoBoxMacBytes(), "mac")
75 | support.CheckSize(n, CryptoBoxNonceBytes(), "nonce")
76 | support.CheckSize(k, CryptoBoxBeforeNmBytes(), "shared secret key")
77 | m := make([]byte, len(c)-CryptoBoxMacBytes())
78 | exit := int(C.crypto_box_open_detached_afternm(
79 | (*C.uchar)(&m[0]),
80 | (*C.uchar)(&c[0]),
81 | (*C.uchar)(&mac[0]),
82 | (C.ulonglong)(len(c)),
83 | (*C.uchar)(&n[0]),
84 | (*C.uchar)(&k[0])))
85 |
86 | return m, exit
87 | }
88 |
89 | func CryptoBoxOpenDetached(c []byte, mac []byte, n []byte, pk []byte, sk []byte) ([]byte, int) {
90 | support.CheckSize(mac, CryptoBoxMacBytes(), "mac")
91 | support.CheckSize(n, CryptoBoxNonceBytes(), "nonce")
92 | support.CheckSize(pk, CryptoBoxPublicKeyBytes(), "public key")
93 | support.CheckSize(sk, CryptoBoxSecretKeyBytes(), "secret key")
94 | m := make([]byte, len(c)-CryptoBoxMacBytes())
95 | exit := int(C.crypto_box_open_detached(
96 | (*C.uchar)(&m[0]),
97 | (*C.uchar)(&c[0]),
98 | (*C.uchar)(&mac[0]),
99 | (C.ulonglong)(len(c)),
100 | (*C.uchar)(&n[0]),
101 | (*C.uchar)(&pk[0]),
102 | (*C.uchar)(&sk[0])))
103 |
104 | return m, exit
105 | }
106 |
107 | func CryptoBoxOpenEasyAfterNm(c []byte, n []byte, k []byte) ([]byte, int) {
108 | support.CheckSize(n, CryptoBoxNonceBytes(), "nonce")
109 | support.CheckSize(k, CryptoBoxBeforeNmBytes(), "shared secret key")
110 | m := make([]byte, len(c)-CryptoBoxMacBytes())
111 | exit := int(C.crypto_box_open_easy_afternm(
112 | (*C.uchar)(&m[0]),
113 | (*C.uchar)(&c[0]),
114 | (C.ulonglong)(len(c)),
115 | (*C.uchar)(&n[0]),
116 | (*C.uchar)(&k[0])))
117 |
118 | return m, exit
119 | }
120 |
121 | func CryptoBoxOpenEasy(c []byte, n []byte, pk []byte, sk []byte) ([]byte, int) {
122 | support.CheckSize(n, CryptoBoxNonceBytes(), "nonce")
123 | support.CheckSize(pk, CryptoBoxPublicKeyBytes(), "public key")
124 | support.CheckSize(sk, CryptoBoxSecretKeyBytes(), "secret key")
125 | m := make([]byte, len(c)-CryptoBoxMacBytes())
126 | exit := int(C.crypto_box_open_easy(
127 | (*C.uchar)(&m[0]),
128 | (*C.uchar)(&c[0]),
129 | (C.ulonglong)(len(c)),
130 | (*C.uchar)(&n[0]),
131 | (*C.uchar)(&pk[0]),
132 | (*C.uchar)(&sk[0])))
133 |
134 | return m, exit
135 | }
136 |
--------------------------------------------------------------------------------
/cryptobox/crypto_box_seal.go:
--------------------------------------------------------------------------------
1 | package cryptobox
2 |
3 | // #cgo pkg-config: libsodium
4 | // #include
5 | // #include
6 | import "C"
7 | import "github.com/GoKillers/libsodium-go/support"
8 |
9 | func CryptoBoxSeal(m []byte, pk []byte) ([]byte, int) {
10 | support.CheckSize(pk, CryptoBoxPublicKeyBytes(), "public key")
11 | c := make([]byte, len(m)+CryptoBoxSealBytes())
12 | exit := int(C.crypto_box_seal(
13 | (*C.uchar)(&c[0]),
14 | (*C.uchar)(&m[0]),
15 | (C.ulonglong)(len(m)),
16 | (*C.uchar)(&pk[0])))
17 |
18 | return c, exit
19 | }
20 |
21 | func CryptoBoxSealOpen(c []byte, pk []byte, sk []byte) ([]byte, int) {
22 | support.CheckSize(pk, CryptoBoxPublicKeyBytes(), "public key")
23 | support.CheckSize(sk, CryptoBoxSecretKeyBytes(), "secret key")
24 | m := make([]byte, len(c)-CryptoBoxSealBytes())
25 | exit := int(C.crypto_box_seal_open(
26 | (*C.uchar)(&m[0]),
27 | (*C.uchar)(&c[0]),
28 | (C.ulonglong)(len(c)),
29 | (*C.uchar)(&pk[0]),
30 | (*C.uchar)(&sk[0])))
31 |
32 | return m, exit
33 | }
34 |
35 | func CryptoBoxSealBytes() int {
36 | return int(C.crypto_box_sealbytes())
37 | }
38 |
--------------------------------------------------------------------------------
/cryptobox/crypto_box_seal_test.go:
--------------------------------------------------------------------------------
1 | package cryptobox
2 |
3 | import "testing"
4 |
5 | func TestCryptoBoxSeal(t *testing.T) {
6 | sk, pk, exit := CryptoBoxKeyPair()
7 | if exit != 0 {
8 | t.Fatalf("CryptoBoxKeyPair failed: %v", exit)
9 | }
10 | testStr := "test string 12345678901234567890123456789012345678901234567890"
11 | cipherText, exit := CryptoBoxSeal([]byte(testStr), pk)
12 | if exit != 0 {
13 | t.Fatalf("CryptoBoxSeal failed: %v", exit)
14 | }
15 | plaintext, exit := CryptoBoxSealOpen(cipherText, pk, sk)
16 | if exit != 0 {
17 | t.Fatalf("CryptoBoxSealOpen failed: %v", exit)
18 | }
19 | if string(plaintext) != testStr {
20 | t.Fatalf("Bad plaintext: %#v", plaintext)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/cryptogenerichash/crypto_generichash.go:
--------------------------------------------------------------------------------
1 | package generichash
2 |
3 | // #cgo pkg-config: libsodium
4 | // #include
5 | // #include
6 | import "C"
7 | import (
8 | "github.com/GoKillers/libsodium-go/support"
9 | "unsafe"
10 | )
11 |
12 | func CryptoGenericHashBytesMin() int {
13 | return int(C.crypto_generichash_bytes_min())
14 | }
15 |
16 | func CryptoGenericHashBytesMax() int {
17 | return int(C.crypto_generichash_bytes_max())
18 | }
19 |
20 | func CryptoGenericHashBytes() int {
21 | return int(C.crypto_generichash_bytes())
22 | }
23 |
24 | func CryptoGenericHashKeyBytesMin() int {
25 | return int(C.crypto_generichash_keybytes_min())
26 | }
27 |
28 | func CryptoGenericHashKeyBytesMax() int {
29 | return int(C.crypto_generichash_keybytes_max())
30 | }
31 |
32 | func CryptoGenericHashKeyBytes() int {
33 | return int(C.crypto_generichash_keybytes())
34 | }
35 |
36 | func CryptoGenericHashPrimitive() string {
37 | return C.GoString(C.crypto_generichash_primitive())
38 | }
39 |
40 | func CryptoGenericHashStateBytes() int {
41 | return int(C.crypto_generichash_statebytes())
42 | }
43 |
44 | // I took care of the typedef confusions. This should work okay.
45 | func CryptoGenericHash(outlen int, in []byte, key []byte) ([]byte, int) {
46 | support.CheckIntInRange(outlen, CryptoGenericHashBytesMin(), CryptoGenericHashBytesMax(), "out")
47 |
48 | // Check size of key only if actually given
49 | if len(key) > 0 {
50 | support.CheckSizeInRange(key, CryptoGenericHashKeyBytesMin(), CryptoGenericHashKeyBytesMax(), "key")
51 | }
52 |
53 | out := make([]byte, outlen)
54 | exit := int(C.crypto_generichash(
55 | (*C.uchar)(&out[0]),
56 | (C.size_t)(outlen),
57 | (*C.uchar)(support.BytePointer(in)),
58 | (C.ulonglong)(len(in)),
59 | (*C.uchar)(support.BytePointer(key)),
60 | (C.size_t)(len(key))))
61 |
62 | return out, exit
63 | }
64 |
65 | // I took care of the typedef confusions. This should work okay.
66 | func CryptoGenericHashInit(key []byte, outlen int) (*C.struct_crypto_generichash_blake2b_state, int) {
67 | support.CheckIntInRange(outlen, CryptoGenericHashBytesMin(), CryptoGenericHashBytesMax(), "out")
68 |
69 | // Check size of key only if actually given
70 | if len(key) > 0 {
71 | support.CheckSizeInRange(key, CryptoGenericHashKeyBytesMin(), CryptoGenericHashKeyBytesMax(), "key")
72 | }
73 |
74 | state := (*C.struct_crypto_generichash_blake2b_state)(
75 | unsafe.Pointer(&support.AlignedSlice(CryptoGenericHashStateBytes(), 64)[0]))
76 |
77 | exit := int(C.crypto_generichash_init(
78 | state,
79 | (*C.uchar)(support.BytePointer(key)),
80 | (C.size_t)(len(key)),
81 | (C.size_t)(outlen)))
82 |
83 | return state, exit
84 | }
85 |
86 | // I took care of the typedef confusions. This should work okay.
87 | func CryptoGenericHashUpdate(state *C.struct_crypto_generichash_blake2b_state, in []byte) (*C.struct_crypto_generichash_blake2b_state, int) {
88 | exit := int(C.crypto_generichash_update(
89 | state,
90 | (*C.uchar)(support.BytePointer(in)),
91 | (C.ulonglong)(len(in))))
92 |
93 | return state, exit
94 | }
95 |
96 | func CryptoGenericHashFinal(state *C.struct_crypto_generichash_blake2b_state, outlen int) (*C.struct_crypto_generichash_blake2b_state, []byte, int) {
97 | support.CheckIntInRange(outlen, CryptoGenericHashBytesMin(), CryptoGenericHashBytesMax(), "out")
98 | out := make([]byte, outlen)
99 | exit := int(C.crypto_generichash_final(
100 | state,
101 | (*C.uchar)(&out[0]),
102 | (C.size_t)(outlen)))
103 |
104 | return state, out, exit
105 | }
106 |
--------------------------------------------------------------------------------
/cryptohash/crypto_hash.go:
--------------------------------------------------------------------------------
1 | package cryptohash
2 |
3 | // #cgo pkg-config: libsodium
4 | // #include
5 | // #include
6 | import "C"
7 |
8 | func CryptoHashBytes() int {
9 | return int(C.crypto_hash_bytes())
10 | }
11 |
12 | func CryptoHashPrimitive() string {
13 | return C.GoString(C.crypto_hash_primitive())
14 | }
15 |
16 | func CryptoHash(in []byte) ([]byte, int) {
17 | out := make([]byte, CryptoHashBytes())
18 | exit := int(C.crypto_hash(
19 | (*C.uchar)(&out[0]),
20 | (*C.uchar)(&in[0]),
21 | (C.ulonglong)(len(in))))
22 |
23 | return out, exit
24 | }
25 |
--------------------------------------------------------------------------------
/cryptokdf/crypto_kdf.go:
--------------------------------------------------------------------------------
1 | package cryptokdf
2 |
3 | // #cgo pkg-config: libsodium
4 | // #include
5 | // #include
6 | import "C"
7 | import "github.com/GoKillers/libsodium-go/support"
8 |
9 | func CryptoKdfKeybytes() int {
10 | return int(C.crypto_kdf_keybytes())
11 | }
12 |
13 | func CryptoKdfContextbytes() int {
14 | return int(C.crypto_kdf_contextbytes())
15 | }
16 |
17 | func CryptoKdfBytesMin() int {
18 | return int(C.crypto_kdf_bytes_min())
19 | }
20 |
21 | func CryptoKdfBytesMax() int {
22 | return int(C.crypto_kdf_bytes_max())
23 | }
24 |
25 | func CryptoKdfKeygen() []byte {
26 | k := make([]byte, CryptoKdfKeybytes())
27 | C.crypto_kdf_keygen((*C.uchar)(&k[0]))
28 | return k
29 | }
30 |
31 | func CryptoKdfDeriveFromKey(l int, i uint64, c string, k []byte) ([]byte, int) {
32 | support.CheckSize(k, CryptoKdfKeybytes(), "keybytes")
33 | support.CheckSize([]byte(c), CryptoKdfContextbytes(), "contextbytes")
34 | support.CheckIntInRange(l, CryptoKdfBytesMin(), CryptoKdfBytesMax(), "subkey_len")
35 | out := make([]byte, l)
36 |
37 | exit := int(C.crypto_kdf_derive_from_key(
38 | (*C.uchar)(&out[0]),
39 | (C.size_t)(l),
40 | (C.uint64_t)(i),
41 | C.CString(c),
42 | (*C.uchar)(&k[0])))
43 |
44 | return out, exit
45 | }
46 |
--------------------------------------------------------------------------------
/cryptosecretbox/crypto_secretbox.go:
--------------------------------------------------------------------------------
1 | package secretbox
2 |
3 | // #cgo pkg-config: libsodium
4 | // #include
5 | // #include
6 | import "C"
7 | import "github.com/GoKillers/libsodium-go/support"
8 |
9 | func CryptoSecretBoxKeyBytes() int {
10 | return int(C.crypto_secretbox_keybytes())
11 | }
12 |
13 | func CryptoSecretBoxNonceBytes() int {
14 | return int(C.crypto_secretbox_noncebytes())
15 | }
16 |
17 | func CryptoSecretBoxZeroBytes() int {
18 | return int(C.crypto_secretbox_zerobytes())
19 | }
20 |
21 | func CryptoSecretBoxBoxZeroBytes() int {
22 | return int(C.crypto_secretbox_boxzerobytes())
23 | }
24 |
25 | func CryptoSecretBoxMacBytes() int {
26 | return int(C.crypto_secretbox_macbytes())
27 | }
28 |
29 | func CryptoSecretBoxPrimitive() string {
30 | return C.GoString(C.crypto_secretbox_primitive())
31 | }
32 |
33 | func CryptoSecretBox(m []byte, n []byte, k []byte) ([]byte, int) {
34 | support.CheckSize(n, CryptoSecretBoxNonceBytes(), "nonce")
35 | support.CheckSize(k, CryptoSecretBoxKeyBytes(), "key")
36 | c := make([]byte, len(m)+CryptoSecretBoxMacBytes())
37 | exit := int(C.crypto_secretbox(
38 | (*C.uchar)(&c[0]),
39 | (*C.uchar)(&m[0]),
40 | (C.ulonglong)(len(m)),
41 | (*C.uchar)(&n[0]),
42 | (*C.uchar)(&k[0])))
43 |
44 | return c, exit
45 | }
46 |
47 | func CryptoSecretBoxOpen(c []byte, n []byte, k []byte) ([]byte, int) {
48 | support.CheckSize(n, CryptoSecretBoxNonceBytes(), "nonce")
49 | support.CheckSize(k, CryptoSecretBoxKeyBytes(), "key")
50 | m := make([]byte, len(c)-CryptoSecretBoxMacBytes())
51 | exit := int(C.crypto_secretbox_open(
52 | (*C.uchar)(&m[0]),
53 | (*C.uchar)(&c[0]),
54 | (C.ulonglong)(len(c)),
55 | (*C.uchar)(&n[0]),
56 | (*C.uchar)(&k[0])))
57 |
58 | return m, exit
59 | }
60 |
--------------------------------------------------------------------------------
/cryptosecretbox/crypto_secretbox_easy.go:
--------------------------------------------------------------------------------
1 | package secretbox
2 |
3 | // #cgo pkg-config: libsodium
4 | // #include
5 | // #include
6 | import "C"
7 | import "github.com/GoKillers/libsodium-go/support"
8 |
9 | func CryptoSecretBoxDetached(m []byte, n []byte, k []byte) ([]byte, []byte, int) {
10 | support.CheckSize(n, CryptoSecretBoxNonceBytes(), "nonce")
11 | support.CheckSize(k, CryptoSecretBoxKeyBytes(), "key")
12 | c := make([]byte, len(m))
13 | mac := make([]byte, CryptoSecretBoxMacBytes())
14 | exit := int(C.crypto_secretbox_detached(
15 | (*C.uchar)(&c[0]),
16 | (*C.uchar)(&mac[0]),
17 | (*C.uchar)(&m[0]),
18 | (C.ulonglong)(len(m)),
19 | (*C.uchar)(&n[0]),
20 | (*C.uchar)(&k[0])))
21 |
22 | return c, mac, exit
23 | }
24 |
25 | func CryptoSecretBoxOpenDetached(c []byte, mac []byte, n []byte, k []byte) ([]byte, int) {
26 | support.CheckSize(mac, CryptoSecretBoxMacBytes(), "mac")
27 | support.CheckSize(n, CryptoSecretBoxNonceBytes(), "nonce")
28 | support.CheckSize(k, CryptoSecretBoxKeyBytes(), "key")
29 | m := make([]byte, len(c))
30 | exit := int(C.crypto_secretbox_open_detached(
31 | (*C.uchar)(&m[0]),
32 | (*C.uchar)(&c[0]),
33 | (*C.uchar)(&mac[0]),
34 | (C.ulonglong)(len(c)),
35 | (*C.uchar)(&n[0]),
36 | (*C.uchar)(&k[0])))
37 |
38 | return m, exit
39 | }
40 |
41 | func CryptoSecretBoxEasy(m []byte, n []byte, k []byte) ([]byte, int) {
42 | support.CheckSize(n, CryptoSecretBoxNonceBytes(), "nonce")
43 | support.CheckSize(k, CryptoSecretBoxKeyBytes(), "key")
44 | c := make([]byte, len(m)+CryptoSecretBoxMacBytes())
45 | exit := int(C.crypto_secretbox_easy(
46 | (*C.uchar)(&c[0]),
47 | (*C.uchar)(&m[0]),
48 | (C.ulonglong)(len(m)),
49 | (*C.uchar)(&n[0]),
50 | (*C.uchar)(&k[0])))
51 |
52 | return c, exit
53 | }
54 |
55 | func CryptoSecretBoxOpenEasy(c []byte, n []byte, k []byte) ([]byte, int) {
56 | support.CheckSize(n, CryptoSecretBoxNonceBytes(), "nonce")
57 | support.CheckSize(k, CryptoSecretBoxKeyBytes(), "key")
58 | m := make([]byte, len(c)-CryptoSecretBoxMacBytes())
59 | exit := int(C.crypto_secretbox_open_easy(
60 | (*C.uchar)(&m[0]),
61 | (*C.uchar)(&c[0]),
62 | (C.ulonglong)(len(c)),
63 | (*C.uchar)(&n[0]),
64 | (*C.uchar)(&k[0])))
65 |
66 | return m, exit
67 | }
68 |
--------------------------------------------------------------------------------
/cryptosign/crypto_sign.go:
--------------------------------------------------------------------------------
1 | package cryptosign
2 |
3 | // #cgo pkg-config: libsodium
4 | // #include
5 | // #include
6 | import "C"
7 | import "github.com/GoKillers/libsodium-go/cryptobox"
8 | import "github.com/GoKillers/libsodium-go/support"
9 |
10 | func CryptoSignBytes() int {
11 | return int(C.crypto_sign_bytes())
12 | }
13 |
14 | func CryptoSignSeedBytes() int {
15 | return int(C.crypto_sign_seedbytes())
16 | }
17 |
18 | func CryptoSignPublicKeyBytes() int {
19 | return int(C.crypto_sign_publickeybytes())
20 | }
21 |
22 | func CryptoSignSecretKeyBytes() int {
23 | return int(C.crypto_sign_secretkeybytes())
24 | }
25 |
26 | func CryptoSignPrimitive() string {
27 | return C.GoString(C.crypto_sign_primitive())
28 | }
29 |
30 | func CryptoSignSeedKeyPair(seed []byte) ([]byte, []byte, int) {
31 | support.CheckSize(seed, CryptoSignSeedBytes(), "seed")
32 | sk := make([]byte, CryptoSignSecretKeyBytes())
33 | pk := make([]byte, CryptoSignPublicKeyBytes())
34 | exit := int(C.crypto_sign_seed_keypair(
35 | (*C.uchar)(&pk[0]),
36 | (*C.uchar)(&sk[0]),
37 | (*C.uchar)(&seed[0])))
38 |
39 | return sk, pk, exit
40 | }
41 |
42 | func CryptoSignKeyPair() ([]byte, []byte, int) {
43 | sk := make([]byte, CryptoSignSecretKeyBytes())
44 | pk := make([]byte, CryptoSignPublicKeyBytes())
45 | exit := int(C.crypto_sign_keypair(
46 | (*C.uchar)(&pk[0]),
47 | (*C.uchar)(&sk[0])))
48 |
49 | return sk, pk, exit
50 | }
51 |
52 | func CryptoSign(m []byte, sk []byte) ([]byte, int) {
53 | support.CheckSize(sk, CryptoSignSecretKeyBytes(), "secret key")
54 | sm := make([]byte, len(m)+CryptoSignBytes())
55 | var actualSmSize C.ulonglong
56 |
57 | exit := int(C.crypto_sign(
58 | (*C.uchar)(&sm[0]),
59 | (&actualSmSize),
60 | (*C.uchar)(&m[0]),
61 | (C.ulonglong)(len(m)),
62 | (*C.uchar)(&sk[0])))
63 |
64 | return sm[:actualSmSize], exit
65 | }
66 |
67 | func CryptoSignOpen(sm []byte, pk []byte) ([]byte, int) {
68 | support.CheckSize(pk, CryptoSignPublicKeyBytes(), "public key")
69 | m := make([]byte, len(sm)-CryptoSignBytes())
70 | var actualMSize C.ulonglong
71 |
72 | exit := int(C.crypto_sign_open(
73 | (*C.uchar)(&m[0]),
74 | (&actualMSize),
75 | (*C.uchar)(&sm[0]),
76 | (C.ulonglong)(len(sm)),
77 | (*C.uchar)(&pk[0])))
78 |
79 | return m[:actualMSize], exit
80 | }
81 |
82 | func CryptoSignDetached(m []byte, sk []byte) ([]byte, int) {
83 | support.CheckSize(sk, CryptoSignSecretKeyBytes(), "secret key")
84 | sig := make([]byte, CryptoSignBytes())
85 | var actualSigSize C.ulonglong
86 |
87 | exit := int(C.crypto_sign_detached(
88 | (*C.uchar)(&sig[0]),
89 | (&actualSigSize),
90 | (*C.uchar)(&m[0]),
91 | (C.ulonglong)(len(m)),
92 | (*C.uchar)(&sk[0])))
93 |
94 | return sig[:actualSigSize], exit
95 | }
96 |
97 | func CryptoSignVerifyDetached(sig []byte, m []byte, pk []byte) int {
98 | support.CheckSize(sig, CryptoSignBytes(), "signature")
99 | support.CheckSize(pk, CryptoSignPublicKeyBytes(), "public key")
100 |
101 | return int(C.crypto_sign_verify_detached(
102 | (*C.uchar)(&sig[0]),
103 | (*C.uchar)(&m[0]),
104 | (C.ulonglong)(len(m)),
105 | (*C.uchar)(&pk[0])))
106 | }
107 |
108 | func CryptoSignEd25519PkToCurve25519(pkEd25519 []byte) ([]byte, int) {
109 | support.CheckSize(pkEd25519, CryptoSignPublicKeyBytes(), "public key")
110 | pkCurve25519 := make([]byte, cryptobox.CryptoBoxPublicKeyBytes())
111 |
112 | exit := int(C.crypto_sign_ed25519_pk_to_curve25519(
113 | (*C.uchar)(&pkCurve25519[0]),
114 | (*C.uchar)(&pkEd25519[0])))
115 |
116 | return pkCurve25519, exit
117 | }
118 |
119 | func CryptoSignEd25519SkToCurve25519(skEd25519 []byte) ([]byte, int) {
120 | support.CheckSize(skEd25519, CryptoSignSecretKeyBytes(), "secret key")
121 | skCurve25519 := make([]byte, cryptobox.CryptoBoxSecretKeyBytes())
122 |
123 | exit := int(C.crypto_sign_ed25519_sk_to_curve25519(
124 | (*C.uchar)(&skCurve25519[0]),
125 | (*C.uchar)(&skEd25519[0])))
126 |
127 | return skCurve25519, exit
128 | }
129 |
--------------------------------------------------------------------------------
/cryptostream/crypto_stream.go:
--------------------------------------------------------------------------------
1 | package cryptostream
2 |
3 | // #cgo pkg-config: libsodium
4 | // #include
5 | // #include
6 | import "C"
7 | import "github.com/GoKillers/libsodium-go/support"
8 |
9 | func CryptoStreamKeyBytes() int {
10 | return int(C.crypto_stream_keybytes())
11 | }
12 |
13 | func CryptoStreamNonceBytes() int {
14 | return int(C.crypto_stream_noncebytes())
15 | }
16 |
17 | func CryptoStreamPrimitive() string {
18 | return C.GoString(C.crypto_stream_primitive())
19 | }
20 |
21 | func CryptoStream(clen int, n []byte, k []byte) ([]byte, int) {
22 | support.CheckSize(n, CryptoStreamNonceBytes(), "nonce")
23 | support.CheckSize(k, CryptoStreamKeyBytes(), "key")
24 | return CryptoStreamXSalsa20(clen, n, k)
25 | }
26 |
27 | func CryptoStreamXOR(m []byte, n []byte, k []byte) ([]byte, int) {
28 | support.CheckSize(n, CryptoStreamNonceBytes(), "nonce")
29 | support.CheckSize(k, CryptoStreamKeyBytes(), "key")
30 | return CryptoStreamXSalsa20XOR(m, n, k)
31 | }
32 |
--------------------------------------------------------------------------------
/cryptostream/crypto_stream_chacha20.go:
--------------------------------------------------------------------------------
1 | package cryptostream
2 |
3 | // #cgo pkg-config: libsodium
4 | // #include
5 | // #include
6 | import "C"
7 | import "github.com/GoKillers/libsodium-go/support"
8 |
9 | func CryptoStreamChaCha20KeyBytes() int {
10 | return int(C.crypto_stream_chacha20_keybytes())
11 | }
12 |
13 | func CryptoStreamChaCha20NonceBytes() int {
14 | return int(C.crypto_stream_chacha20_noncebytes())
15 | }
16 |
17 | func CryptoStreamChaCha20(clen int, n []byte, k []byte) ([]byte, int) {
18 | support.CheckSize(n, CryptoStreamChaCha20NonceBytes(), "nonce")
19 | support.CheckSize(k, CryptoStreamChaCha20KeyBytes(), "key")
20 | c := make([]byte, clen)
21 | exit := int(C.crypto_stream_chacha20(
22 | (*C.uchar)(&c[0]),
23 | (C.ulonglong)(clen),
24 | (*C.uchar)(&n[0]),
25 | (*C.uchar)(&k[0])))
26 |
27 | return c, exit
28 | }
29 |
30 | func CryptoStreamChaCha20XOR(m []byte, n []byte, k []byte) ([]byte, int) {
31 | support.CheckSize(n, CryptoStreamChaCha20NonceBytes(), "nonce")
32 | support.CheckSize(k, CryptoStreamChaCha20KeyBytes(), "key")
33 | c := make([]byte, len(m))
34 | exit := int(C.crypto_stream_chacha20_xor(
35 | (*C.uchar)(&c[0]),
36 | (*C.uchar)(&m[0]),
37 | (C.ulonglong)(len(m)),
38 | (*C.uchar)(&n[0]),
39 | (*C.uchar)(&k[0])))
40 |
41 | return c, exit
42 | }
43 |
44 | func CryptoStreamChaCha20XORIC(m []byte, n []byte, ic uint64, k []byte) ([]byte, int) {
45 | support.CheckSize(n, CryptoStreamChaCha20NonceBytes(), "nonce")
46 | support.CheckSize(k, CryptoStreamChaCha20KeyBytes(), "key")
47 |
48 | c := make([]byte, len(m))
49 | exit := int(C.crypto_stream_chacha20_xor_ic(
50 | (*C.uchar)(&c[0]),
51 | (*C.uchar)(&m[0]),
52 | (C.ulonglong)(len(m)),
53 | (*C.uchar)(&n[0]),
54 | (C.uint64_t)(ic),
55 | (*C.uchar)(&k[0])))
56 |
57 | return c, exit
58 | }
59 |
60 | func CryptoStreamChaCha20Keygen() []byte {
61 | c := make([]byte, CryptoStreamChaCha20KeyBytes())
62 | C.crypto_stream_chacha20_keygen((*C.uchar)(&c[0]))
63 | return c
64 | }
65 |
66 | func CryptoStreamChaCha20IETFKeyBytes() int {
67 | return int(C.crypto_stream_chacha20_ietf_keybytes())
68 | }
69 |
70 | func CryptoStreamChaCha20IETFNonceBytes() int {
71 | return int(C.crypto_stream_chacha20_ietf_noncebytes())
72 | }
73 |
74 | func CryptoStreamChaCha20IETF(clen int, n []byte, k []byte) ([]byte, int) {
75 | support.CheckSize(n, CryptoStreamChaCha20IETFNonceBytes(), "nonce")
76 | support.CheckSize(k, CryptoStreamChaCha20IETFKeyBytes(), "key")
77 | c := make([]byte, clen)
78 | exit := int(C.crypto_stream_chacha20_ietf(
79 | (*C.uchar)(&c[0]),
80 | (C.ulonglong)(clen),
81 | (*C.uchar)(&n[0]),
82 | (*C.uchar)(&k[0])))
83 |
84 | return c, exit
85 | }
86 |
87 | func CryptoStreamChaCha20IETFXOR(m []byte, n []byte, k []byte) ([]byte, int) {
88 | support.CheckSize(n, CryptoStreamChaCha20IETFNonceBytes(), "nonce")
89 | support.CheckSize(k, CryptoStreamChaCha20IETFKeyBytes(), "key")
90 | c := make([]byte, len(m))
91 | exit := int(C.crypto_stream_chacha20_ietf_xor(
92 | (*C.uchar)(&c[0]),
93 | (*C.uchar)(&m[0]),
94 | (C.ulonglong)(len(m)),
95 | (*C.uchar)(&n[0]),
96 | (*C.uchar)(&k[0])))
97 |
98 | return c, exit
99 | }
100 |
101 | func CryptoStreamChaCha20IETFXORIC(m []byte, n []byte, ic uint32, k []byte) ([]byte, int) {
102 | support.CheckSize(n, CryptoStreamChaCha20IETFNonceBytes(), "nonce")
103 | support.CheckSize(k, CryptoStreamChaCha20IETFKeyBytes(), "key")
104 |
105 | c := make([]byte, len(m))
106 | exit := int(C.crypto_stream_chacha20_ietf_xor_ic(
107 | (*C.uchar)(&c[0]),
108 | (*C.uchar)(&m[0]),
109 | (C.ulonglong)(len(m)),
110 | (*C.uchar)(&n[0]),
111 | (C.uint32_t)(ic),
112 | (*C.uchar)(&k[0])))
113 |
114 | return c, exit
115 | }
116 |
117 | func CryptoStreamChaCha20IETFKeygen() []byte {
118 | c := make([]byte, CryptoStreamChaCha20IETFKeyBytes())
119 | C.crypto_stream_chacha20_ietf_keygen((*C.uchar)(&c[0]))
120 | return c
121 | }
122 |
--------------------------------------------------------------------------------
/cryptostream/crypto_stream_salsa20.go:
--------------------------------------------------------------------------------
1 | package cryptostream
2 |
3 | // #cgo pkg-config: libsodium
4 | // #include
5 | // #include
6 | import "C"
7 | import "github.com/GoKillers/libsodium-go/support"
8 |
9 | func CryptoStreamSalsa20KeyBytes() int {
10 | return int(C.crypto_stream_salsa20_keybytes())
11 | }
12 |
13 | func CryptoStreamSalsa20NonceBytes() int {
14 | return int(C.crypto_stream_salsa20_noncebytes())
15 | }
16 |
17 | func CryptoStreamSalsa20(clen int, n []byte, k []byte) ([]byte, int) {
18 | support.CheckSize(n, CryptoStreamSalsa20NonceBytes(), "nonce")
19 | support.CheckSize(k, CryptoStreamSalsa20KeyBytes(), "key")
20 | c := make([]byte, clen)
21 | exit := int(C.crypto_stream_salsa20(
22 | (*C.uchar)(&c[0]),
23 | (C.ulonglong)(clen),
24 | (*C.uchar)(&n[0]),
25 | (*C.uchar)(&k[0])))
26 |
27 | return c, exit
28 | }
29 |
30 | func CryptoStreamSalsa20XOR(m []byte, n []byte, k []byte) ([]byte, int) {
31 | support.CheckSize(n, CryptoStreamSalsa20NonceBytes(), "nonce")
32 | support.CheckSize(k, CryptoStreamSalsa20KeyBytes(), "key")
33 | c := make([]byte, len(m))
34 | exit := int(C.crypto_stream_salsa20_xor(
35 | (*C.uchar)(&c[0]),
36 | (*C.uchar)(&m[0]),
37 | (C.ulonglong)(len(m)),
38 | (*C.uchar)(&n[0]),
39 | (*C.uchar)(&k[0])))
40 |
41 | return c, exit
42 | }
43 |
44 | func CryptoStreamSalsa20XORIC(m []byte, n []byte, ic uint64, k []byte) ([]byte, int) {
45 | support.CheckSize(n, CryptoStreamSalsa20NonceBytes(), "nonce")
46 | support.CheckSize(k, CryptoStreamSalsa20KeyBytes(), "key")
47 |
48 | c := make([]byte, len(m))
49 | exit := int(C.crypto_stream_salsa20_xor_ic(
50 | (*C.uchar)(&c[0]),
51 | (*C.uchar)(&m[0]),
52 | (C.ulonglong)(len(m)),
53 | (*C.uchar)(&n[0]),
54 | (C.uint64_t)(ic),
55 | (*C.uchar)(&k[0])))
56 |
57 | return c, exit
58 | }
59 |
60 | func CryptoStreamSalsa20Keygen() []byte {
61 | c := make([]byte, CryptoStreamSalsa20KeyBytes())
62 | C.crypto_stream_salsa20_keygen((*C.uchar)(&c[0]))
63 | return c
64 | }
65 |
--------------------------------------------------------------------------------
/cryptostream/crypto_stream_salsa2012.go:
--------------------------------------------------------------------------------
1 | package cryptostream
2 |
3 | // #cgo pkg-config: libsodium
4 | // #include
5 | // #include
6 | import "C"
7 | import "github.com/GoKillers/libsodium-go/support"
8 |
9 | func CryptoStreamSalsa2012KeyBytes() int {
10 | return int(C.crypto_stream_salsa2012_keybytes())
11 | }
12 |
13 | func CryptoStreamSalsa2012NonceBytes() int {
14 | return int(C.crypto_stream_salsa2012_noncebytes())
15 | }
16 |
17 | func CryptoStreamSalsa2012(clen int, n []byte, k []byte) ([]byte, int) {
18 | support.CheckSize(n, CryptoStreamSalsa2012NonceBytes(), "nonce")
19 | support.CheckSize(k, CryptoStreamSalsa2012KeyBytes(), "key")
20 | c := make([]byte, clen)
21 | exit := int(C.crypto_stream_salsa2012(
22 | (*C.uchar)(&c[0]),
23 | (C.ulonglong)(clen),
24 | (*C.uchar)(&n[0]),
25 | (*C.uchar)(&k[0])))
26 |
27 | return c, exit
28 | }
29 |
30 | func CryptoStreamSalsa2012XOR(m []byte, n []byte, k []byte) ([]byte, int) {
31 | support.CheckSize(n, CryptoStreamSalsa2012NonceBytes(), "nonce")
32 | support.CheckSize(k, CryptoStreamSalsa2012KeyBytes(), "key")
33 | c := make([]byte, len(m))
34 | exit := int(C.crypto_stream_salsa2012_xor(
35 | (*C.uchar)(&c[0]),
36 | (*C.uchar)(&m[0]),
37 | (C.ulonglong)(len(m)),
38 | (*C.uchar)(&n[0]),
39 | (*C.uchar)(&k[0])))
40 |
41 | return c, exit
42 | }
43 |
44 | func CryptoStreamSalsa2012Keygen() []byte {
45 | c := make([]byte, CryptoStreamSalsa2012KeyBytes())
46 | C.crypto_stream_salsa2012_keygen((*C.uchar)(&c[0]))
47 | return c
48 | }
49 |
--------------------------------------------------------------------------------
/cryptostream/crypto_stream_salsa208.go:
--------------------------------------------------------------------------------
1 | package cryptostream
2 |
3 | // #cgo pkg-config: libsodium
4 | // #include
5 | // #include
6 | import "C"
7 | import "github.com/GoKillers/libsodium-go/support"
8 |
9 | func CryptoStreamSalsa208KeyBytes() int {
10 | return int(C.crypto_stream_salsa208_keybytes())
11 | }
12 |
13 | func CryptoStreamSalsa208NonceBytes() int {
14 | return int(C.crypto_stream_salsa208_noncebytes())
15 | }
16 |
17 | func CryptoStreamSalsa208(clen int, n []byte, k []byte) ([]byte, int) {
18 | support.CheckSize(n, CryptoStreamSalsa208NonceBytes(), "nonce")
19 | support.CheckSize(k, CryptoStreamSalsa208KeyBytes(), "key")
20 | c := make([]byte, clen)
21 | exit := int(C.crypto_stream_salsa208(
22 | (*C.uchar)(&c[0]),
23 | (C.ulonglong)(clen),
24 | (*C.uchar)(&n[0]),
25 | (*C.uchar)(&k[0])))
26 |
27 | return c, exit
28 | }
29 |
30 | func CryptoStreamSalsa208XOR(m []byte, n []byte, k []byte) ([]byte, int) {
31 | support.CheckSize(n, CryptoStreamSalsa208NonceBytes(), "nonce")
32 | support.CheckSize(k, CryptoStreamSalsa208KeyBytes(), "key")
33 | c := make([]byte, len(m))
34 | exit := int(C.crypto_stream_salsa208_xor(
35 | (*C.uchar)(&c[0]),
36 | (*C.uchar)(&m[0]),
37 | (C.ulonglong)(len(m)),
38 | (*C.uchar)(&n[0]),
39 | (*C.uchar)(&k[0])))
40 |
41 | return c, exit
42 | }
43 |
44 | func CryptoStreamSalsa208Keygen() []byte {
45 | c := make([]byte, CryptoStreamSalsa208KeyBytes())
46 | C.crypto_stream_salsa208_keygen((*C.uchar)(&c[0]))
47 | return c
48 | }
49 |
--------------------------------------------------------------------------------
/cryptostream/crypto_stream_xchacha20.go:
--------------------------------------------------------------------------------
1 | package cryptostream
2 |
3 | // #cgo pkg-config: libsodium
4 | // #include
5 | // #include
6 | import "C"
7 | import "github.com/GoKillers/libsodium-go/support"
8 |
9 | func CryptoStreamXChaCha20KeyBytes() int {
10 | return int(C.crypto_stream_xchacha20_keybytes())
11 | }
12 |
13 | func CryptoStreamXChaCha20NonceBytes() int {
14 | return int(C.crypto_stream_xchacha20_noncebytes())
15 | }
16 |
17 | func CryptoStreamXChaCha20(clen int, n []byte, k []byte) ([]byte, int) {
18 | support.CheckSize(n, CryptoStreamXChaCha20NonceBytes(), "nonce")
19 | support.CheckSize(k, CryptoStreamXChaCha20KeyBytes(), "key")
20 | c := make([]byte, clen)
21 | exit := int(C.crypto_stream_xchacha20(
22 | (*C.uchar)(&c[0]),
23 | (C.ulonglong)(clen),
24 | (*C.uchar)(&n[0]),
25 | (*C.uchar)(&k[0])))
26 |
27 | return c, exit
28 | }
29 |
30 | func CryptoStreamXChaCha20XOR(m []byte, n []byte, k []byte) ([]byte, int) {
31 | support.CheckSize(n, CryptoStreamXChaCha20NonceBytes(), "nonce")
32 | support.CheckSize(k, CryptoStreamXChaCha20KeyBytes(), "key")
33 | c := make([]byte, len(m))
34 | exit := int(C.crypto_stream_xchacha20_xor(
35 | (*C.uchar)(&c[0]),
36 | (*C.uchar)(&m[0]),
37 | (C.ulonglong)(len(m)),
38 | (*C.uchar)(&n[0]),
39 | (*C.uchar)(&k[0])))
40 |
41 | return c, exit
42 | }
43 |
44 | func CryptoStreamXChaCha20XORIC(m []byte, n []byte, ic uint64, k []byte) ([]byte, int) {
45 | support.CheckSize(n, CryptoStreamXChaCha20NonceBytes(), "nonce")
46 | support.CheckSize(k, CryptoStreamXChaCha20KeyBytes(), "key")
47 |
48 | c := make([]byte, len(m))
49 | exit := int(C.crypto_stream_xchacha20_xor_ic(
50 | (*C.uchar)(&c[0]),
51 | (*C.uchar)(&m[0]),
52 | (C.ulonglong)(len(m)),
53 | (*C.uchar)(&n[0]),
54 | (C.uint64_t)(ic),
55 | (*C.uchar)(&k[0])))
56 |
57 | return c, exit
58 | }
59 |
60 | func CryptoStreamXChaCha20Keygen() []byte {
61 | c := make([]byte, CryptoStreamXChaCha20KeyBytes())
62 | C.crypto_stream_xchacha20_keygen((*C.uchar)(&c[0]))
63 | return c
64 | }
65 |
--------------------------------------------------------------------------------
/cryptostream/crypto_stream_xsalsa20.go:
--------------------------------------------------------------------------------
1 | package cryptostream
2 |
3 | // #cgo pkg-config: libsodium
4 | // #include
5 | // #include
6 | import "C"
7 | import "github.com/GoKillers/libsodium-go/support"
8 |
9 | func CryptoStreamXSalsa20KeyBytes() int {
10 | return int(C.crypto_stream_xsalsa20_keybytes())
11 | }
12 |
13 | func CryptoStreamXSalsa20NonceBytes() int {
14 | return int(C.crypto_stream_xsalsa20_noncebytes())
15 | }
16 |
17 | func CryptoStreamXSalsa20(clen int, n []byte, k []byte) ([]byte, int) {
18 | support.CheckSize(n, CryptoStreamXSalsa20NonceBytes(), "nonce")
19 | support.CheckSize(k, CryptoStreamXSalsa20KeyBytes(), "key")
20 | c := make([]byte, clen)
21 | exit := int(C.crypto_stream_xsalsa20(
22 | (*C.uchar)(&c[0]),
23 | (C.ulonglong)(clen),
24 | (*C.uchar)(&n[0]),
25 | (*C.uchar)(&k[0])))
26 |
27 | return c, exit
28 | }
29 |
30 | func CryptoStreamXSalsa20XOR(m []byte, n []byte, k []byte) ([]byte, int) {
31 | support.CheckSize(n, CryptoStreamXSalsa20NonceBytes(), "nonce")
32 | support.CheckSize(k, CryptoStreamXSalsa20KeyBytes(), "key")
33 | c := make([]byte, len(m))
34 | exit := int(C.crypto_stream_xsalsa20_xor(
35 | (*C.uchar)(&c[0]),
36 | (*C.uchar)(&m[0]),
37 | (C.ulonglong)(len(m)),
38 | (*C.uchar)(&n[0]),
39 | (*C.uchar)(&k[0])))
40 |
41 | return c, exit
42 | }
43 |
44 | func CryptoStreamXSalsa20XORIC(m []byte, n []byte, ic uint64, k []byte) ([]byte, int) {
45 | support.CheckSize(n, CryptoStreamXSalsa20NonceBytes(), "nonce")
46 | support.CheckSize(k, CryptoStreamXSalsa20KeyBytes(), "key")
47 |
48 | c := make([]byte, len(m))
49 | exit := int(C.crypto_stream_xsalsa20_xor_ic(
50 | (*C.uchar)(&c[0]),
51 | (*C.uchar)(&m[0]),
52 | (C.ulonglong)(len(m)),
53 | (*C.uchar)(&n[0]),
54 | (C.uint64_t)(ic),
55 | (*C.uchar)(&k[0])))
56 |
57 | return c, exit
58 | }
59 |
60 | func CryptoStreamXSalsa20Keygen() []byte {
61 | c := make([]byte, CryptoStreamXSalsa20KeyBytes())
62 | C.crypto_stream_xsalsa20_keygen((*C.uchar)(&c[0]))
63 | return c
64 | }
65 |
--------------------------------------------------------------------------------
/randombytes/randombytes.go:
--------------------------------------------------------------------------------
1 | package randombytes
2 |
3 | // #cgo pkg-config: libsodium
4 | // #include
5 | // #include
6 | import "C"
7 | import "github.com/GoKillers/libsodium-go/support"
8 | import "unsafe"
9 |
10 | // RandomBytesSeedBytes returns the number of bytes required
11 | // for seeding RandomBytesBufDeterministic.
12 | func RandomBytesSeedBytes() int {
13 | return int(C.randombytes_seedbytes())
14 | }
15 |
16 | // RandomBytes returns a specified number of random bytes.
17 | // It is essentially a wrapper around RandomBytesBuf for convenience.
18 | // Note that this behaviour is different than in NaCl and libsodium,
19 | // where this function behaves the same as RandomBytesBuf.
20 | func RandomBytes(size int) []byte {
21 | buf := make([]byte, size)
22 | RandomBytesBuf(buf)
23 | return buf
24 | }
25 |
26 | // RandomBytesBuf fills a buffer with random bytes.
27 | func RandomBytesBuf(buf []byte) {
28 | if len(buf) > 0 {
29 | C.randombytes_buf(unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
30 | }
31 | }
32 |
33 | // RandomBytesBufDeterministic fills a buffer with bytes that are
34 | // indistinguishable from random bytes without knowing seed.
35 | func RandomBytesBufDeterministic(buf []byte, seed []byte) {
36 | support.CheckSize(seed, RandomBytesSeedBytes(), "seed")
37 | if len(buf) > 0 {
38 | C.randombytes_buf_deterministic(
39 | unsafe.Pointer(&buf[0]),
40 | C.size_t(len(buf)),
41 | (*C.uchar)(&seed[0]))
42 | }
43 | }
44 |
45 | // RandomBytesRandom returns a random 32 bit unsigned integer.
46 | func RandomBytesRandom() uint32 {
47 | return uint32(C.randombytes_random())
48 | }
49 |
50 | // RandomBytesUniform returns a random number between 0 and an upper bound.
51 | // The generated bytes have a uniform distribution between 0 and the upper bound.
52 | func RandomBytesUniform(upperBound uint32) uint32 {
53 | return uint32(C.randombytes_uniform(C.uint32_t(upperBound)))
54 | }
55 |
56 | // RandomBytesStir reseeds the random number generator.
57 | func RandomBytesStir() {
58 | C.randombytes_stir()
59 | }
60 |
61 | // RandomBytesClose deallocates the resources used by the random number generator.
62 | func RandomBytesClose() {
63 | C.randombytes_close()
64 | }
65 |
66 | // RandomBytesSetImplementation sets the implementation of the random number generator.
67 | func RandomBytesSetImplementation(impl *C.struct_randombytes_implementation) int {
68 | return int(C.randombytes_set_implementation(impl))
69 | }
70 |
71 | // RandomBytesImplementationName returns the name of the random number
72 | // generator that is being used.
73 | func RandomBytesImplementationName() string {
74 | return C.GoString(C.randombytes_implementation_name())
75 | }
76 |
77 | // RandomBytesSalsa20Implementation contains a pointer to C.randombytes_salsa20_implementation
78 | // This means that it can be used as an argument to RandomBytesSetImplementation
79 | var RandomBytesSalsa20Implementation *C.struct_randombytes_implementation = &C.randombytes_salsa20_implementation
80 |
81 | // RandomBytesSysRandomImplementation contains a pointer to C.randombytes_sysrandom_implementation
82 | // This means that it can be used as an argument to RandomBytesSetImplementation
83 | var RandomBytesSysRandomImplementation *C.struct_randombytes_implementation = &C.randombytes_sysrandom_implementation
84 |
--------------------------------------------------------------------------------
/scalarmult/crypto_scalarmult.go:
--------------------------------------------------------------------------------
1 | package scalarmult
2 |
3 | // #cgo pkg-config: libsodium
4 | // #include
5 | // #include
6 | import "C"
7 | import "github.com/GoKillers/libsodium-go/support"
8 |
9 | func CryptoScalarmultBytes() int {
10 | return int(C.crypto_scalarmult_bytes())
11 | }
12 |
13 | func CryptoScalarmultScalarBytes() int {
14 | return int(C.crypto_scalarmult_scalarbytes())
15 | }
16 |
17 | func CryptoScalarmultPrimitive() string {
18 | return C.GoString(C.crypto_scalarmult_primitive())
19 | }
20 |
21 | func CryptoScalarmultBase(n []byte) ([]byte, int) {
22 | support.CheckSize(n, CryptoScalarmultScalarBytes(), "secret key")
23 | q := make([]byte, CryptoScalarmultBytes())
24 | var exit C.int
25 |
26 | exit = C.crypto_scalarmult_base(
27 | (*C.uchar)(&q[0]),
28 | (*C.uchar)(&n[0]))
29 |
30 | return q, int(exit)
31 | }
32 |
33 | func CryptoScalarMult(n []byte, p []byte) ([]byte, int) {
34 | support.CheckSize(n, CryptoScalarmultScalarBytes(), "secret key")
35 | support.CheckSize(p, CryptoScalarmultScalarBytes(), "public key")
36 | q := make([]byte, CryptoScalarmultBytes())
37 | var exit C.int
38 | exit = C.crypto_scalarmult(
39 | (*C.uchar)(&q[0]),
40 | (*C.uchar)(&n[0]),
41 | (*C.uchar)(&p[0]))
42 |
43 | return q, int(exit)
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/sodium/core.go:
--------------------------------------------------------------------------------
1 | package sodium
2 |
3 | import "fmt"
4 |
5 | // #cgo pkg-config: libsodium
6 | // #include
7 | // #include
8 | import "C"
9 |
10 | func Init() {
11 | result := int(C.sodium_init())
12 | if result != 0 {
13 | panic(fmt.Sprintf("Sodium initialization failed, result code %d.",
14 | result))
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/sodium/runtime.go:
--------------------------------------------------------------------------------
1 | package sodium
2 |
3 | // #cgo pkg-config: libsodium
4 | // #include
5 | // #include
6 | import "C"
7 |
8 | func RuntimeHasNeon() bool {
9 | return C.sodium_runtime_has_neon() != 0
10 | }
11 |
12 | func RuntimeHasSse2() bool {
13 | return C.sodium_runtime_has_sse2() != 0
14 | }
15 |
16 | func RuntimeHasSse3() bool {
17 | return C.sodium_runtime_has_sse3() != 0
18 | }
19 |
--------------------------------------------------------------------------------
/sodium/utils.go:
--------------------------------------------------------------------------------
1 | package sodium
2 |
3 | import "fmt"
4 | import "unsafe"
5 |
6 | // #cgo pkg-config: libsodium
7 | // #include
8 | // #include
9 | import "C"
10 |
11 | func MemZero(buff1 []byte) {
12 | if len(buff1) > 0 {
13 | C.sodium_memzero(unsafe.Pointer(&buff1[0]), C.size_t(len(buff1)))
14 | }
15 | }
16 |
17 | func MemCmp(buff1, buff2 []byte, length int) int {
18 | if length >= len(buff1) || length >= len(buff2) {
19 | panic(fmt.Sprintf("Attempt to compare more bytes (%d) than provided "+
20 | "(%d, %d)", length, len(buff1), len(buff2)))
21 | }
22 | return int(C.sodium_memcmp(unsafe.Pointer(&buff1[0]),
23 | unsafe.Pointer(&buff2[0]),
24 | C.size_t(length)))
25 | }
26 |
27 | func Bin2hex(bin []byte) string {
28 | maxlen := len(bin)*2 + 1
29 | binPtr := (*C.uchar)(unsafe.Pointer(&bin[0]))
30 | buf := (*C.char)(C.malloc(C.size_t(maxlen)))
31 | defer C.free(unsafe.Pointer(buf))
32 |
33 | C.sodium_bin2hex(buf, C.size_t(maxlen), binPtr, C.size_t(len(bin)))
34 |
35 | return C.GoString(buf)
36 | }
37 |
--------------------------------------------------------------------------------
/sodium/version.go:
--------------------------------------------------------------------------------
1 | package sodium
2 |
3 | // #cgo pkg-config: libsodium
4 | // #include
5 | // #include
6 | import "C"
7 |
8 | // VersionString returns the libsodium version string
9 | func VersionString() string {
10 | return C.GoString(C.sodium_version_string())
11 | }
12 |
13 | // LibraryVersionMajor returns the library major version number
14 | func LibraryVersionMajor() int {
15 | return int(C.sodium_library_version_major())
16 | }
17 |
18 | // LibraryVersionMinor returns the library minor version number
19 | func LibraryVersionMinor() int {
20 | return int(C.sodium_library_version_minor())
21 | }
22 |
23 | // LibraryMinimal returns true for a minimal build
24 | func LibraryMinimal() bool {
25 | return int(C.sodium_library_minimal()) != 0
26 | }
27 |
--------------------------------------------------------------------------------
/sodium/version_test.go:
--------------------------------------------------------------------------------
1 | package sodium
2 |
3 | import (
4 | "testing"
5 | "strings"
6 | )
7 |
8 | func TestSodiumVersion(t *testing.T) {
9 | str := VersionString()
10 | maj := LibraryVersionMajor()
11 | min := LibraryVersionMinor()
12 | slm := LibraryMinimal()
13 |
14 | t.Logf("Sodium version: %s\n", str)
15 | t.Logf("Sodium library version: %v.%v", maj, min)
16 | t.Logf("Minimal: %v", slm)
17 |
18 | version := strings.Split(VersionString(), ".")
19 | if len(version) != 3 {
20 | t.Error("Sodium version should consist of three components")
21 | }
22 |
23 | if maj <= 0 || maj > 100 {
24 | t.Errorf("Suspicious library version major: %v", maj)
25 | }
26 |
27 | if min <= 0 || min > 100 {
28 | t.Errorf("Suspicious library version minor: %v", min)
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/support/error.go:
--------------------------------------------------------------------------------
1 | package support
2 |
3 | import "strconv"
4 |
5 | // KeySizeError is an error that occurs when a key has an incorrect length.
6 | type KeySizeError int
7 |
8 | func (k KeySizeError) Error() string {
9 | return "invalid key size " + strconv.Itoa(int(k))
10 | }
11 |
12 | // NonceSizeError is an error that occurs when a nonce has an incorrect length.
13 | type NonceSizeError int
14 |
15 | func (k NonceSizeError) Error() string {
16 | return "invalid nonce size " + strconv.Itoa(int(k))
17 | }
18 |
19 | // NilPointerError is an error that occurs when a pointer is a nil pointer
20 | type NilPointerError string
21 |
22 | func (k NilPointerError) Error() string {
23 | return string(k) + " is a nil pointer"
24 | }
25 |
26 | // VerificationError is an error that occurs when the verification of
27 | // a signature or authentication tag fails.
28 | type VerificationError struct {}
29 |
30 | func (k VerificationError) Error() string {
31 | return "verification failed"
32 | }
33 |
--------------------------------------------------------------------------------
/support/support.go:
--------------------------------------------------------------------------------
1 | // Package support implements support functions and errors that are used by by other libsodium-go packages.
2 | package support
3 |
4 | import (
5 | "fmt"
6 | "unsafe"
7 | )
8 |
9 | // CheckSize checks if the length of a byte slice is equal to the expected length,
10 | // and panics when this is not the case.
11 | func CheckSize(buf []byte, expected int, descrip string) {
12 | if len(buf) != expected {
13 | panic(fmt.Sprintf("Incorrect %s buffer size, expected (%d), got (%d).", descrip, expected, len(buf)))
14 | }
15 | }
16 |
17 | // CheckSizeMin checks if the length of a byte slice is greater or equal than a minimum length,
18 | // and panics when this is not the case.
19 | func CheckSizeMin(buf []byte, min int, descrip string) {
20 | if len(buf) < min {
21 | panic(fmt.Sprintf("Incorrect %s buffer size, expected (>%d), got (%d).", descrip, min, len(buf)))
22 | }
23 | }
24 |
25 | // CheckIntInRange checks if the size of an integer is between a lower and upper boundaries.
26 | func CheckIntInRange(n int, min int, max int, descrip string) {
27 | if n < min || n > max {
28 | panic(fmt.Sprintf("Incorrect %s size, expected (%d - %d), got (%d).", descrip, min, max, n))
29 | }
30 | }
31 |
32 | // CheckSizeInRange checks if the length of a byte slice is between a lower and upper boundaries.
33 | func CheckSizeInRange(buf []byte, min int, max int, descrip string) {
34 | if len(buf) < min || len(buf) > max {
35 | panic(fmt.Sprintf("Incorrect %s buffer size, expected (%d - %d), got (%d).", descrip, min, max, len(buf)))
36 | }
37 | }
38 |
39 | // CheckSizeGreaterOrEqual checks if the length of a byte slice is greater or equal to that of a second byte slice.
40 | func CheckSizeGreaterOrEqual(a, b []byte, aDescription, bDescription string) {
41 | if len(a) < len(b) {
42 | panic(fmt.Sprintf("%s smaller than %s", aDescription, bDescription))
43 | }
44 | }
45 |
46 | // NilPanic is a shorthand that results in a panic when called with true.
47 | func NilPanic(t bool, description string) {
48 | if t {
49 | panic(description + " is a nil pointer")
50 | }
51 | }
52 |
53 | // BytePointer returns a pointer to the start of a byte slice, or nil when the slice is empty.
54 | func BytePointer(b []byte) *uint8 {
55 | if len(b) > 0 {
56 | return &b[0]
57 | } else {
58 | return nil
59 | }
60 | }
61 |
62 | // AlignedSlice returns a memory aligned slice
63 | func AlignedSlice(size, alignment int) []byte {
64 | slice := make([]byte, size+alignment)
65 | offset := alignment - int(uintptr(unsafe.Pointer(&slice[0])))%alignment
66 | return slice[offset : offset+size]
67 | }
68 |
--------------------------------------------------------------------------------