class Botan::Cipher
Examples¶ ↑
examples/cipher.rb¶ ↑
{include:file:examples/cipher.rb}
Public Class Methods
Creates a new cipher instance for decryption.
@param algo [String] the algorithm to use (example: AES-128/CTR-BE) @return [Botan::Cipher] the cipher instance
# File lib/botan/cipher.rb, line 50 def self.decryption(algo) Cipher.new(algo, encrypt: false) end
@api private
# File lib/botan/cipher.rb, line 34 def self.destroy(ptr) LibBotan.botan_cipher_destroy(ptr) end
Creates a new cipher instance for encryption.
@param algo [String] the algorithm to use (example: AES-128/CTR-BE) @return [Botan::Cipher] the cipher instance
# File lib/botan/cipher.rb, line 42 def self.encryption(algo) Cipher.new(algo, encrypt: true) end
Prefer the shortcuts {encryption} and {decryption} instead.
@param algo [String] the algorithm to use (example: AES-128/CTR-BE) @param encrypt [Boolean] true if this will be used for encryption,
false if it will be used for decryption.
# File lib/botan/cipher.rb, line 24 def initialize(algo, encrypt:) flags = encrypt ? 0 : 1 ptr = FFI::MemoryPointer.new(:pointer) Botan.call_ffi(:botan_cipher_init, ptr, algo, flags) ptr = ptr.read_pointer raise Botan::Error, 'botan_cipher_init returned NULL' if ptr.null? @ptr = FFI::AutoPointer.new(ptr, self.class.method(:destroy)) end
Public Instance Methods
Sets the associated data when using AEAD modes.
This should be called after {#key=} and before {#iv=}.
@param ad [String] the associated data
# File lib/botan/cipher.rb, line 145 def auth_data=(ad) ad_buf = FFI::MemoryPointer.from_data(ad) Botan.call_ffi(:botan_cipher_set_associated_data, @ptr, ad_buf, ad.size) end
Determines whether this is an AEAD mode.
@return [Boolean] true if this is an AEAD mode
# File lib/botan/cipher.rb, line 98 def authenticated? tag_length.positive? end
Retrieves the default nonce length for the cipher.
@return [Integer]
# File lib/botan/cipher.rb, line 57 def default_nonce_length length_ptr = FFI::MemoryPointer.new(:size_t) Botan.call_ffi(:botan_cipher_get_default_nonce_length, @ptr, length_ptr) length_ptr.read(:size_t) end
Finalize the message processing.
It is perfectly valid to skip {#update} and pass your entire message here.
Note: Some ciphers may require a final piece of data of a certain size. See minimum_final_size in the Botan
documentation.
@param data [String] the data, if any @return [String] the ciphertext or plaintext
# File lib/botan/cipher.rb, line 169 def finish(data = nil) _update(data, final: true) end
# File lib/botan/cipher.rb, line 173 def inspect Botan.inspect_ptr(self) end
Sets the IV to be used for the cipher.
This should generally be called after {#key=} or after {#auth_data=} (if using AEAD).
@param iv [String] the IV
# File lib/botan/cipher.rb, line 136 def iv=(iv) start(iv) end
Sets the key to be used for the cipher.
This should generally be the first thing called after creating a new cipher instance (or after reset).
@param key [String] the key
# File lib/botan/cipher.rb, line 125 def key=(key) key_buf = FFI::MemoryPointer.from_data(key) Botan.call_ffi(:botan_cipher_set_key, @ptr, key_buf, key_buf.size) end
Retrieves the maximum key length for the cipher.
@return [Integer]
# File lib/botan/cipher.rb, line 82 def key_length_max key_lengths[1] end
Retrieves the minimum key length for the cipher.
@return [Integer]
# File lib/botan/cipher.rb, line 75 def key_length_min key_lengths[0] end
Resets the cipher state.
@return [self]
# File lib/botan/cipher.rb, line 114 def reset Botan.call_ffi(:botan_cipher_clear, @ptr) self end
Retrieves the tag length when using AEAD modes.
@return [Integer]
# File lib/botan/cipher.rb, line 89 def tag_length length_ptr = FFI::MemoryPointer.new(:size_t) Botan.call_ffi(:botan_cipher_get_tag_length, @ptr, length_ptr) length_ptr.read(:size_t) end
Process the data (encrypt/decrypt).
@param data [String] the data to encrypt or decrypt.
The size should likely be a multiple of {#update_granularity}.
@return [String] the ciphertext or plaintext
# File lib/botan/cipher.rb, line 155 def update(data) _update(data, final: false) end
Retrieves the update granularity for the cipher.
@return [Integer]
# File lib/botan/cipher.rb, line 66 def update_granularity gran_ptr = FFI::MemoryPointer.new(:size_t) Botan.call_ffi(:botan_cipher_get_update_granularity, @ptr, gran_ptr) gran_ptr.read(:size_t) end
Checks whether a nonce length is valid for this cipher.
@param nonce_len [Integer] the nonce length to check @return [Boolean] true if the provided nonce length is valid
# File lib/botan/cipher.rb, line 106 def valid_nonce_length?(nonce_len) rc = Botan.call_ffi_rc(:botan_cipher_valid_nonce_length, @ptr, nonce_len) rc == 1 end
Private Instance Methods
# File lib/botan/cipher.rb, line 191 def _update(data, final:) inp = data ? data : '' flags = final ? 1 : 0 out_buf_size = inp.bytesize + (final ? tag_length : 0) # FIXME: botan currently lacks a way of determining the size required # here, taking in to account padding mechanism, etc. out_buf_size += 128 out_buf = FFI::MemoryPointer.new(:uint8, out_buf_size) out_written_ptr = FFI::MemoryPointer.new(:size_t) input_buf = FFI::MemoryPointer.from_data(inp) inp_consumed_ptr = FFI::MemoryPointer.new(:size_t) Botan.call_ffi(:botan_cipher_update, @ptr, flags, out_buf, out_buf.size, out_written_ptr, input_buf, input_buf.size, inp_consumed_ptr) consumed = inp_consumed_ptr.read(:size_t) if consumed != inp.bytesize raise Botan::Error, 'botan_cipher_update did not consume all input' \ " (#{consumed} out of #{inp.bytesize} bytes)" end out_buf.read_bytes(out_written_ptr.read(:size_t)) end
# File lib/botan/cipher.rb, line 184 def key_lengths kmin_ptr = FFI::MemoryPointer.new(:size_t) kmax_ptr = FFI::MemoryPointer.new(:size_t) Botan.call_ffi(:botan_cipher_query_keylen, @ptr, kmin_ptr, kmax_ptr) [kmin_ptr.read(:size_t), kmax_ptr.read(:size_t)] end
# File lib/botan/cipher.rb, line 179 def start(nonce) nonce_buf = FFI::MemoryPointer.from_data(nonce) Botan.call_ffi(:botan_cipher_start, @ptr, nonce_buf, nonce_buf.size) end