Module: Conceal

Defined in:
lib/conceal.rb,
lib/conceal/cli.rb,
lib/conceal/version.rb

Defined Under Namespace

Classes: CLI

Constant Summary collapse

FORMAT_VERSION =
1
FIELD_SEPARATOR =
':'
VERSION =
'0.2.0'

Class Method Summary collapse

Class Method Details

.decrypt(data, opts = {}) ⇒ Object

Decrypts the given encrypted string.

Parameters:

  • data (String)

    the encrypted string to decrypt

  • opts (Hash) (defaults to: {})

    additional options

Options Hash (opts):

  • :key (String)

    the secret shared key

Raises:

  • (ArgumentError)


58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/conceal.rb', line 58

def decrypt(data, opts = {})
  key = opts[:key]
  raise ArgumentError.new(':key option missing') if key.to_s.empty?

  ver, algorithm, iv64, salt64, hmac64, ciphertext64 = data.split(FIELD_SEPARATOR, 6)
  raise ArgumentError.new('ciphertext has unknown version') unless ver == FORMAT_VERSION.to_s

  iv         = Base64.decode64(iv64)
  salt       = Base64.decode64(salt64)
  hmac       = Base64.decode64(hmac64)
  ciphertext = Base64.decode64(ciphertext64)

  # validate the hmac
  digest = OpenSSL::Digest.new('sha256')
  actual_hmac = OpenSSL::HMAC.digest(digest, key, ciphertext)
  raise ArgumentError.new('HMAC mismatch') unless actual_hmac == hmac

  # decrypt
  cipher = OpenSSL::Cipher::Cipher.new(algorithm)
  cipher.decrypt
  cipher.iv = iv
  cipher.key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(key, salt, 2000, cipher.key_len)

  plaintext = cipher.update(ciphertext)
  plaintext << cipher.final
  plaintext
end

.encrypt(plaintext, opts = {}) ⇒ Object

Encrypts the given plaintext string.

Parameters:

  • plaintext (String)

    the plaintext string to encrypt

  • opts (Hash) (defaults to: {})

    additional options

Options Hash (opts):

  • :algorithm (String)

    the cipher algorithm to use (defaults to ‘aes-25c-cbc’)

  • :key (String)

    the secret shared key

Raises:

  • (ArgumentError)


18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/conceal.rb', line 18

def encrypt(plaintext, opts = {})
  opts = {
    algorithm: 'aes-256-cbc',
  }.merge(opts)
  key       = opts[:key]
  algorithm = opts[:algorithm]
  raise ArgumentError.new(':key option missing') if key.to_s.empty?
  salt = SecureRandom.hex(128)

  # setup the cipher
  cipher = OpenSSL::Cipher::Cipher.new(algorithm)
  cipher.encrypt
  iv = cipher.random_iv
  cipher.iv = iv
  cipher.key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(key, salt, 2000, cipher.key_len)

  # encrypt
  ciphertext = cipher.update(plaintext)
  ciphertext << cipher.final

  # MAC
  digest = OpenSSL::Digest.new('sha256')
  hmac = OpenSSL::HMAC.digest(digest, key, ciphertext)

  [
    FORMAT_VERSION,
    algorithm,
    encode64(iv),
    encode64(salt),
    encode64(hmac),
    encode64(ciphertext),
  ].join(FIELD_SEPARATOR)
end