ruby-botan
¶ ↑
ruby-botan is a Ruby interface to Botan.
Note: Refer to the Botan
documentation in addition to the documentation here. In particular, this note from the Botan
manual applies here as well:
You should have some knowledge of cryptography before trying to use the library. This is an area where it is very easy to make mistakes, and where things are often subtle and/or counterintuitive. Obviously the library tries to provide things at a high level precisely to minimize the number of ways things can go wrong, but naive use will almost certainly not result in a secure system.
Requirements¶ ↑
Ruby¶ ↑
ruby-botan is currently tested to work with:
-
Ruby 2.3
-
Ruby 2.4
Botan
¶ ↑
Botan version 2.2 or newer is required.
Basic Usage¶ ↑
The samples below are meant to be a brief introduction to the library. Refer to the full documentation for full details.
Also see the examples directory for examples on using various parts of the library.
Utilities¶ ↑
Botan.hex_encode("\x01\x02\x03\x04") Botan.hex_decode('01020304')
RNG - Random Number Generation¶ ↑
# shortcut method that uses default RNG to get 10 bytes Botan::RNG.get(10) # create a different type of RNG, and reseed from the system RNG rng = Botan::RNG.new('user') rng.reseed rng.get(5)
Digest / Hash¶ ↑
There are a few different ways to utilize Digest. Which method you choose may depend on whether the data is immediately available in full, or whether it is becoming available over time.
Simple One-Shot Hash¶ ↑
If you simply want to hash some data that you have immediately available in full, you may want to do something like the following.
Botan::Digest::MD5.digest('my data') Botan::Digest::SHA256.hexdigest('my data')
You may also use a longer form, in case there is not a pre-defined class (like MD5
and SHA256
above). For example:
Botan::Digest.digest('Comb4P(SHA-160,RIPEMD-160)', 'my data') Botan::Digest.hexdigest('SHA-3(224)', 'my data')
Continuously Updated Hash¶ ↑
If you have a stream of incoming data that is not readily available that you want to hash, you may proceed in a couple of ways:
# MD5 md5 = Botan::Digest::MD5.new md5.update('my ') md5 << 'data' md5.hexdigest # Comb4P hash combiner hash = Botan::Digest.new('Comb4P(SHA-160,RIPEMD-160)') hash << 'my ' hash << 'data' hash.hexdigest
Cipher¶ ↑
# encrypt enc = Botan::Cipher.encryption('AES-128/CBC/PKCS7') key = Botan::RNG.get(enc.key_length_max) iv = Botan::RNG.get(enc.default_nonce_length) enc.key = key enc.iv = iv ciphertext = enc.finish('my data') # decrypt dec = Botan::Cipher.decryption('AES-128/CBC/PKCS7') dec.key = key dec.iv = iv plaintext = dec.finish(ciphertext)
BCrypt¶ ↑
The Botan::BCrypt
module supports simple bcrypt password hashing.
# generate password hash password_input = gets.chomp password_hash = Botan::BCrypt.hash(password_input, work_factor: 10) # check password password_input = gets.chomp Botan::BCrypt.valid?(password: password_input, phash: password_hash)
KDF - Key Derivation Functions¶ ↑
The Botan::KDF
module has a few different functions for key derivation.
Botan::KDF.kdf(algo: 'KDF2(SHA-160)', secret: Botan::RNG.get(9), salt: Botan::RNG.get(7), key_length: 32) Botan::KDF.pbkdf(algo: 'PBKDF2(CMAC(Blowfish))', password: 'some long passphrase', iterations: 150_000, key_length: 16) Botan::KDF.pbkdf_timed(algo: 'PBKDF2(SHA-256)', password: 'my secret passphrase', key_length: 8, milliseconds: 100)
MAC - Message Authentication Code¶ ↑
hmac = Botan::MAC.new('HMAC(SHA-256)') hmac.key = Botan.hex_decode('0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20') hmac << "\x61\x62\x63" hmac.hexdigest
PK - Public Key Cryptography¶ ↑
The Botan::PK
module exposes functionality for public key loading, exporting, encryption, decryption, signing, and verification.
Key Generation¶ ↑
# generate a 4096-bit RSA key privkey = Botan::PK::PrivateKey.generate('RSA', params: '4096') # generate an ECDSA key with group secp384r1 privkey = Botan::PK::PrivateKey.generate('ECDSA', params: 'secp384r1') # generate a 4096-bit ElGamal key privkey = Botan::PK::PrivateKey.generate('ElGamal', params: 'modp/ietf/4096')
Key Loading¶ ↑
# load a public key pubkey = Botan::PK::PublicKey.from_data(File.read('some_file.pem')) # load an encrypted private key privkey = Botan::PK::PrivateKey.from_data(File.read('some_file.pem'), password: 'my key password') # load an unencrypted private key privkey = Botan::PK::PrivateKey.from_data(File.read('some_file.pem'))
Key Exporting¶ ↑
# private key export (PEM) pem = privkey.export_pem(password: 'my secret password') # public key export (PEM) pem = pubkey.export_pem
Encryption / Decryption¶ ↑
# using defaults ciphertext = pubkey.encrypt('my data') plaintext = privkey.decrypt(ciphertext)
Signing / Verifying¶ ↑
data = 'my data' # using defaults signature = privkey.sign(data) valid = pubkey.verify(data: data, signature: signature)
X.509 Certificates¶ ↑
Certificate Loading¶ ↑
# load from a file cert = Botan::X509::Certificate.from_file('my cert.crt') # load from some data in memory cert = Botan::X509::Certificate.from_data(File.read('my cert.crt'))
Certificate Properties¶ ↑
# fingerprint fpr = cert.fingerprint('SHA-256') # subject's public key pubkey = cert.subject_public_key