Ciphers

Ciphers support in buddy is available on buddy.core.crypto namespace.

Block Ciphers

In cryptography, a block cipher is a deterministic algorithm operating on fixed-length groups of bits, called blocks, with an unvarying transformation that is specified by a symmetric key.

This is a table of currently supported block ciphers in buddy-core:

Algorithm name Keywords
AES :aes
Twofish :twofish
Blowfish :blowfish

Additionally, for good security, is mandatory to combine a block cipher with some cipher mode of operation.

This is a table of currently supported of cipher mode of operation:

Algorithm name Keywords
SIC (CTR) :ctr, :sic
CBC :cbc
OFB :ofb
GCM :gcm

NOTE: currently buddy comes with limited number of ciphers and modes, but in near future more many more options should be added.

Example encrypt:

(require '[buddy.core.crypto :as crypto])
(require '[buddy.core.nonce :as nonce])
(require '[buddy.core.codecs :as codecs])

(let [eng   (crypto/block-cipher :twofish :cbc)
      iv16  (nonce/random-nonce 16)
      key32 (nonce/random-nonce 32)
      data  (codecs/hex->bytes "000000000000000000000000000000AA")]
  (crypto/init! eng {:key key32 :iv iv16 :op :encrypt})
  (crypto/process-block! eng data))

;; => #<byte[] [B@efadff9>

AEAD mode of operations also exposes additional function for caluclate the total size of the output including the authentication tag: output-size.

Stream Ciphers

Stream ciphers differ from block ciphers, in that they works with arbitrary length input and do not require any additional mode of operation.

This is a table of currently supported of stream ciphers in buddy:

Algorithm name Keywords
ChaCha :chacha

Example encrypt:

(require '[buddy.core.crypto :as crypto])
(require '[buddy.core.codecs :as codecs])
(require '[buddy.core.nonce :as nonce])

(let [eng   (crypto/stream-cipher :chacha)
      iv8   (nonce/random-nonce 8)
      key32 (nonce/random-nonce 32)
      data  (codecs/hex->bytes "0011")]
  (crypto/init! eng {:key key32 :iv iv8 :op :encrypt})
  (crypto/process-bytes! eng data))

;; => #<byte[] [B@efadff9>

NOTE: the iv and key size depends estrictly on cipher engine, in this case, chacha engine requires 8 bytes iv.

NOTE: for decrypt, only change :op value to :decrypt

NOTE: You can call crypto/initialize! any times as you want, it simply reinitializes the engine.

High level encryption schemes

Since version 0.6.0, buddy-core comes with high level crypto interface that allows user encrypt arbitrary length data using one of the well established encryption schemes.

The api consists in two simple functions. Let see an example of how to encrypt arbitrary length text and decrypt it:

(require '[buddy.core.crypto :as crypto])
(require '[buddy.core.codecs :as codecs])
(require '[buddy.core.nonce :as nonce])
(require '[buddy.core.hash :as hash])

(def original-text
  (codecs/to-bytes "Hello World."))

(def iv (nonce/random-bytes 16))   ;; 16 bytes random iv
(def key (hash/sha256 "mysecret")) ;; 32 bytes key

;; Encrypt the original-text content using previously
;; declared iv and key.
(def encrypted (crypto/encrypt original-text key iv
                               {:alg :aes128-cbc-hmac-sha256}))

;; And now, decrypt it using the same parameters:
(-> (crypto/decrypt encrypted key iv {:alg :aes128-cbc-hmac-sha256})
    (codecs/bytes->str))
;; => "Hello World."

This is a complete list of supported encryption schemes:

  • :aes128-cbc-hmac-sha256 (default)
  • :aes192-cbc-hmac-sha384
  • :aes256-cbc-hmac-sha512
  • :aes128-gcm
  • :aes192-gcm
  • :aes256-gcm