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...)
----------------
- Stephen Chavez (@redragonx)
- Graham Smith (@neuegram)
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]
}