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.

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.