Crypt

CI Status GitHub release Docs

Cryptographic utilities made easy for Crystal lang.

This module provides cryptographic features, with abstractions on top of OpenSSL and Crypto (included in the Crystal standard-library).

Installation

  1. Add the dependency to your shard.yml:
dependencies:
  crypt:
    github: nicolab/crystal-crypt
  1. Run shards install

Usage

To optimize the size of the final binary, features are decoupled, so each module must be included when you need it.

OpenSSL Cipher: Encrypt / Decrypt

API doc: Crypt::Crypter

require "crypt"
require "crypt/crypter"
require "crypt/random"

data = "super secret data"
secret = Crypt.random_string(32)
crypter = Crypt::Crypter.new(secret)

# Data encrypted
encrypted = crypter.encrypt(data)

# Data decrypted
decrypted_bytes = crypter.decrypt(encrypted)

# Decrypted data (Bytes)
puts decrypted_bytes

# Convert Bytes to String
puts String.new(decrypted_bytes)

With signature

Encrypt with a crypto signature:

require "crypt"
require "crypt/crypter"
require "crypt/random"

data = "super secret data"
secret = Crypt.random_string(32)
crypter = Crypt::Crypter.new(secret)

# Data encrypted and signed
encrypted = crypter.encrypt(data, :sign)

# Data verified and decrypted
decrypted_bytes = crypter.decrypt(encrypted, :sign)

# Decrypted data (Bytes)
puts decrypted_bytes

# Convert Bytes to String
puts String.new(decrypted_bytes)

Signer

Sign and verify given data.

require "crypt"
require "crypt/signer"

data = "Hello Crystal!"
secret = "super secret"
signer = Crypt::Signer.new(secret)

# Sign the data
signed_data = signer.sign(data)

# => Encoded String, URL and filename safe alphabet (RFC 4648).
puts signed_data

# Verify the data integrity and get it
puts signer.verify(signed_data)         # => "Hello Crystal!"
puts signer.verify(signed_data) == data # => true

API doc: Crypt::Signer

Bcrypt password

Generate, read and verify Crypto::Bcrypt hashes:

require "crypt"
require "crypt/bcrypt"

password = Crypt.create_bcrypt_password("super secret", cost: 10)
# => $2a$10$rI4xRiuAN2fyiKwynO6PPuorfuoM4L2PVv6hlnVJEmNLjqcibAfHq

password.verify("wrong secret") # => false
password.verify("super secret") # => true

API doc: Crypt.create_bcrypt_password


Loads a Bcrypt password hash.

require "crypt"
require "crypt/bcrypt"

password = Crypt.load_bcrypt_password(
  "$2a$10$X6rw/jDiLBuzHV./JjBNXe8/Po4wTL0fhdDNdAdjcKN/Fup8tGCya"
)
password.version # => "2a"
password.salt    # => "X6rw/jDiLBuzHV./JjBNXe"
password.digest  # => "8/Po4wTL0fhdDNdAdjcKN/Fup8tGCya"

# password.verify("some secret")

API doc: Crypt.load_bcrypt_password

Secure random

require "crypt"
require "crypt/random"

See API doc:

Key derivation

Key derivation PKCS5/PBKDF2 (Password-Based Key Derivation Function 2)

require "crypt"
require "crypt/key-deriv"
require "crypt/random"

password = "My password"
salt = Crypt.random_string(16)

# key size: 64
Crypt.key_deriv(password, salt)

# key size: 10
Crypt.key_deriv(password, salt, key_size: 10)

# iteration: 2000
Crypt.key_deriv(password, salt, iter: 2000)

# algo: sha256
Crypt.key_deriv(password, salt, algo: :sha256)

API doc: Crypt.key_deriv

Contributing

  1. Fork it (https://github.com/nicolab/crystal-crypt/fork)
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

Development

One line:

./scripts/develop

or splitted:

Terminal 1:

docker-compose up

Terminal 2:

# host
docker-compose exec app bash

# container
just develop

When you are done, clean and check the code:

# container
just format

# host
./scripts/check

LICENSE

MIT (c) 2020, Nicolas Talle.

Author

| Nicolas Tallefourtane - Nicolab.net | |---| | Nicolas Talle | | Make a donation via Paypal |