Crypto

Usage

use Crypto;

or

import Crypto;

Submodules

A cryptographic library based on OpenSSL, targeted at flexible encryption purposes.

The Crypto module focuses on providing various cryptographic utilities such as

Note

This module is currently under development and will expand significantly in upcoming releases.

Compiling with Crypto

In order to compile a Chapel program that uses this module, the Crypto and C_OpenSSL (C wrappers to OpenSSL) libraries must be installed on the system. The paths to both the openssl/<module>.h header files and OpenSSL library must be passed to the -I and -L compiler arguments. The library name, typically crypto, must be passed to the -l argument as well.

The compilation command should look something like this:

chpl -I$PATH_TO_OPENSSL_DIR \
     -L$PATH_TO_OPENSSL_LIBS -lcrypto source.chpl

This would also work by setting the LDFLAGS and CPPFLAGS environment variables to the expected paths on certain systems.

Chapel Crypto API

class CryptoBuffer

The CryptoBuffer class is a wrapper around the internal representation of how the values in this library are stored. Every sequence of bytes going into a Crypto utility or coming out of it, is a CryptoBuffer.

A CryptoBuffer can enclose a string or a [] uint(8) passed to its initializer and provides helper functions to access those values.

proc init(s: string)

The CryptoBuffer class initializer that initializes the buffer when a string is supplied to it.

Arguments:s : stringstring input for buffer conversion.
Returns:An object of class CryptoBuffer.
Return type:CryptoBuffer
proc init(s: [] uint(8))

The CryptoBuffer class initializer that initializes the buffer when a [] uint(8) is supplied to it.

Arguments:s : [] uint(8)[] uint(8) input for buffer conversion.
Returns:An object of class CryptoBuffer.
Return type:CryptoBuffer
proc getBuffData()

Returns the entire internal buffer with each byte in ASCII.

Returns:the internal buffer representation.
Return type:[] uint(8)
proc getBuffPtr()

Returns the pointer to the entire internal buffer with each byte in ASCII.

Returns:pointer to the internal buffer representation.
Return type:c_ptr([] uint(8))
proc getBuffSize(): int

Returns the length of the entire internal buffer.

Returns:length of the internal buffer representation.
Return type:int
proc toHex() throws

Returns the hexadecimal array representation of the entire internal buffer.

Returns:hex array representation of the internal buffer.
Return type:[] string
proc toHexString() throws

Returns the hexadecimal string representation of the entire internal buffer.

Returns:hex string representation of the internal buffer.
Return type:string
class RSAKey

RSAKey class encloses the EVP_PKEY object provided by the OpenSSL primitives. The EVP_PKEY object can contain the public key, private key or both of them. Hence, the contents of an object of the class RSAKey may be decided by the user.

Calling the RSAKey initializer without using any key import or export functions may result in generation of a single object that contains both the keys (public and private).

In order to separate out the key objects, keys can be imported from a .pem file. (TODO)

proc init(keyLen: int)

The RSAKey class initializer that initializes the EVP_PKEY object of OpenSSL and basically, initializes a set of public and private keys.

It checks for valid RSA key lengths and generates a public key and private key pair accordingly.

Arguments:keyLen : int – RSA Key length in bits.
Returns:An object of class RSAKey representing the key pair.
Return type:RSAKey
class Envelope

The Envelope class wraps all the data returned by the encrypt function of the RSA class along with some utility data. An RSA encrypt function returns an array of RSA encrypted symmetric keys and a single AES encrypted message. The Envelope also encloses the initialization vector used during encryption such that it can be utilized during the decryption phase as well.

proc init(iv: owned CryptoBuffer, encSymmKey: [] owned CryptoBuffer, encSymmValue: owned CryptoBuffer)

The Envelope class initializer that encapsulates the IV, AES encrypted ciphertext buffer and an array of encrypted key buffers.

Arguments:
  • iv : owned CryptoBuffer – Initialization Vector.
  • encSymmKey : [] owned CryptoBuffer – Array of encrypted symmetric (AES) keys.
  • encSymmValue : owned CryptoBuffer – AES-encrypted ciphertext buffer.
Returns:

An object of class Envelope.

Return type:

Envelope

