├── 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 | 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 | --------------------------------------------------------------------------------