lastpass 1.2.0 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,8 @@
1
+ Version 1.2.1
2
+ -------------
3
+
4
+ - Fixed the decryption bug on long shared folder names.
5
+
1
6
  Version 1.2.0
2
7
  -------------
3
8
 
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
19
19
  s.add_dependency "httparty", "~> 0.13.0"
20
20
  s.add_dependency "pbkdf2-ruby", "~> 0.2.0"
21
21
 
22
- s.add_development_dependency "rake", "~> 10.1.0"
22
+ s.add_development_dependency "rake", "~> 10.3.0"
23
23
  s.add_development_dependency "rspec", "~> 2.14.0"
24
24
  s.add_development_dependency "coveralls", "~> 0.7.0"
25
25
 
@@ -6,6 +6,14 @@ module LastPass
6
6
  # OpenSSL constant
7
7
  RSA_PKCS1_OAEP_PADDING = 4
8
8
 
9
+ # Secure note types that contain account-like information
10
+ ALLOWED_SECURE_NOTE_TYPES = {
11
+ "Server" => true,
12
+ "Email Account" => true,
13
+ "Database" => true,
14
+ "Instant Messenger" => true,
15
+ }
16
+
9
17
  # Splits the blob into chucks grouped by kind.
10
18
  def self.extract_chunks blob
11
19
  chunks = []
@@ -28,13 +36,13 @@ module LastPass
28
36
  def self.parse_ACCT chunk, encryption_key
29
37
  StringIO.open chunk.payload do |io|
30
38
  id = read_item io
31
- name = decode_aes256_auto read_item(io), encryption_key
32
- group = decode_aes256_auto read_item(io), encryption_key
39
+ name = decode_aes256_plain_auto read_item(io), encryption_key
40
+ group = decode_aes256_plain_auto read_item(io), encryption_key
33
41
  url = decode_hex read_item io
34
- notes = decode_aes256_auto read_item(io), encryption_key
42
+ notes = decode_aes256_plain_auto read_item(io), encryption_key
35
43
  2.times { skip_item io }
36
- username = decode_aes256_auto read_item(io), encryption_key
37
- password = decode_aes256_auto read_item(io), encryption_key
44
+ username = decode_aes256_plain_auto read_item(io), encryption_key
45
+ password = decode_aes256_plain_auto read_item(io), encryption_key
38
46
  2.times { skip_item io }
39
47
  secure_note = read_item io
40
48
 
@@ -43,8 +51,7 @@ module LastPass
43
51
  17.times { skip_item io }
44
52
  secure_note_type = read_item io
45
53
 
46
- # Only "Server" secure note stores account information
47
- if secure_note_type != "Server"
54
+ if !ALLOWED_SECURE_NOTE_TYPES.key? secure_note_type
48
55
  return nil
49
56
  end
50
57
 
@@ -95,10 +102,10 @@ module LastPass
95
102
  key = if key.empty?
96
103
  decode_hex rsa_key.private_decrypt(encrypted_key, RSA_PKCS1_OAEP_PADDING)
97
104
  else
98
- decode_hex decode_aes256_auto(key, encryption_key)
105
+ decode_hex decode_aes256_plain_auto(key, encryption_key)
99
106
  end
100
107
 
101
- name = decode_aes256_auto encrypted_name, key
108
+ name = decode_aes256_base64_auto encrypted_name, key
102
109
 
103
110
  # TODO: Return an object, not a hash
104
111
  {id: id, name: name, encryption_key: key}
@@ -189,27 +196,29 @@ module LastPass
189
196
  Base64.decode64 data
190
197
  end
191
198
 
192
- # Guesses AES encoding/cipher from the length of the data.
193
- # Possible combinations are:
194
- # - ciphers: AES-256 EBC, AES-256 CBC
195
- # - encodings: plain, base64
196
- def self.decode_aes256_auto data, encryption_key
199
+ # Guesses AES cipher (EBC or CBD) from the length of the plain data.
200
+ def self.decode_aes256_plain_auto data, encryption_key
197
201
  length = data.length
198
- length16 = length % 16
199
- length64 = length % 64
200
202
 
201
203
  if length == 0
202
204
  ""
