NAME
Sodium::FFI - FFI implementation of libsodium
SYNOPSIS
use strict;
use warnings;
use v5.34;
use Sodium::FFI ();
my $text = "1234";
my $padded = Sodium::FFI::pad($text, 16);
say Sodium::FFI::unpad($padded);
DESCRIPTION
Sodium::FFI is a set of Perl bindings for the LibSodium
C library. These bindings have been created
using FFI via FFI::Platypus to make building and maintaining the
bindings easier than was done via Crypt::NaCl::Sodium. While we also
intend to fix up Crypt::NaCl::Sodium so that it can use newer versions
of LibSodium, the FFI method is faster to build and release.
Crypto Auth Functions
LibSodium provides a few Crypto Auth Functions
to encrypt and verify messages with a key.
crypto_auth
use Sodium::FFI qw(randombytes_buf crypto_auth crypto_auth_keygen);
# First, let's create a key
my $key = crypto_auth_keygen();
# let's encrypt 12 bytes of random data... for fun
my $message = randombytes_buf(12);
my $encrypted_bytes = crypto_auth($message, $key);
say $encrypted_bytes;
The crypto_auth
function encrypts a message using a secret key and returns
that message as a string of bytes.
crypto_auth_verify
use Sodium::FFI qw(randombytes_buf crypto_auth_verify crypto_auth_keygen);
my $message = randombytes_buf(12);
# you'd really need to already have the key, but here
my $key = crypto_auth_keygen();
# your encrypted data would come from a call to crypto_auth
my $encrypted; # assume this is full of bytes
# let's verify
my $boolean = crypto_auth_verify($encrypted, $message, $key);
say $boolean;
The crypto_auth_verify
function returns a boolean letting us know if the encrypted
message and the original message are verified with the secret key.
crypto_auth_keygen
use Sodium::FFI qw(crypto_auth_keygen);
my $key = crypto_auth_keygen();
# this could also be written:
use Sodium::FFI qw(randombytes_buf crypto_auth_KEYBYTES);
my $key = randombytes_buf(crypto_auth_KEYBYTES);
The crypto_auth_keygen
function returns a byte string of "crypto_auth_KEYBYTES"
bytes.
AES256-GCM Crypto Functions
LibSodium provides a few AES256-GCM functions
to
encrypt or decrypt a message with a nonce and key. Note that these
functions may not be available on your hardware and will "croak" in such
a case.
crypto_aead_aes256gcm_decrypt
use Sodium::FFI qw(
randombytes_buf crypto_aead_aes256gcm_decrypt
crypto_aead_aes256gcm_is_available
crypto_aead_aes256gcm_keygen crypto_aead_aes256gcm_NPUBBYTES
);
if (crypto_aead_aes256gcm_is_available()) {
# you'd really need to already have the nonce and key, but here
my $key = crypto_aead_aes256gcm_keygen();
my $nonce = randombytes_buf(crypto_aead_aes256gcm_NPUBBYTES);
# your encrypted data would come from a call to crypto_aead_aes256gcm_encrypt
my $encrypted; # assume this is full of bytes
# any additional data bytes that were encrypted should also be included
# they can be undef
my $additional_data = undef; # we don't care to add anything extra
# let's decrypt!
my $decrypted_bytes = crypto_aead_aes256gcm_decrypt(
$encrypted, $additional_data, $nonce, $key
);
say $decrypted_bytes;
}
The crypto_aead_aes256gcm_decrypt
function returns a string of bytes after verifying that the
ciphertext includes a valid tag using a secret key, a public nonce, and
additional data.
crypto_aead_aes256gcm_encrypt
use Sodium::FFI qw(
randombytes_buf crypto_aead_aes256gcm_encrypt
crypto_aead_aes256gcm_is_available
crypto_aead_aes256gcm_keygen crypto_aead_aes256gcm_NPUBBYTES
);
if (crypto_aead_aes256gcm_is_available()) {
# First, let's create a key and nonce
my $key = crypto_aead_aes256gcm_keygen();
my $nonce = randombytes_buf(crypto_aead_aes256gcm_NPUBBYTES);
# let's encrypt 12 bytes of random data... for fun
my $message = randombytes_buf(12);
# any additional data bytes that were encrypted should also be included
# they can be undef
my $additional_data = undef; # we don't care to add anything extra
$additional_data = randombytes_buf(12); # or some random byte string
my $encrypted_bytes = crypto_aead_aes256gcm_encrypt(
$message, $additional_data, $nonce, $key
);
say $encrypted_bytes;
}
The crypto_aead_aes256gcm_encrypt
function encrypts a message using a secret key and a public
nonce and returns that message as a string of bytes.
crypto_aead_aes256gcm_is_available
use Sodium::FFI qw(crypto_aead_aes256gcm_is_available);
if (crypto_aead_aes256gcm_is_available()) {
# ... encrypt and decrypt some data here
}
The crypto_aead_aes256gcm_is_available
function returns 1 if the current CPU supports the AES256-GCM
implementation, 0 otherwise.
crypto_aead_aes256gcm_keygen
use Sodium::FFI qw(
crypto_aead_aes256gcm_keygen crypto_aead_aes256gcm_is_available
);
if (crypto_aead_aes256gcm_is_available()) {
my $key = crypto_aead_aes256gcm_keygen();
# this could also be written:
use Sodium::FFI qw(randombytes_buf crypto_aead_aes256gcm_KEYBYTES);
my $key = randombytes_buf(crypto_aead_aes256gcm_KEYBYTES);
}
The crypto_aead_aes256gcm_keygen
function returns a byte string of
"crypto_aead_aes256gcm_KEYBYTES" bytes.
chacha20poly1305 Crypto Functions
LibSodium provides a few chacha20poly1305 functions
to encrypt or decrypt a
message with a nonce and key.
crypto_aead_chacha20poly1305_decrypt
use Sodium::FFI qw(
randombytes_buf crypto_aead_chacha20poly1305_decrypt
crypto_aead_chacha20poly1305_keygen crypto_aead_chacha20poly1305_NPUBBYTES
);
# you'd really need to already have the nonce and key, but here
my $key = crypto_aead_chacha20poly1305_keygen();
my $nonce = randombytes_buf(crypto_aead_chacha20poly1305_NPUBBYTES);
# your encrypted data would come from a call to crypto_aead_chacha20poly1305_encrypt
my $encrypted; # assume this is full of bytes
# any additional data bytes that were encrypted should also be included
# they can be undef
my $additional_data = undef; # we don't care to add anything extra
# let's decrypt!
my $decrypted_bytes = crypto_aead_chacha20poly1305_decrypt(
$encrypted, $additional_data, $nonce, $key
);
say $decrypted_bytes;
The crypto_aead_chacha20poly1305_decrypt
function
returns a string of bytes after verifying that the ciphertext includes a
valid tag using a secret key, a public nonce, and additional data.
crypto_aead_chacha20poly1305_encrypt
use Sodium::FFI qw(
randombytes_buf crypto_aead_chacha20poly1305_encrypt
crypto_aead_chacha20poly1305_keygen crypto_aead_chacha20poly1305_NPUBBYTES
);
# First, let's create a key and nonce
my $key = crypto_aead_chacha20poly1305_keygen();
my $nonce = randombytes_buf(crypto_aead_chacha20poly1305_NPUBBYTES);
# let's encrypt 12 bytes of random data... for fun
my $message = randombytes_buf(12);
# any additional data bytes that were encrypted should also be included
# they can be undef
my $additional_data = undef; # we don't care to add anything extra
$additional_data = randombytes_buf(12); # or some random byte string
my $encrypted_bytes = crypto_aead_chacha20poly1305_encrypt(
$message, $additional_data, $nonce, $key
);
say $encrypted_bytes;
The crypto_aead_chacha20poly1305_encrypt
function
encrypts a message using a secret key and a public nonce and returns
that message as a string of bytes.
crypto_aead_chacha20poly1305_keygen
use Sodium::FFI qw(
crypto_aead_chacha20poly1305_keygen
);
my $key = crypto_aead_chacha20poly1305_keygen();
# this could also be written:
use Sodium::FFI qw(randombytes_buf crypto_aead_chacha20poly1305_KEYBYTES);
my $key = randombytes_buf(crypto_aead_chacha20poly1305_KEYBYTES);
The crypto_aead_chacha20poly1305_keygen
function
returns a byte string of "crypto_aead_chacha20poly1305_KEYBYTES" bytes.
chacha20poly1305_ietf Crypto Functions
LibSodium provides a few chacha20poly1305 IETF functions
to encrypt or decrypt a message
with a nonce and key.
The "IETF" variant of the "ChaCha20-Poly1305" construction can safely
encrypt a practically unlimited number of messages, but individual
messages cannot exceed approximately "256 GiB".
crypto_aead_chacha20poly1305_ietf_decrypt
use Sodium::FFI qw(
randombytes_buf crypto_aead_chacha20poly1305_ietf_decrypt
crypto_aead_chacha20poly1305_ietf_keygen crypto_aead_chacha20poly1305_IETF_NPUBBYTES
);
# you'd really need to already have the nonce and key, but here
my $key = crypto_aead_chacha20poly1305_ietf_keygen();
my $nonce = randombytes_buf(crypto_aead_chacha20poly1305_IETF_NPUBBYTES);
# your encrypted data would come from a call to crypto_aead_chacha20poly1305_ietf_encrypt
my $encrypted; # assume this is full of bytes
# any additional data bytes that were encrypted should also be included
# they can be undef
my $additional_data = undef; # we don't care to add anything extra
# let's decrypt!
my $decrypted_bytes = crypto_aead_chacha20poly1305_ietf_decrypt(
$encrypted, $additional_data, $nonce, $key
);
say $decrypted_bytes;
The crypto_aead_chacha20poly1305_ietf_decrypt
function returns a
string of bytes after verifying that the ciphertext includes a valid tag
using a secret key, a public nonce, and additional data.
crypto_aead_chacha20poly1305_ietf_encrypt
use Sodium::FFI qw(
randombytes_buf crypto_aead_chacha20poly1305_ietf_encrypt
crypto_aead_chacha20poly1305_ietf_keygen crypto_aead_chacha20poly1305_IETF_NPUBBYTES
);
# First, let's create a key and nonce
my $key = crypto_aead_chacha20poly1305_ietf_keygen();
my $nonce = randombytes_buf(crypto_aead_chacha20poly1305_IETF_NPUBBYTES);
# let's encrypt 12 bytes of random data... for fun
my $message = randombytes_buf(12);
# any additional data bytes that were encrypted should also be included
# they can be undef
my $additional_data = undef; # we don't care to add anything extra
$additional_data = randombytes_buf(12); # or some random byte string
my $encrypted_bytes = crypto_aead_chacha20poly1305_ietf_encrypt(
$message, $additional_data, $nonce, $key
);
say $encrypted_bytes;
The crypto_aead_chacha20poly1305_ietf_encrypt
function encrypts a
message using a secret key and a public nonce and returns that message
as a string of bytes.
crypto_aead_chacha20poly1305_ietf_keygen
use Sodium::FFI qw(
crypto_aead_chacha20poly1305_ietf_keygen
);
my $key = crypto_aead_chacha20poly1305_ietf_keygen();
# this could also be written:
use Sodium::FFI qw(randombytes_buf crypto_aead_chacha20poly1305_IETF_KEYBYTES);
my $key = randombytes_buf(crypto_aead_chacha20poly1305_IETF_KEYBYTES);
The crypto_aead_chacha20poly1305_ietf_keygen
function returns a
byte string of "crypto_aead_chacha20poly1305_IETF_KEYBYTES" bytes.
Public Key Cryptography - Public Key Signatures
LibSodium provides a few Public Key Signature Functions
where a signer generates a key pair (public key and secret key) and
appends the secret key to any number of messages. The one doing the
verification will need to know and trust the public key before messages
signed using it can be verified. This is not authenticated encryption.
crypto_sign
use Sodium::FFI qw(crypto_sign_keypair crypto_sign);
my $msg = "Let's sign this and stuff!";
my ($public_key, $secret_key) = crypto_sign_keypair();
my $signed_msg = crypto_sign($msg, $secret_key);
The crypto_sign
function prepends a signature to an unaltered message.
crypto_sign_detached
use Sodium::FFI qw(crypto_sign_keypair crypto_sign_detached);
my $msg = "Let's sign this and stuff!";
my ($public_key, $secret_key) = crypto_sign_keypair();
my $signature = crypto_sign_detached($msg, $secret_key);
The crypto_sign_detached
function signs the message with the secret key and
returns the signature.
crypto_sign_keypair
use Sodium::FFI qw(crypto_sign_keypair);
my ($public_key, $secret_key) = crypto_sign_keypair();
The crypto_sign_keypair
function randomly generates a secret key and a
corresponding public key.
crypto_sign_open
use Sodium::FFI qw(crypto_sign_open);
# we should have the public key and signed message to open
my $signed_msg = ...;
my $public_key = ...;
my $msg = crypto_sign_open($signed_msg, $public_key);
The crypto_sign_open
function checks that a signed message has a valid
signature for the public key. If so, it returns that message and if not,
it will throw.
crypto_sign_seed_keypair
use Sodium::FFI qw(crypto_sign_seed_keypair crypto_sign_SEEDBYTES randombytes_buf);
my $seed = randombytes_buf(crypto_sign_SEEDBYTES);
my ($public_key, $secret_key) = crypto_sign_seed_keypair($seed);
The crypto_sign_seed_keypair
function randomly generates a secret key
deterministically derived from a single key seed and a corresponding
public key.
crypto_sign_verify_detached
use Sodium::FFI qw(crypto_sign_verify_detached);
my $signature = ...;
my $message = ...;
my $public_key = ...;
my $boolean = crypto_sign_verify_detached($signature, $message, $public_key);
The crypto_sign_verify_detached
function verifies that a signature is valid for the
supplied message with public key. It returns a boolean value, 1 for
true, 0 for false.
Random Number Functions
LibSodium provides a few Random Number Generator Functions
to assist you in
getting your data ready for encryption, decryption, or hashing.
randombytes_buf
use Sodium::FFI qw(randombytes_buf);
my $bytes = randombytes_buf(2);
say $bytes; # contains two bytes of random data
The randombytes_buf
function
returns string of random bytes limited by a provided length.
randombytes_buf_deterministic
use Sodium::FFI qw(randombytes_buf_deterministic);
# create some seed string of length Sodium::FFI::randombytes_SEEDBYTES
my $seed = 'x' x Sodium::FFI::randombytes_SEEDBYTES;
# use that seed to create a random string
my $length = 2;
my $bytes = randombytes_buf_deterministic($length, $seed);
say $bytes; # contains two bytes of random data
The randombytes_buf_deterministic
function
returns string of random bytes limited by a provided length.
It returns a byte string indistinguishable from random bytes without
knowing the $seed. For a given seed, this function will always output
the same sequence. The seed string you create should be
"randombytes_SEEDBYTES" bytes long. Up to 256 GB can be produced with a
single seed.
randombytes_random
use Sodium::FFI qw(randombytes_random);
my $random = randombytes_random();
say $random;
The randombytes_random
function
returns an unpredictable value between 0 and 0xffffffff (included).
randombytes_uniform
use Sodium::FFI qw(randombytes_uniform);
my $upper_limit = 0xffffffff;
my $random = randombytes_uniform($upper_limit);
say $random;
The randombytes_uniform
function
returns an unpredictable value between 0 and $upper_bound (excluded).
Unlike "randombytes_random() % $upper_bound", it guarantees a uniform
distribution of the possible output values even when $upper_bound is not
a power of 2. Note that an $upper_bound less than 2 leaves only a single
element to be chosen, namely 0.
Utility/Helper Functions
LibSodium provides a few Utility/Helper Functions
to assist you in getting your data
ready for encryption, decryption, or hashing.
sodium_add
use Sodium::FFI qw(sodium_add);
my $left = "111";
$left = sodium_add($left, 111);
say $left; # bbb
The sodium_add
function adds 2 large numbers.
sodium_base642bin
use Sodium::FFI qw(sodium_base642bin);
say sodium_base642bin('/wA='); # \377\000
my $variant = Sodium::FFI::sodium_base64_VARIANT_ORIGINAL;
say sodium_base642bin('/wA=', $variant); # \377\000
$variant = Sodium::FFI::sodium_base64_VARIANT_ORIGINAL_NO_PADDING;
say sodium_base642bin('/wA', $variant); # \377\000
$variant = Sodium::FFI::sodium_base64_VARIANT_URLSAFE;
say sodium_base642bin('_wA=', $variant); # \377\000
$variant = Sodium::FFI::sodium_base64_VARIANT_URLSAFE_NO_PADDING;
say sodium_base642bin('_wA', $variant); # \377\000
The sodium_base642bin
function
takes a base64 encoded string and turns it back into a binary string.
sodium_bin2base64
use Sodium::FFI qw(sodium_bin2base64);
say sodium_bin2base64("\377\000"); # /wA=
my $variant = Sodium::FFI::sodium_base64_VARIANT_ORIGINAL;
say sodium_bin2base64("\377\000", $variant); # /wA=
$variant = Sodium::FFI::sodium_base64_VARIANT_ORIGINAL_NO_PADDING;
say sodium_bin2base64("\377\000", $variant); # /wA
$variant = Sodium::FFI::sodium_base64_VARIANT_URLSAFE;
say sodium_bin2base64("\377\000", $variant); # _wA=
$variant = Sodium::FFI::sodium_base64_VARIANT_URLSAFE_NO_PADDING;
say sodium_bin2base64("\377\000", $variant); # _wA
The sodium_bin2base64
function
takes a binary string and turns it into a base64 encoded string.
sodium_bin2hex
use Sodium::FFI qw(sodium_bin2hex);
my $binary = "ABC";
my $hex = sodium_bin2hex($binary);
say $hex; # 414243
The sodium_bin2hex
function takes a binary string and turns it into a hex string.
sodium_compare
use Sodium::FFI qw(sodium_compare);
say sodium_compare("\x01", "\x02"); # -1
say sodium_compare("\x02", "\x01"); # 1
say sodium_compare("\x01", "\x01"); # 0
The sodium_compare
function
compares two large numbers encoded in little endian format. Results in
-1 when "$left < $right" Results in 0 when "$left eq $right" Results in
1 when "$left > $right"
sodium_hex2bin
use Sodium::FFI qw(sodium_hex2bin);
my $hex = "414243";
my $bin = sodium_hex2bin($hex);
say $bin; # ABC
The sodium_hex2bin
function takes a hex string and turns it into a binary string.
sodium_increment
use Sodium::FFI qw(sodium_increment);
my $x = "\x01";
$x = sodium_increment($x); # "\x02";
The sodium_increment
function
takes an arbitrarily long unsigned number and increments it.
sodium_is_zero
use Sodium::FFI qw(sodium_is_zero);
my $string = "\x00\x00\x01"; # zero zero 1
# entire string not zeros
say sodium_is_zero($string); # 0
# first byte of string is zero
say sodium_is_zero($string, 1); # 1
# first two bytes of string is zero
say sodium_is_zero($string, 2); # 1
The sodium_is_zero
function tests
a string for all zeros.
sodium_library_minimal
use Sodium::FFI qw(sodium_library_minimal);
say sodium_library_minimal; # 0 or 1
The "sodium_library_minimal" function lets you know if this is a minimal
version.
sodium_library_version_major
use Sodium::FFI qw(sodium_library_version_major);
say sodium_library_version_major; # 10
The "sodium_library_version_major" function returns the major version of
the library.
sodium_library_version_minor
use Sodium::FFI qw(sodium_library_version_minor);
say sodium_library_version_minor; # 3
The "sodium_library_version_minor" function returns the minor version of
the library.
sodium_memcmp
use Sodium::FFI qw(sodium_memcmp);
my $string1 = "abcdef";
my $string2 = "abc";
my $match_length = 3;
# string 1 and 2 are equal for the first 3
say sodium_memcmp($string1, $string2, $match_length); # 0
# they are not equal for 4 slots
say sodium_memcmp("abcdef", "abc", 4); # -1
The sodium_memcmp
function compares two strings in constant time. Results in -1 when
strings 1 and 2 aren't equal. Results in 0 when strings 1 and 2 are
equal.
sodium_pad
use Sodium::FFI qw(sodium_pad);
my $bin_string = "\x01";
my $block_size = 4;
say sodium_pad($bin_string, $block_size); # 01800000
The sodium_pad function adds padding
data to a buffer in order to extend its total length to a multiple of
the block size.
sodium_sub
use Sodium::FFI qw(sodium_sub);
my $x = "\x02";
my $y = "\x01";
my $z = sodium_sub($x, $y);
say $x; # \x01
The sodium_sub
function
subtracts 2 large, unsigned numbers encoded in little-endian format.
sodium_unpad
use Sodium::FFI qw(sodium_unpad);
my $bin_string = "\x01\x80\x00\x00\x0";
my $block_size = 4;
say sodium_unpad($bin_string, $block_size); # 01
The sodium_unpad function computes
the original, unpadded length of a message previously padded using
"sodium_pad".
sodium_version_string
use Sodium::FFI qw(sodium_version_string);
say sodium_version_string; # 1.0.18
The "sodium_version_string" function returns the stringified version
information for the version of LibSodium that you have installed.
COPYRIGHT
Copyright 2020 Chase Whitener. All rights reserved.
This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.