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