# Raku Gcrypt - Bindings for GNU Libgcrypt [![Build Status](https://travis-ci.org/CurtTilmes/raku-libgcrypt.svg)](https://travis-ci.org/CurtTilmes/raku-libgcrypt) * [Introduction](#introduction) * [Message Digest (Hash)](#message-digest-hash) * [Symmetric cryptography ciphers](#symmetric-cryptography-ciphers) * [Random](#random) * [Passphrase](#passphrase) * [libgcrypt versions/features](#libgcrypt-versionsfeatures) * [Multi-threading](#multi-threading) * [Installation](#installation) * [License](#license) ## Introduction A [Raku](https://raku.org/) interface to [libgcrypt](https://gnupg.org/software/libgcrypt/). Libgcrypt is a general purpose cryptographic library originally based on code from GnuPG. It provides functions for all cryptograhic building blocks: symmetric cipher algorithms (AES, Arcfour, Blowfish, Camellia, CAST5, ChaCha20 DES, GOST28147, Salsa20, SEED, Serpent, Twofish) and modes (ECB,CFB,CBC,OFB,CTR,CCM,GCM,OCB,POLY1305,AESWRAP), hash algorithms (MD2, MD4, MD5, GOST R 34.11, RIPE-MD160, SHA-1, SHA2-224, SHA2-256, SHA2-384, SHA2-512, SHA3-224, SHA3-256, SHA3-384, SHA3-512, SHAKE-128, SHAKE-256, TIGER-192, Whirlpool), MACs (HMAC for all hash algorithms, CMAC for all cipher algorithms, GMAC-AES, GMAC-CAMELLIA, GMAC-TWOFISH, GMAC-SERPENT, GMAC-SEED, Poly1305, Poly1305-AES, Poly1305-CAMELLIA, Poly1305-TWOFISH, Poly1305-SERPENT, Poly1305-SEED), and random numbers. **Note, this is still a work in progress, more features may or may not be forthcoming!! Patches welcome!!** # Usage ## Message Digest (Hash) A [message digest or cryptographic hash function](https://en.wikipedia.org/wiki/Cryptographic_hash_function) is a function that maps data of arbitrary size to a bit string of fixed size, the hash or digest. ``` use Gcrypt::Simple :MD5; # Import routines you specify, or use :ALL for all say MD5('Some text').hex; # 9db5682a4d778ca2cb79580bdb67083f say MD5(slurp).hex; # print md5sum of STDIN my $obj = MD5; # Get a new object $obj.write("$_\n") for lines; # Incremental calculation say $obj.digest; # Blob say $obj.hex; # Hex string say $obj.dec; # Decimal $obj.reset; # Reuse object on another message ``` Available Hashes: MD5 SHA1 RIPEMD160 TIGER SHA256 SHA384 SHA512 SHA224 MD4 CRC32 CRC32_RFC1510 CRC24_RFC2440 WHIRLPOOL TIGER1 TIGER2 GOSTR3411_94 STRIBOG256 STRIBOG512 SHA3_224 SHA3_256 SHA3_384 SHA3_512 SHAKE128 SHAKE256 BLAKE2B_512 BLAKE2B_384 BLAKE2B_256 BLAKE2B_160 BLAKE2S_256 BLAKE2S_224 BLAKE2S_160 BLAKE2S_128 See [Available hash algorithms](https://gnupg.org/documentation/manuals/gcrypt/Available-hash-algorithms.html) for more details on each algorithm. Note that SHAKE128 and SHAKE256 are extendable-output functions (XOF), and can produce variable amounts of output. Pass in the number of bytes you want to `digest`, `hex` or `dec`: ``` use Gcrypt::Simple :SHAKE128; say SHAKE128('Some text').hex(16); ``` ## Message Authentication Codes (MAC) A [message authentication code](https://en.wikipedia.org/wiki/Message_authentication_code) is a short code used to authenticate that a message came from the stated sender (its authenticity) and has not been changed. To create one, you need a key and the message. ``` use Gcrypt::Simple :HMAC_MD5; # Select algorithm, or :ALL for all say HMAC_MD5('mykey', 'my message').hex; # f50357b6299b741cf6b1c63073e54112 my $obj = HMAC_MD5('mykey'); # Create object $obj.write('my message'); # Add data say $obj.MAC; # Blob say $obj.hex; # Hex string $obj.reset; # Reuse object on another message ``` Key is truncated or 0 extended to the size for the algorithm. (`$obj.keylen` will tell you the algorithm's key size). Available MAC algorithms: HMAC_SHA256 HMAC_SHA224 HMAC_SHA512 HMAC_SHA384 HMAC_SHA1 HMAC_MD5 HMAC_MD4 HMAC_RIPEMD160 HMAC_TIGER HMAC_WHIRLPOOL HMAC_GOSTR3411_94 HMAC_STRIBOG256 HMAC_STRIBOG512 HMAC_SHA3_224 HMAC_SHA3_256 HMAC_SHA3_384 HMAC_SHA3_512 CMAC_AES CMAC_3DES CMAC_Camellia CMAC_CAST5 CMAC_Blowfish CMAC_Twofish CMAC_Serpent CMAC_SEED CMAC_RFC2268 CMAC_IDEA CMAC_GOST28147 GMAC_AES GMAC_Camellia GMAC_Twofish GMAC_Serpent GMAC_SEED POLY1305 See [Available MAC algorithms](https://gnupg.org/documentation/manuals/gcrypt/Available-MAC-algorithms.html) for more details on each algorithm. ## Symmetric cryptography ciphers ``` use Gcrypt::Simple :IDEA; my $key = 'foobar'; my $encrypted = IDEA($key).encrypt('Some text'); say IDEA($key).decrypt($encrypted); my $obj = IDEA($key); # Create object my $encrypted = $obj.encrypt('Some text'); $obj.reset; # Reuse object say $obj.decrypt($encrypted); ``` Available Ciphers: IDEA DES3 CAST5 Blowfish AES AES192 AES256 Twofish RC4 DES Twofish128 Serpent128 Serpent192 RFC2268_40 SEED Camellia128 Camellia192 Camellia256 Salsa20 Salsa20R12 GOST28147 ChaCha20 See [Available ciphers](https://gnupg.org/documentation/manuals/gcrypt/Available-ciphers.html) for more details on each algorithm. ## Random ``` use Gcrypt::Random; my $rand = random(10); # Buf[uint8].new(148,229,159,236,230,13,154,226,245,23) my $rand = random(10, :weak); # actually the same as strong my $rand = random(10, :strong); # default my $rand = random(10, :very-strong); # stronger my $rand = nonce(10); # Actually weak, but unpredictable ``` Returns a buffer of random bytes. See [Quality of random numbers](https://gnupg.org/documentation/manuals/gcrypt/Quality-of-random-numbers.html) for more information. ## Passphrase Derive a key from a string ``` use Gcrypt::Passphrase; my $passphrase = "This is a long and complicated passphrase."; my $key = key-from-passphrase($passphrase, keysize => 16, algorithm => 'SIMPLE_S2K', subalgorithm => 'SHA1'); $key = key-from-passphrase($passphrase, keysize => 64, algorithm => 'ITERSALTED_S2K', subalgorithm => 'SHA512', iterations => 12, salt => 'abcdefgh'); ``` See [Key Derivation](https://gnupg.org/documentation/manuals/gcrypt/Key-Derivation.html) for more information. # libgcrypt versions/features By default, this module verifies that the library is a very late version to enable all the features that are implemented here. If you have an older version installed, the initialization will fail with an `X::Gcrypt::BadVersion` exception. If you know what you are doing and promise to only use features that you know that your library is capable of performing, you can supply an older version to the initialization. ``` use Gcrypt; Gcrypt.init(version => '1.7.6'); ``` Gcrypt.init() also returns the actual version of the libarary, so you can use it, for example, to pick the algorithm to use based on the version. # Multi-threading Make sure the library is initialized prior to creating any threads you will be accessing it in. You can do this by doing any `Gcrypt` action, or just manually calling init: ``` use Gcrypt; Gcrypt.init; ``` The error strings use a static memory buffer, so make sure only one thread is printing out an `Exception` message at a time. You can use the exception's integer `code` safely. ## Installation Many distributions already have libgcrypt installed, but if not, get it first: * For debian or ubuntu: `apt install libgcrypt20` * For alpine: `apk add libgcrypt` Then `zef install Gcrypt`. ## License This work is subject to the Artistic License 2.0. See [LICENSE](LICENSE) for more information.