proc getEncMessage()

This function returns the encrypted version of the plaintext supplied by the user.

Returns:A ‘CryptoBuffer’ representing the ciphertext.
Return type:CryptoBuffer
proc getIV()

This function returns the IV generated by the encrypt routine and encapsulated in the Envelope. This is used for both encryption and decryption.

Returns:Initialization Vector.
Return type:CryptoBuffer
proc getEncKeyByIndex(i: int)

This function returns a particular symmetric key buffer based on the index supplied as the argument.

Note

The supplied index should be in the domain of the RSA-encrypted keys array.

Arguments:i : int – An index of the symmetric key buffer array.
Returns:A specific key buffer based on the index.
Return type:CryptoBuffer
proc getEncKeys()

This function returns the entire array of symmetric key buffers.

Returns:Entire array of key buffers.
Return type:[] CryptoBuffer
enum Digest { MD5, SHA1, SHA224, SHA256, SHA384, SHA512, RIPEMD160 }

The Digest enum represents all the hashing functions provided by the OpenSSL primitives. Value from this enum is passed to the Hash class initializer in order to select the type of hashing function to be used.

class Hash

The Hash class represents all the hashing functions provided by the OpenSSL primitives. It supports all the prominent and most commonly used deterministic hashing functions.

proc init(digestName: Digest)

The Hash class initializer that initializes the hashing function to be used. This initializer sets the byte length of the respective hash and allocates a domain for memory allocation for hashing. It currently supports the following hashing functions - MD5, SHA1, SHA224, SHA256, SHA384, SHA512 and RIPEMD160 consumed via an enum, Digest.

Arguments:digestName : Digest – Hashing function to be used.
Returns:An object of class Hash.
Return type:Hash

Initialization example,

var h = new Hash(Digest.SHA256);
proc getDigestName(): string

Returns the name of the hashing function used. For instance, instantiating an object with var hash = new Hash("SHA256"), would make this function return the string SHA256.

Returns:Name of the hashing function.
Return type:string
proc getDigest(inputBuffer: CryptoBuffer): owned CryptoBuffer

Given a CryptoBuffer (buffer) as input, this function returns it’s hash digest. The returned hash digest is also a buffer that can be accessed by using buffer utility functions.

Arguments:inputBuffer : CryptoBuffer – A CryptoBuffer representing the input to be hashed.
Returns:An owned CryptoBuffer representing the hash digest.
Return type:owned CryptoBuffer
enum CryptoChainMode { cbc, ecb, cfb, ofb }

The CryptoChainMode enum represents all cipher chaining modes that can be used by a symmetric cipher. It is used by the AES and Blowfish class initializers to select a chaining mode.

class AES

The AES class represents the symmetric encryption algorithm, AES. The Advanced Encryption Standard (AES), also known by its original name Rijndael is a specification for the encryption of electronic data established by the U.S. National Institute of Standards and Technology (NIST) in 2001.

It is the most widely used symmetric cipher and is also used to encrypt messages in public-key cryptography such as within RSA.

Currently, the AES class allows symmetric encryption using only the CBC or Cipher Block Chaining mode in 128, 192, and 256 key size variants.

After thorough testing, ECB, OCB and other chaining mode variants will also be added to this library(TODO).

proc init(bits: int, mode: CryptoChainMode)

The AES class initializer that initializes the AES encryption algorithm with the right key length and chaining mode.

Arguments:
  • bits : int – Number of bits representing the variant of AES based on key-size. (128, 192 or 256)
  • mode : CryptoChainMode – Chaining mode to be used.
Returns:

An object of class AES.

Return type:

AES

Initialization example,

var aes = new AES(256, CryptoChainMode.cbc);
proc getByteSize(): int

This function returns the size in bytes of the key-length/variant of AES which is to be used. For instance,

  • AES128 returns 16
  • AES192 returns 24
  • AES256 returns 32
Returns:Key length of AES in bytes.
Return type:int
proc encrypt(plaintext: CryptoBuffer, key: CryptoBuffer, IV: CryptoBuffer): owned CryptoBuffer

This is the ‘AES’ encrypt routine that encrypts the user supplied message buffer using the key and IV.

