class Darrrr::EncryptedData

Constants

AUTH_TAG_LENGTH
CIPHER
CIPHER_OPTIONS
CIPHER_VERSION
IV_LENGTH

This is the NIST recommended minimum: nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf

PROTOCOL_VERSION

Attributes

token_object[R]

Public Class Methods

build(data) click to toggle source

data: the value to encrypt.

returns an EncryptedData instance.

# File lib/darrrr/cryptors/default/encrypted_data.rb, line 43
def build(data)
  cipher = cipher(:encrypt)
  iv = SecureRandom.random_bytes(EncryptedData::IV_LENGTH)
  cipher.iv = iv
  cipher.auth_data = ""

  ciphertext = cipher.update(data.to_s) + cipher.final

  token = EncryptedDataIO.new.tap do |edata|
    edata.version = CIPHER_VERSION
    edata.auth_tag = cipher.auth_tag.bytes
    edata.iv = iv.bytes
    edata.ciphertext = ciphertext.bytes
  end

  new(token)
end
cipher(mode) click to toggle source

DRY helper for generating cipher objects

# File lib/darrrr/cryptors/default/encrypted_data.rb, line 78
def cipher(mode)
  unless CIPHER_OPTIONS.include?(mode)
    raise ArgumentError, "mode must be `encrypt` or `decrypt`"
  end

  OpenSSL::Cipher.new(EncryptedData::CIPHER).tap do |cipher|
    cipher.send(mode)
    cipher.key = [Darrrr.this_account_provider.instance_variable_get(:@symmetric_key)].pack("H*")
  end
end
parse(serialized_data) click to toggle source

serialized_data: the binary representation of a token.

returns an EncryptedData instance.

# File lib/darrrr/cryptors/default/encrypted_data.rb, line 64
def parse(serialized_data)
  data = new(EncryptedDataIO.new.read(serialized_data))

  # be extra paranoid, oracles and stuff
  if data.num_bytes != serialized_data.bytesize
    raise CryptoError, "Encypted data field includes unexpected extra bytes"
  end

  data
rescue IOError => e
  raise RecoveryTokenSerializationError, e.message
end

Private Class Methods

new(token_object) click to toggle source

token_object: an EncryptedDataIO instance instance.

# File lib/darrrr/cryptors/default/encrypted_data.rb, line 21
def initialize(token_object)
  raise TokenFormatError, "Version must be #{PROTOCOL_VERSION}. Supplied: #{token_object.version}" unless token_object.version == CIPHER_VERSION
  raise TokenFormatError, "Auth Tag must be 16 bytes" unless token_object.auth_tag.length == AUTH_TAG_LENGTH
  raise TokenFormatError, "IV must be 12 bytes" unless token_object.iv.length == IV_LENGTH
  @token_object = token_object
end

Public Instance Methods

decrypt() click to toggle source
# File lib/darrrr/cryptors/default/encrypted_data.rb, line 29
def decrypt
  cipher = self.class.cipher(:decrypt)
  cipher.iv = self.iv.to_binary_s
  cipher.auth_tag = self.auth_tag.to_binary_s
  cipher.auth_data = ""
  cipher.update(self.ciphertext.to_binary_s) + cipher.final
rescue OpenSSL::Cipher::CipherError => e
  raise CryptoError, "Unable to decrypt data: #{e}"
end