203
- elsif length16 == 0
204
- decode_aes256_ecb_plain data, encryption_key
205
- elsif length64 == 0 || length64 == 24 || length64 == 44
206
- decode_aes256_ecb_base64 data, encryption_key
207
- elsif length16 == 1
205
+ elsif data[0] == "!" && length % 16 == 1 && length > 32
208
206
  decode_aes256_cbc_plain data, encryption_key
209
- elsif length64 == 6 || length64 == 26 || length64 == 50
207
+ else
208
+ decode_aes256_ecb_plain data, encryption_key
209
+ end
210
+ end
211
+
212
+ # Guesses AES cipher (EBC or CBD) from the length of the base64 encoded data.
213
+ def self.decode_aes256_base64_auto data, encryption_key
214
+ length = data.length
215
+
216
+ if length == 0
217
+ ""
218
+ elsif data[0] == "!"
210
219
  decode_aes256_cbc_base64 data, encryption_key
211
220
  else
212
- raise RuntimeError, "'#{data.inspect}' doesn't seem to be AES-256 encrypted"
221
+ decode_aes256_ecb_base64 data, encryption_key
213
222
  end
214
223
  end
215
224
 
@@ -2,5 +2,5 @@
2
2
  # Licensed under the terms of the MIT license. See LICENCE for details.
3
3
 
4
4
  module LastPass
5
- VERSION = "1.2.0"
5
+ VERSION = "1.2.1"
6
6
  end
@@ -316,9 +316,9 @@ describe LastPass::Parser do
316
316
  end
317
317
  end
318
318
 
319
- describe ".decode_aes256_auto" do
319
+ describe ".decode_aes256_plain_auto" do
320
320
  def check encoded, decoded
321
- expect(LastPass::Parser.decode_aes256_auto encoded, encryption_key)
321
+ expect(LastPass::Parser.decode_aes256_plain_auto encoded, encryption_key)
322
322
  .to eq decoded
323
323
  end
324
324
 
@@ -331,13 +331,24 @@ describe LastPass::Parser do
331
331
  "All your base are belong to us"
332
332
  end
333
333
 
334
- it "decodes ECB/base64 string" do
335
- check "BNhd3Q3ZVODxk9c0C788NUPTIfYnZuxXfkghtMJ8jVM=",
334
+ it "decodes CBC/plain string" do
335
+ check "IcokDWmjOkKtLpZehWKL6666Uj6fNXPpX6lLWlou+1Lrwb+D3ymP6BAwd6C0TB3hSA==".decode64,
336
336
  "All your base are belong to us"
337
337
  end
338
+ end
338
339
 
339
- it "decodes CBC/plain string" do
340
- check "IcokDWmjOkKtLpZehWKL6666Uj6fNXPpX6lLWlou+1Lrwb+D3ymP6BAwd6C0TB3hSA==".decode64,
340
+ describe ".decode_aes256_base64_auto" do
341
+ def check encoded, decoded
342
+ expect(LastPass::Parser.decode_aes256_base64_auto encoded, encryption_key)
343
+ .to eq decoded
344
+ end
345
+
346
+ it "decodes a blank string" do
347
+ check "", ""
348
+ end
349
+
350
+ it "decodes ECB/base64 string" do
351
+ check "BNhd3Q3ZVODxk9c0C788NUPTIfYnZuxXfkghtMJ8jVM=",
341
352
  "All your base are belong to us"
342
353
  end
343
354
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lastpass
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.2.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-04-13 00:00:00.000000000 Z
12
+ date: 2014-06-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: httparty
@@ -50,7 +50,7 @@ dependencies:
50
50
  requirements:
51
51
  - - ~>
52
52
  - !ruby/object:Gem::Version
53
- version: 10.1.0
53
+ version: 10.3.0
54
54
  type: :development
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
@@ -58,7 +58,7 @@ dependencies:
58
58
  requirements:
59
59
  - - ~>
60
60
  - !ruby/object:Gem::Version
61
- version: 10.1.0
61
+ version: 10.3.0
62
62
  - !ruby/object:Gem::Dependency
63
63
  name: rspec
64
64
  requirement: !ruby/object:Gem::Requirement