The encrypt takes in the plaintext buffer, key buffer and IV buffer as the arguments and returns a buffer of the ciphertext.

Arguments:
  • plaintext : CryptoBuffer – A CryptoBuffer representing the plaintext to be encrypted.
  • key : CryptoBuffer – A CryptoBuffer representing the key to be used for encryption.
  • IV : CryptoBuffer – A CryptoBuffer representing the initialization vector to be used for encryption.
Returns:

An owned CryptoBuffer representing the ciphertext.

Return type:

owned CryptoBuffer

proc decrypt(ciphertext: CryptoBuffer, key: CryptoBuffer, IV: CryptoBuffer): owned CryptoBuffer

This is the ‘AES’ decrypt routine that decrypts the user supplied ciphertext buffer using the same key and IV used for encryption.

The decrypt takes in the ciphertext buffer, key buffer and IV buffer as the arguments and returns a buffer of the decrypted plaintext.

Arguments:
  • ciphertext : CryptoBuffer – A CryptoBuffer representing the ciphertext to be decrypted.
  • key : CryptoBuffer – A CryptoBuffer representing the key to be used for decryption (same as the one used in encryption).
  • IV : CryptoBuffer – A CryptoBuffer representing the initialization vector to be used for decryption (same as the one used in encryption).
Returns:

An owned CryptoBuffer representing the obtained plaintext.

Return type:

owned CryptoBuffer

class Blowfish

The Blowfish class represents a symmetric-key block cipher called Blowfish, designed in 1993 by Bruce Schneier. Considering current scenario, the Advanced Encryption Standard(AES) cipher is used more in practice. Since, Blowfish is unpatented and placed in the public domain, it receives a decent amount of attention from the community.

Note

Since the key in Blowfish can be of various sizes, use a KDF routine to generate a secure-key with the recommended byte-size as 16 bytes. Also, the initialization vector in Blowfish cipher should strictly be 8 bytes long.

The Blowfish class supports 4 chaining modes:

  • cbc or Cipher Block Chaining
  • ecb or Electronic Codebook
  • cfb or Cipher Feedback
  • ofb or Output Feedback
proc init(mode: CryptoChainMode)

The Blowfish class initializer that initializes the Blowfish encryption algorithm with the right key length and chaining mode.

Arguments:mode : CryptoChainMode – Name of the chaining mode to be used.
Returns:An object of class Blowfish.
Return type:Blowfish

Initialization example,

var bf = new Blowfish(CryptoChainMode.cbc);
proc encrypt(plaintext: CryptoBuffer, key: CryptoBuffer, IV: CryptoBuffer): owned CryptoBuffer throws

This is the ‘Blowfish’ encrypt routine that encrypts the user supplied message buffer using the key and IV.

The encrypt takes in the plaintext buffer, key buffer and IV buffer as the arguments and returns a buffer of the ciphertext.

Arguments:
  • plaintext : CryptoBuffer – A CryptoBuffer representing the plaintext to be encrypted.
  • key : CryptoBuffer – A CryptoBuffer representing the key to be used for encryption.
  • IV : CryptoBuffer – A CryptoBuffer representing the initialization vector to be used for encryption.
Returns:

An owned CryptoBuffer representing the ciphertext.

Return type:

owned CryptoBuffer

proc decrypt(ciphertext: CryptoBuffer, key: CryptoBuffer, IV: CryptoBuffer): owned CryptoBuffer

This is the ‘Blowfish’ decrypt routine that decrypts the user supplied ciphertext buffer using the same key and IV used for encryption.

The decrypt takes in the ciphertext buffer, key buffer and IV buffer as the arguments and returns a buffer of the decrypted plaintext.

Arguments:
  • ciphertext : CryptoBuffer – A CryptoBuffer representing the ciphertext to be decrypted.
  • key : CryptoBuffer – A CryptoBuffer representing the key to be used for decryption (same as the one used in encryption).
  • IV : CryptoBuffer – A CryptoBuffer representing the initialization vector to be used for decryption (same as the one used in encryption).
Returns:

An owned CryptoBuffer representing the obtained plaintext.

Return type:

owned CryptoBuffer

class CryptoRandom

