Class: Chef::EncryptedDataBagItem::Encryptor

Inherits:
Object
  • Object
show all
Defined in:
lib/chef/encrypted_data_bag_item.rb

Overview

Implementation class for converting plaintext data bag item values to an encrypted value, including any necessary wrappers and metadata.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(plaintext_data, key, iv = nil) ⇒ Encryptor

Create a new Encryptor for data, which will be encrypted with the given key.

Arguments:

  • data: An object of any type that can be serialized to json

  • key: A String representing the desired passphrase

  • iv: The optional iv parameter is intended for testing use only. When

not supplied, Encryptor will use OpenSSL to generate a secure random IV, which is what you want.



79
80
81
82
83
# File 'lib/chef/encrypted_data_bag_item.rb', line 79

def initialize(plaintext_data, key, iv=nil)
  @plaintext_data = plaintext_data
  @key = key
  @iv = iv && Base64.decode64(iv)
end

Instance Attribute Details

#keyObject (readonly)

Returns the value of attribute key.



67
68
69
# File 'lib/chef/encrypted_data_bag_item.rb', line 67

def key
  @key
end

#plaintext_dataObject (readonly)

Returns the value of attribute plaintext_data.



68
69
70
# File 'lib/chef/encrypted_data_bag_item.rb', line 68

def plaintext_data
  @plaintext_data
end

Instance Method Details

#encrypted_dataObject

Encrypts and Base64 encodes serialized_data



118
119
120
121
122
123
124
# File 'lib/chef/encrypted_data_bag_item.rb', line 118

def encrypted_data
  @encrypted_data ||= begin
    enc_data = openssl_encryptor.update(serialized_data)
    enc_data << openssl_encryptor.final
    Base64.encode64(enc_data)
  end
end

#for_encrypted_itemObject

Returns a wrapped and encrypted version of plaintext_data suitable for using as the value in an encrypted data bag item.



87
88
89
90
91
92
93
94
# File 'lib/chef/encrypted_data_bag_item.rb', line 87

def for_encrypted_item
  {
    "encrypted_data" => encrypted_data,
    "iv" => Base64.encode64(iv),
    "version" => 1,
    "cipher" => ALGORITHM
  }
end

#ivObject

Generates or returns the IV.



97
98
99
100
101
102
# File 'lib/chef/encrypted_data_bag_item.rb', line 97

def iv
  # Generated IV comes from OpenSSL::Cipher::Cipher#random_iv
  # This gets generated when +openssl_encryptor+ gets created.
  openssl_encryptor if @iv.nil?
  @iv
end

#openssl_encryptorObject

Generates (and memoizes) an OpenSSL::Cipher::Cipher object and configures it for the specified iv and encryption key.



106
107
108
109
110
111
112
113
114
115
# File 'lib/chef/encrypted_data_bag_item.rb', line 106

def openssl_encryptor
  @openssl_encryptor ||= begin
    encryptor = OpenSSL::Cipher::Cipher.new(ALGORITHM)
    encryptor.encrypt
    @iv ||= encryptor.random_iv
    encryptor.iv = @iv
    encryptor.key = Digest::SHA256.digest(key)
    encryptor
  end
end

#serialized_dataObject

Wraps the data in a single key Hash (JSON Object) and converts to JSON. The wrapper is required because we accept values (such as Integers or Strings) that do not produce valid JSON when serialized without the wrapper.



130
131
132
# File 'lib/chef/encrypted_data_bag_item.rb', line 130

def serialized_data
  Yajl::Encoder.encode(:json_wrapper => plaintext_data)
end