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.
ruby-botan is currently tested to work with:
- Ruby 2.5
- Ruby 2.4
Botan version 2.2 or newer is required.
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.
RNG - Random Number Generation
# shortcut method that uses default RNG to get 10 bytes ::.(10) # create a different type of RNG, and reseed from the system RNG rng = ::.('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.
::::MD5.digest('my data') ::::SHA256.hexdigest('my data')
You may also use a longer form, in case there is not a pre-defined class (like
SHA256 above). For example:
::.('Comb4P(SHA-160,RIPEMD-160)', 'my data') ::.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 = ::::MD5.new md5.update('my ') md5 << 'data' md5.hexdigest # Comb4P hash combiner hash = ::.('Comb4P(SHA-160,RIPEMD-160)') hash << 'my ' hash << 'data' hash.hexdigest
# encrypt enc = ::.('AES-128/CBC/PKCS7') key = ::.(enc.key_length_max) iv = ::.(enc.default_nonce_length) enc.key = key enc.iv = iv ciphertext = enc.finish('my data') # decrypt dec = ::.('AES-128/CBC/PKCS7') dec.key = key dec.iv = iv plaintext = dec.finish(ciphertext)
Botan::BCrypt module supports simple bcrypt password hashing.
# generate password hash password_input = gets.chomp password_hash = ::.(password_input, work_factor: 10) # check password password_input = gets.chomp ::.(password: password_input, phash: password_hash)
KDF - Key Derivation Functions
Botan::KDF module has a few different functions for key derivation.
::.(algo: 'KDF2(SHA-160)', secret: ::.(9), salt: ::.(7), key_length: 32) ::.(algo: 'PBKDF2(CMAC(Blowfish))', password: 'some long passphrase', iterations: 150_000, key_length: 16) ::.(algo: 'PBKDF2(SHA-256)', password: 'my secret passphrase', key_length: 8, milliseconds: 100)
MAC - Message Authentication Code
hmac = ::.('HMAC(SHA-256)') hmac.key = .('0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20') hmac << "\x61\x62\x63" hmac.hexdigest
PK - Public Key Cryptography
Botan::PK module exposes functionality for public key loading, exporting, encryption, decryption, signing, and verification.
# generate a 4096-bit RSA key privkey = ::::.('RSA', params: '4096') # generate an ECDSA key with group secp384r1 privkey = ::::.('ECDSA', params: 'secp384r1') # generate a 4096-bit ElGamal key privkey = ::::.('ElGamal', params: 'modp/ietf/4096')
# load a public key pubkey = ::::.(File.read('some_file.pem')) # load an encrypted private key privkey = ::::.(File.read('some_file.pem'), password: 'my key password') # load an unencrypted private key privkey = ::::.(File.read('some_file.pem'))
# 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)
# load from a file cert = ::::.('my cert.crt') # load from some data in memory cert = ::::.(File.read('my cert.crt'))
# fingerprint fpr = cert.fingerprint('SHA-256') # subject's public key pubkey = cert.subject_public_key