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.
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
);
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.
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.