Class: OnePassword::Encryption

Inherits:
Object
  • Object
show all
Defined in:
lib/one_password/encryption.rb

Constant Summary collapse

ZERO_IV =
"\x00" * 8
NR =
10
NK =
4

Class Method Summary collapse

Class Method Details

.decrypt_using_key(encrypted, encryption_key) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/one_password/encryption.rb', line 28

def self.decrypt_using_key(encrypted, encryption_key)
  encrypted = Base64.decode64(encrypted)

  if Encryption.salted?(encrypted)
    salt      = encrypted[8, 8]
    encrypted = encrypted[16..-1]

    key, iv = Encryption.open_ssl_key(encryption_key, salt)
  else
    key = OpenSSL::Digest::MD5.digest(encryption_key)
    iv  = Encryption::ZERO_IV
  end

  plain_text = Encryption.decrypt_using_key_and_ivec(encrypted, key, iv)


  CGI::unescape(CGI::escape(plain_text))

end

.decrypt_using_key_and_ivec(encrypted, key, iv) ⇒ Object



48
49
50
51
52
53
54
# File 'lib/one_password/encryption.rb', line 48

def self.decrypt_using_key_and_ivec(encrypted, key, iv)
  aes = OpenSSL::Cipher.new('AES-128-CBC')
  aes.decrypt
  aes.key = key
  aes.iv  = iv
  aes.update(encrypted) << aes.final
end

.decrypt_using_pbkdf2(data, password, iterations) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/one_password/encryption.rb', line 12

def self.decrypt_using_pbkdf2(data, password, iterations)
  encrypted = Base64.decode64(data)
  salt      = ZERO_IV
  if salted?(encrypted)
    salt      = encrypted[8, 8]
    encrypted = encrypted[16..-1]
  end

  derived_key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(password, salt, iterations, 32)

  key = derived_key.slice(0..15)
  iv  = derived_key.slice(16..-1)

  decrypt_using_key_and_ivec(encrypted, key, iv)
end

.open_ssl_key(password, salt) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/one_password/encryption.rb', line 60

def self.open_ssl_key(password, salt)
  rounds   = NR >= 12 ? 3 : 2
  data00   = password + salt
  md5_hash = [OpenSSL::Digest::MD5.digest(data00)]
  result   = md5_hash[0]
  1.upto(rounds - 1) do |i|
    md5_hash[i] = OpenSSL::Digest::MD5.digest(md5_hash[i - 1] + data00)
    result      += md5_hash[i]
  end
  key = result.slice(0..(4 * NK - 1))
  iv  = result.slice((4 * NK)..(4 * NK + 15))
  [key, iv]
end

.salted?(string) ⇒ Boolean

Returns:

  • (Boolean)


56
57
58
# File 'lib/one_password/encryption.rb', line 56

def self.salted?(string)
  (string =~ /\ASalted__/)
end