Class: MasterCrypt

Inherits:
Object
  • Object
show all
Defined in:
lib/master_crypt.rb,
lib/master_crypt/version.rb

Defined Under Namespace

Classes: CryptoError

Constant Summary collapse

VERSION =
"0.0.5"

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(master_key) ⇒ MasterCrypt

Create a new MasterCrypt object with a master key which is used in ‘master_key_encrypt` and `master_key_decrypt`

Parameters:

  • Master (String)

    key

Raises:

  • (ArgumentError)


15
16
17
18
# File 'lib/master_crypt.rb', line 15

def initialize(master_key)
  raise ArgumentError, "Master key must not be blank" if master_key.nil? || master_key.empty?
  @master_key = master_key
end

Class Method Details

.decrypt(encrypted_data, secret_key) ⇒ String

Decrypts encrypted data with a provided secret key

Parameters:

  • encrypted_data (String)

    Base64 representation of encrypted data

  • secret_key (String)

    Secret key to be used to decrypt data

Returns:

  • (String)

    Decrypted plaintext data

Raises:



88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/master_crypt.rb', line 88

def decrypt(encrypted_data, secret_key)
  encrypted_data64, encrypted_random_keys64_joined = Base64.strict_decode64(encrypted_data).split("|", 2)

  encrypted_random_keys64 = encrypted_random_keys64_joined.split(":")
  key = find_key(encrypted_random_keys64, secret_key)

  box = RbNaCl::SimpleBox.from_secret_key(key)

  ciphertext = Base64.strict_decode64(encrypted_data64)
  box.decrypt(ciphertext).force_encoding(Encoding::UTF_8)
rescue RbNaCl::CryptoError => e
  raise CryptoError, e.message
end

.encrypt(plaintext, secret_keys) ⇒ String

Encrypts plaintext data with a list of secret keys

Parameters:

  • plaintext (String)

    Plaintext data to be encrypted

  • secret_keys (Array<String>)

    A list of secret keys to be used for encrypting data

Returns:

  • (String)

    Base64 representation of encrypted data

Raises:

  • (ArgumentError)

    When secret keys are missing or blank



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/master_crypt.rb', line 54

def encrypt(plaintext, secret_keys)
  raise ArgumentError, "At least 1 secret key is required" if !secret_keys.is_a?(Array) || secret_keys.empty?
  raise ArgumentError, "Secret keys must not be blank" unless secret_keys.select(&:empty?).empty?
  # there's no point in using the same key multiple times
  secret_keys.uniq!

  random_key = RbNaCl::Random.random_bytes(RbNaCl::SecretBox.key_bytes)
  # encrypt data with random_key
  box = RbNaCl::SimpleBox.from_secret_key(random_key)

  encrypted_data = box.encrypt(plaintext)
  encrypted_data64 = Base64.strict_encode64(encrypted_data)

  # encrypt random_kets with each secret
  encrypted_random_keys64 = secret_keys.collect do |secret|
    key = generate_key_from_secret(secret)
    box = RbNaCl::SimpleBox.from_secret_key(key)

    encrypted_random_key = box.encrypt(random_key)
    encrypted_random_key64 = Base64.strict_encode64(encrypted_random_key)
    encrypted_random_key64
  end
  # encrypted_data|encrypted_random_key1:encrypted_random_key2:...
  Base64.strict_encode64(encrypted_data64 + "|" + encrypted_random_keys64.join(":"))
end

Instance Method Details

#master_key_decrypt(encrypted_data) ⇒ String

Decrypts encrypted data with the master key

Parameters:

  • encrypted_data (String)

    Base64 representation of encrypted data

Returns:

  • (String)

    Decrypted plaintext data

Raises:



41
42
43
# File 'lib/master_crypt.rb', line 41

def master_key_decrypt(encrypted_data)
  self.class.decrypt(encrypted_data, @master_key)
end

#master_key_encrypt(plaintext, secret_keys = []) ⇒ String

Encrypts plaintext data with the master key and an optional list of additional secret keys

additional secret keys to be used for encrypting data

Parameters:

  • plaintext (String)

    Plaintext data to be encrypted

  • secret_keys (Array<String>) (defaults to: [])

    Optional list of

Returns:

  • (String)

    Base64 representation of encrypted data

Raises:

  • (ArgumentError)

    When secret keys are missing or blank



30
31
32
# File 'lib/master_crypt.rb', line 30

def master_key_encrypt(plaintext, secret_keys = [])
  self.class.encrypt(plaintext, [@master_key] + Array(secret_keys))
end