class Botan::Cipher

Cipher

Examples

examples/cipher.rb

{include:file:examples/cipher.rb}

Public Class Methods

decryption(algo) click to toggle source

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
destroy(ptr) click to toggle source

@api private

# File lib/botan/cipher.rb, line 34
def self.destroy(ptr)
  LibBotan.botan_cipher_destroy(ptr)
end
encryption(algo) click to toggle source

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
new(algo, encrypt:) click to toggle source

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

auth_data=(ad) click to toggle source

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
authenticated?() click to toggle source

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
default_nonce_length() click to toggle source

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
finish(data = nil) click to toggle source

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
inspect() click to toggle source
# File lib/botan/cipher.rb, line 173
def inspect
  Botan.inspect_ptr(self)
end
iv=(iv) click to toggle source

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
key=(key) click to toggle source

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
key_length_max() click to toggle source

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
key_length_min() click to toggle source

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
reset() click to toggle source

Resets the cipher state.

@return [self]

# File lib/botan/cipher.rb, line 114
def reset
  Botan.call_ffi(:botan_cipher_clear, @ptr)
  self
end
tag_length() click to toggle source

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
update(data) click to toggle source

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
update_granularity() click to toggle source

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
valid_nonce_length?(nonce_len) click to toggle source

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

_update(data, final:) click to toggle source
# 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
key_lengths() click to toggle source
# 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
start(nonce) click to toggle source
# 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