The CryptoRandom class represents a CSPRNG provided by OpenSSL that automatically does the seeding part before returning a random sequence of bytes of the type CryptoBuffer.

Given the length of the buffer required by the user, it generates a random buffer of the same size.

proc getRandomBuffer(buffLen: int): owned CryptoBuffer throws

This function represents a CSPRNG that generates and allocates the desired number of random values as specified by the argument. Halts for number of bytes less than 1 (invalid). For instance,

var a = (new CryptoRandom()).getRandomBuffer(5)

would give us a CryptoBuffer of size 5 and pre-initialized with values.

Arguments:buffLen : int – Number of random values to be generated in the buffer.
Returns:An owned CryptoBuffer representing the generated values.
Return type:owned CryptoBuffer
class KDF

The KDF class contains the most widely used key derivation functions. Currently it supports a single password based key derivation function which is the most secure one as of writing this library. More KDFs will be added to this in the future.

proc init(byteLen: int, iterCount: int, digest: Hash)

The KDF class initializer that initializes the common data used by most of the Key Derivation Functions.

Arguments:
  • byteLen : int – Size of the expected key in bytes / key length.
  • iterCount : int – The iteration count used by OpenSSL to repeat the Update primitive. Min. recommended value = 1000. Greater the iterCount, greater the security of the key.
  • digest : Hash – An object of class ‘Hash’. This decides the Hashing function to be used for HMAC based KDFs.
Returns:

An object of class KDF.

Return type:

KDF

proc passKDF(userKey: string, saltBuff: CryptoBuffer): owned CryptoBuffer

This function represents Password-Based KDF 2. It generates a secure-key buffer based on the salt and also on the metadata provided in the KDF initializer.

Arguments:
  • userKey : string – User-specified string representation of the key.
  • saltBuff : CryptoBuffer – A CryptoBuffer representing the user generated salt.
Returns:

An owned CryptoBuffer representing the generated key.

Return type:

owned CryptoBuffer

class RSA

RSA is one of the first practical public-key cryptosystems and is widely used for secure data transmission. A user of the RSA first generates the public and private keys using the RSAKey class. The RSAKey object is then passed to the RSA functions for further encryption and decryption purposes.

The encrypt function of this class takes in an array of RSAKey objects and uses all of them to perform the encryption.

Similarly, decryption can be done individually performed (without passing an array as an argument) by passing a single RSAKey object every time the decryption takes place.

proc encrypt(plaintext: CryptoBuffer, keys: [] RSAKey): owned Envelope

This is the ‘RSA’ encrypt routine that encrypts the plaintext buffer. This uses the AES encryption algorithm to encrypt the plaintext and auto-generates a secure IV and key. Furthermore, the key is encrypted using RSA based on the ‘RSAKey’ objects supplied in the arguments.

The function returns an Envelope object that encloses the auto-generated IV, AES encrypted ciphertext and an array of RSA encrypted key buffers. The number of encrypted keys is equal to the number of RSAKey objects in the array. This kind of use case is useful specifically in developing one-to-many systems such as GPG.

For instance, consider a server-client model where the server performs encryption using the public keys of all the clients and returns an Envelope to each client. Now, the decryption can only be performed by each client using only their own private key.

Arguments:
  • plaintext : CryptoBuffer – A CryptoBuffer representing the plaintext to be encrypted.
  • keys : [] RSAKey – An array of RSAKey objects. This depends on the number of different RSA encryptions that are to be performed on the same plaintext.
Returns:

An owned Envelope object which comprises of the IV buffer, array of RSA encrypted keys and AES encrypted ciphertext.

Return type:

owned Envelope

proc decrypt(envp: Envelope, key: RSAKey): owned CryptoBuffer throws

This is the ‘RSA’ decrypt routine that decrypts the ciphertext buffer. This uses AES decryption to decrypt the ciphertext.

It accepts the entire Envelope object but only a single RSAKey object for unilateral decryption.

Arguments:
  • envp : Envelope – A CryptoBuffer representing the plaintext to be encrypted.
  • key : RSAKey – An array of RSAKey objects. This depends on the number of different RSA encryptions that are to be performed on the same plaintext.
Returns:

An owned CryptoBuffer representing the obtained plaintext.

Return type:

owned CryptoBuffer