pws 1.0.5 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +60 -0
- data/{LICENSE → LICENSE.txt} +1 -1
- data/README.md +1 -1
- data/lib/pws/format/1.0.rb +28 -29
- data/lib/pws/version.rb +1 -1
- data/pws.gemspec +2 -2
- metadata +27 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cc1bda6125f66bd7dab182c1f36e041ed31c508a
|
4
|
+
data.tar.gz: bd1b9682fc619df19892b53bf6ffc3697bfa9b2c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d9ff5f1633c6b41bec56714684fc7ddc38068b4f5e31a33d151bf0cfc575e6ade4e42313d2e847d3dde06357a015111d82d124f1a2c0a5f31a0626df062c6057
|
7
|
+
data.tar.gz: 47dff7dc77be80f60ad44407877ad849b9ea79ab0fe7846711e8b7ec5932c4f8704e2d596fe0b3aac318ac2392608b290dd44f9584e117698e0573ffdef314b2
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
== 1.0.6
|
2
|
+
* Ruby 2.2 compat (remove digest/hmac)
|
3
|
+
|
4
|
+
== 1.0.5
|
5
|
+
* Ruby 2 compat
|
6
|
+
* Use "pbkdf2-ruby" instead of "pbkdf2" gem
|
7
|
+
* Bump paint/clipboard dependencies
|
8
|
+
* Remove zucker dependency
|
9
|
+
|
10
|
+
== 1.0.4
|
11
|
+
* You can now get your passwords using as short shortcuts as possible powered by stdlib's abbrev library
|
12
|
+
|
13
|
+
== 1.0.3
|
14
|
+
* Fix single options (like --cwd) to really be single
|
15
|
+
|
16
|
+
== 1.0.2
|
17
|
+
* Output a small warning when using Ruby fallback (pbkdf2 is only implemented in openssl >= 1.0)
|
18
|
+
* New --cwd option for easy access to .pws files in the current directory
|
19
|
+
|
20
|
+
== 1.0.1
|
21
|
+
* Ruby fallback if pbkdf2 is not available in OpenSSL
|
22
|
+
|
23
|
+
== 1.0.0
|
24
|
+
* New file format, the old one needs to be converted by calling `pws resave --in 0.9 --out 1.0`
|
25
|
+
* Bruteforce protection by using pbkdf2, you can choose the number of iterations (default: 75_000)
|
26
|
+
* Password files have now better integrity checks
|
27
|
+
* Store and display updated_at timestamp for entries
|
28
|
+
* Don't rely on Ruby marshalling
|
29
|
+
* New actions: update (updates an entry, cannot be used to create one), update-gen
|
30
|
+
* New action: resave (useful for converting safes)
|
31
|
+
* Better exit statuses
|
32
|
+
* Misc tweaks (password confirmation when creating, etc)
|
33
|
+
|
34
|
+
== 0.9.2
|
35
|
+
* Configure your favourite waiting time, password length and password char pool using ENV options
|
36
|
+
* More flexible command line argument parsing, allows allows overriding of the ENV options
|
37
|
+
* Show action takes optional regex filter argument
|
38
|
+
* Creating new safes also creates the directory for them and sets permissions to 0600
|
39
|
+
|
40
|
+
== 0.9.1
|
41
|
+
* Add password confirmation when changing master password
|
42
|
+
|
43
|
+
== 0.9.0
|
44
|
+
* It's working, again! (Sorry for the broken gem version that long time...)
|
45
|
+
* Cucumber spec suite :D [based on the one by thecatwasnot]
|
46
|
+
* Ruby 1.9 only
|
47
|
+
* Colorized output using the paint gem
|
48
|
+
* Fix an encoding issue
|
49
|
+
* New redundancy data mechanism (old file format not compatible anymore)
|
50
|
+
* Uses PWS environment variable to determine the password file location (default is still: ~/.pws)
|
51
|
+
* Easy namespace support for different password files
|
52
|
+
* Add ability to rename entry keys
|
53
|
+
* Remove descriptions (keep it simple)
|
54
|
+
* Different generate method interface
|
55
|
+
* Uses SecureRandom instead of rand
|
56
|
+
* Fix removing passwords
|
57
|
+
* Lots of little fixes and tweaks
|
58
|
+
* New default clipboard time: 10 seconds. Another feature: Old clipboard content gets restored after that time
|
59
|
+
|
60
|
+
== See gist https://gist.github.com/658494 for older changes
|
data/{LICENSE → LICENSE.txt}
RENAMED
data/README.md
CHANGED
data/lib/pws/format/1.0.rb
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
require_relative '../format'
|
4
4
|
require 'securerandom'
|
5
|
-
require 'digest/hmac'
|
6
5
|
require 'openssl'
|
7
6
|
require 'pbkdf2'
|
8
7
|
|
@@ -15,12 +14,12 @@ class PWS
|
|
15
14
|
DEFAULT_ITERATIONS = 75_000
|
16
15
|
MAX_ITERATIONS = 10_000_000
|
17
16
|
MAX_ENTRY_LENGTH = 4_294_967_295 # N
|
18
|
-
|
17
|
+
|
19
18
|
class << self
|
20
19
|
def write(application_data, options = {})
|
21
20
|
encrypt(marshal(application_data), options)
|
22
21
|
end
|
23
|
-
|
22
|
+
|
24
23
|
def encrypt(unencrypted_data, options = {})
|
25
24
|
raise ArgumentError, 'No password given' if \
|
26
25
|
!options[:password]
|
@@ -28,27 +27,27 @@ class PWS
|
|
28
27
|
iterations = ( options[:iterations] || DEFAULT_ITERATIONS ).to_i
|
29
28
|
raise ArgumentError, 'Invalid iteration count given' if \
|
30
29
|
iterations > MAX_ITERATIONS || iterations < 2
|
31
|
-
|
30
|
+
|
32
31
|
salt = SecureRandom.random_bytes(64)
|
33
32
|
iv = Encryptor.random_iv
|
34
|
-
|
33
|
+
|
35
34
|
encryption_key, hmac_key = kdf(
|
36
35
|
options[:password],
|
37
36
|
salt,
|
38
37
|
iterations,
|
39
38
|
).unpack('a256 a256')
|
40
|
-
|
39
|
+
|
41
40
|
sha = hmac(hmac_key, salt, iv, iterations, unencrypted_data)
|
42
|
-
|
41
|
+
|
43
42
|
encrypted_data = Encryptor.encrypt(
|
44
43
|
unencrypted_data,
|
45
44
|
key: encryption_key,
|
46
45
|
iv: iv,
|
47
46
|
)
|
48
|
-
|
49
|
-
[salt, iv, iterations, sha, encrypted_data].pack(TEMPLATE)
|
47
|
+
|
48
|
+
[salt, iv, iterations, sha, encrypted_data].pack(TEMPLATE)
|
50
49
|
end
|
51
|
-
|
50
|
+
|
52
51
|
def marshal(application_data, options = {})
|
53
52
|
number_of_dummy_bytes = 100_000 + SecureRandom.random_number(1_000_000)
|
54
53
|
ordered_data = application_data.to_a
|
@@ -62,32 +61,32 @@ class PWS
|
|
62
61
|
SecureRandom.random_bytes(100_000 + SecureRandom.random_number(1_000_000))
|
63
62
|
].pack('N N a*')
|
64
63
|
end
|
65
|
-
|
64
|
+
|
66
65
|
# - - -
|
67
|
-
|
66
|
+
|
68
67
|
def read(encrypted_data, options = {})
|
69
68
|
unmarshal(decrypt(encrypted_data, options))
|
70
69
|
end
|
71
|
-
|
70
|
+
|
72
71
|
def decrypt(saved_data, options = {})
|
73
72
|
raise ArgumentError, 'No password given' if \
|
74
73
|
!options[:password]
|
75
74
|
raise ArgumentError, 'No data given' if \
|
76
75
|
!saved_data || saved_data.empty?
|
77
76
|
salt, iv, iterations, sha, encrypted_data = saved_data.unpack(TEMPLATE)
|
78
|
-
|
77
|
+
|
79
78
|
raise NoAccess, 'Password file invalid' if \
|
80
79
|
salt.size != 64 ||
|
81
80
|
iterations > MAX_ITERATIONS ||
|
82
81
|
iv.size != 16 ||
|
83
82
|
sha.size != 64
|
84
|
-
|
83
|
+
|
85
84
|
encryption_key, hmac_key = kdf(
|
86
85
|
options[:password],
|
87
86
|
salt,
|
88
87
|
iterations,
|
89
88
|
).unpack('a256 a256')
|
90
|
-
|
89
|
+
|
91
90
|
begin
|
92
91
|
unencrypted_data = Encryptor.decrypt(
|
93
92
|
encrypted_data,
|
@@ -97,13 +96,13 @@ class PWS
|
|
97
96
|
rescue OpenSSL::Cipher::CipherError
|
98
97
|
raise NoAccess, 'Could not decrypt'
|
99
98
|
end
|
100
|
-
|
99
|
+
|
101
100
|
raise NoAccess, 'Password file invalid' unless \
|
102
101
|
sha == hmac(hmac_key, salt, iv, iterations, unencrypted_data)
|
103
|
-
|
102
|
+
|
104
103
|
unencrypted_data
|
105
104
|
end
|
106
|
-
|
105
|
+
|
107
106
|
def unmarshal(saved_data, options = {})
|
108
107
|
number_of_dummy_bytes, data_size, raw_data = saved_data.unpack('N N a*')
|
109
108
|
i = number_of_dummy_bytes
|
@@ -121,15 +120,15 @@ class PWS
|
|
121
120
|
)
|
122
121
|
]
|
123
122
|
end
|
124
|
-
|
123
|
+
|
125
124
|
# support
|
126
|
-
|
125
|
+
|
127
126
|
def hmac(key, *strings)
|
128
|
-
|
127
|
+
OpenSSL::HMAC.new(key, OpenSSL::Digest::SHA512.new).update(
|
129
128
|
strings.map(&:to_s).join
|
130
129
|
).digest
|
131
130
|
end
|
132
|
-
|
131
|
+
|
133
132
|
def kdf_openssl(password, salt, iterations)
|
134
133
|
OpenSSL::PKCS5::pbkdf2_hmac(
|
135
134
|
password,
|
@@ -139,7 +138,7 @@ class PWS
|
|
139
138
|
OpenSSL::Digest::SHA512.new,
|
140
139
|
)
|
141
140
|
end
|
142
|
-
|
141
|
+
|
143
142
|
def kdf_ruby(password, salt, iterations)
|
144
143
|
PBKDF2.new(
|
145
144
|
password: password,
|
@@ -149,7 +148,7 @@ class PWS
|
|
149
148
|
hash_function: OpenSSL::Digest::SHA512,
|
150
149
|
).bin_string
|
151
150
|
end
|
152
|
-
|
151
|
+
|
153
152
|
# see gh#7
|
154
153
|
begin
|
155
154
|
OpenSSL::PKCS5::pbkdf2_hmac("","",2,512,OpenSSL::Digest::SHA512.new)
|
@@ -159,9 +158,9 @@ class PWS
|
|
159
158
|
else
|
160
159
|
alias kdf kdf_openssl
|
161
160
|
end
|
162
|
-
|
161
|
+
|
163
162
|
private
|
164
|
-
|
163
|
+
|
165
164
|
def array_to_data_string(array)
|
166
165
|
array.map{ |e|
|
167
166
|
e = e.to_s
|
@@ -170,12 +169,12 @@ class PWS
|
|
170
169
|
[s, e].pack('N a*')
|
171
170
|
}.join
|
172
171
|
end
|
173
|
-
|
172
|
+
|
174
173
|
def get_next_data_string(string, pos)
|
175
174
|
res_length = string[pos..pos+4].unpack('N')[0]
|
176
175
|
new_pos = pos + 4 + res_length
|
177
176
|
res = string[pos+4...new_pos].unpack('a*')[0]
|
178
|
-
|
177
|
+
|
179
178
|
[res, new_pos]
|
180
179
|
end
|
181
180
|
end#self
|
data/lib/pws/version.rb
CHANGED
data/pws.gemspec
CHANGED
@@ -4,7 +4,7 @@ name = 'pws'
|
|
4
4
|
require File.dirname(__FILE__) + "/lib/#{name}/version"
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
|
-
s.required_ruby_version = '>= 1.9.
|
7
|
+
s.required_ruby_version = '>= 1.9.3'
|
8
8
|
s.name = name
|
9
9
|
s.version = PWS::VERSION
|
10
10
|
s.authors = ["Jan Lelis"]
|
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.summary = "pws is a CLI password safe."
|
14
14
|
s.description = "pws is a command-line password safe. Please run `pws --help` for usage information."
|
15
15
|
s.files = Dir.glob(%w[{lib,test}/**/*.rb bin/* [A-Z]*.{txt,rdoc} ext/**/*.{rb,c} features/**/*]) + %w{Rakefile pws.gemspec}
|
16
|
-
s.extra_rdoc_files = ["README.md", "LICENSE"]
|
16
|
+
s.extra_rdoc_files = ["README.md", "LICENSE.txt", "CHANGELOG.md"]
|
17
17
|
s.license = 'MIT'
|
18
18
|
s.executables = ['pws']
|
19
19
|
s.add_dependency 'clipboard', '~> 1.0.5'
|
metadata
CHANGED
@@ -1,139 +1,139 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pws
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jan Lelis
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-01-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: clipboard
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 1.0.5
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 1.0.5
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: paint
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: 0.8.7
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 0.8.7
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: pbkdf2-ruby
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: aruba
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: cucumber
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- -
|
87
|
+
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- -
|
94
|
+
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: rspec
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- -
|
101
|
+
- - ">="
|
102
102
|
- !ruby/object:Gem::Version
|
103
103
|
version: '0'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- -
|
108
|
+
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: guard-cucumber
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
|
-
- -
|
115
|
+
- - ">="
|
116
116
|
- !ruby/object:Gem::Version
|
117
117
|
version: '0'
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
|
-
- -
|
122
|
+
- - ">="
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: guard-rspec
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
|
-
- -
|
129
|
+
- - ">="
|
130
130
|
- !ruby/object:Gem::Version
|
131
131
|
version: '0'
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
|
-
- -
|
136
|
+
- - ">="
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '0'
|
139
139
|
description: pws is a command-line password safe. Please run `pws --help` for usage
|
@@ -144,9 +144,11 @@ executables:
|
|
144
144
|
extensions: []
|
145
145
|
extra_rdoc_files:
|
146
146
|
- README.md
|
147
|
-
- LICENSE
|
147
|
+
- LICENSE.txt
|
148
|
+
- CHANGELOG.md
|
148
149
|
files:
|
149
|
-
-
|
150
|
+
- CHANGELOG.md
|
151
|
+
- LICENSE.txt
|
150
152
|
- README.md
|
151
153
|
- Rakefile
|
152
154
|
- bin/pws
|
@@ -190,12 +192,12 @@ require_paths:
|
|
190
192
|
- lib
|
191
193
|
required_ruby_version: !ruby/object:Gem::Requirement
|
192
194
|
requirements:
|
193
|
-
- -
|
195
|
+
- - ">="
|
194
196
|
- !ruby/object:Gem::Version
|
195
|
-
version: 1.9.
|
197
|
+
version: 1.9.3
|
196
198
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
197
199
|
requirements:
|
198
|
-
- -
|
200
|
+
- - ">="
|
199
201
|
- !ruby/object:Gem::Version
|
200
202
|
version: '0'
|
201
203
|
requirements: []
|