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 <https://doc.libsodium.org/> 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 <https://doc.libsodium.org/secret-key_cryptography/aead/aes-256-gcm> 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 <https://doc.libsodium.org/secret-key_cryptography/aead/aes-256-gcm#comb ined-mode> 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 <https://doc.libsodium.org/secret-key_cryptography/aead/aes-256-gcm#comb ined-mode> 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 <https://doc.libsodium.org/secret-key_cryptography/aead/aes-256-gcm#limi tations> 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 <https://doc.libsodium.org/secret-key_cryptography/aead/aes-256-gcm#deta ched-mode> function returns a byte string of "crypto_aead_aes256gcm_KEYBYTES" bytes. Random Number Functions LibSodium provides a few Random Number Generator Functions <https://doc.libsodium.org/generating_random_data> 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 <https://doc.libsodium.org/generating_random_data#usage> 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 <https://doc.libsodium.org/generating_random_data#usage> 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 <https://doc.libsodium.org/generating_random_data#usage> 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 <https://doc.libsodium.org/generating_random_data#usage> 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 <https://doc.libsodium.org/helpers> 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 <https://doc.libsodium.org/helpers#adding-large-numbers> 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 <https://doc.libsodium.org/helpers#base64-encoding-decoding> 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 <https://doc.libsodium.org/helpers#base64-encoding-decoding> 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 <https://doc.libsodium.org/helpers#hexadecimal-encoding-decoding> 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 <https://doc.libsodium.org/helpers#comparing-large-numbers> 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 <https://doc.libsodium.org/helpers#hexadecimal-encoding-decoding> 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 <https://doc.libsodium.org/helpers#incrementing-large-numbers> 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 <https://doc.libsodium.org/helpers#testing-for-all-zeros> 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 <https://doc.libsodium.org/helpers#constant-time-test-for-equality> 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 <https://doc.libsodium.org/padding> 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 <https://doc.libsodium.org/helpers#subtracting-large-numbers> 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 <https://doc.libsodium.org/padding> 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.