pwdhash 0.3.2 → 0.3.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: bb0a326c401db28d80926db611907417abd26c83
4
- data.tar.gz: 6e0c010c435d13f50b3c4e7d582f72ce47140ef1
2
+ SHA256:
3
+ metadata.gz: c4724abfd27a606ddc0e0136b7b442098f24f67c0755b80ee5622abf580424dd
4
+ data.tar.gz: 8ccc81e9a1c7be717f30cab699625145b7f08d2fb88ddafe32a071972c8c3c51
5
5
  SHA512:
6
- metadata.gz: c4ff8c1cb1d94d97176abd54c4997a44750d85d4942f83acb5ac232a907560021af99cb7fad637ecc1d2edce8d10cc2473e18d50916e9fba8abc2c4d33b9f96c
7
- data.tar.gz: e1d4f23b0bac24fb7e9b2e7cf2ddab0a7b1627b57b04b06ac492ef9d95e3417ee4fb29d3aa0f47c494eedc3c44169e30ca0058fcbd40175b0d28b39ea2c9c402
6
+ metadata.gz: 41f39488b7b5d0638b6c84aae4c7805eec2d1871f496b049e855ba6bc3d483290df51e2576bdf25822142e34be7251e295047a52c4feaa38b4a2c2910f7ef0f9
7
+ data.tar.gz: ae7fc1d0ee62e3a1144b5ae02ddfe45e9f9639a731e0377d2a0643a2a62ec9cd7a4bbf9a37a086b71065b0adc7b5446aaced38ad15cfd8526adb68959750dbca
data/README.markdown CHANGED
@@ -6,7 +6,7 @@ Generates PwdHash passwords from the command line.
6
6
 
7
7
  This is a simple Ruby command line tool to generate hashed passwords, using PwdHash's algorithm.
8
8
 
9
- PwdHash was written as a browser plugin, but sometimes we'd like to extend its use to desktop applications too. e.g. IM clients, Dropbox, etc. just to name a few.
9
+ PwdHash was written as a browser plug-in, but sometimes we'd like to extend its use to desktop applications too. e.g. IM clients, Dropbox, etc. just to name a few.
10
10
 
11
11
  This tool is essentially a *straight* copy of [Chris Roos' implementation][chris-roos-impl], with a couple of command line interface improvements:
12
12
 
@@ -28,17 +28,41 @@ This tool is essentially a *straight* copy of [Chris Roos' implementation][chris
28
28
  Password for example.com:
29
29
  5NBoCKraALBs
30
30
 
31
- $ pwdhash example.com | xcilp # Put generated password to X clipboard
31
+ $ pwdhash example.com | xclip # Put generated password to X clipboard (paste with middle-click)
32
+ $ pwdhash example.com | xclip -selection c # Put generated password to X clipboard (paste with CTRL+V)
32
33
  $ pwdhash example.com | pbcopy # Or in OS X
33
34
  > pwdhash example.com | clip # Or in Windows
34
35
  $ pwdhash example.com | putclip # Or in Cygwin
35
36
 
37
+ ## PwdHash2
38
+
39
+ Some vulnerabilities of PwdHash have been exposed in [Cracking PwdHash: A Brute-force Attack on Client-side Password Hashing][cracking-pwdhash], along with a [proof-of-concept][pwdhash-poc] update to PwdHash. The updated algorithm (with PBKDF2-SHA256 + salt + multiple iterations) has been implemented as a Firefox Add-On at [GWuk/PwdHash2][gwuk-pwdhash2].
40
+
41
+ The corresponding algorithm can be used with:
42
+
43
+ $ pwdhash2 URI [SALT] [ITERATIONS]
44
+
45
+ $ pwdhash2 example.com ReplaceThisSalt 50_000
46
+ Password for example.com (salt = 'ReplaceThisSalt', iterations = 50000):
47
+ IHC8WhmO40v
48
+
49
+ *SALT* can be defined in `PWDHASH2_SALT` environment variable.
50
+
51
+ *ITERATIONS* can be defined in `PWDHASH2_ITERATIONS` environment variable.
52
+
53
+ $ pwdhash2 example.com | xclip -selection c # Put generated password to X clipboard (paste with CTRL+V)
54
+
36
55
  ## Attribution
37
56
 
38
57
  The library part of this tool is a *straight* copy of [Chris Roos' implementation][chris-roos-impl]. The reason this git repository is set up is because: a) Chris Roos decided to put the code in an obscure corner in a pile of code which makes it hard for people to find and b) GitHub uses git :p
39
58
 
40
- The PwdHash plugin and the PwdHash algorithm is contributed by [Stanford PwdHash][stanford-pwdhash].
59
+ The PwdHash plug-in and the PwdHash algorithm is contributed by [Stanford PwdHash][stanford-pwdhash].
60
+
61
+ The PwdHash2 algorithm is contributed by [David Llewellyn-Jones and Graham Rymer][pwdhash-poc].
41
62
 
42
63
  [chris-roos-impl]: http://chrisroos.co.uk/blog/2007-04-11-getting-to-grips-with-pwdhash
43
64
  [stanford-pwdhash]: http://pwdhash.com
44
65
  [usenix-paper]: http://crypto.stanford.edu/PwdHash/pwdhash.pdf
66
+ [cracking-pwdhash]: https://www.researchgate.net/publication/316267246_Cracking_PwdHash_A_Bruteforce_Attack_on_Client-side_Password_Hashing
67
+ [pwdhash-poc]: https://github.com/llewelld/pwdhash-poc
68
+ [gwuk-pwdhash2]: https://github.com/GWuk/PwdHash2/
data/bin/pwdhash2 ADDED
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'highline/import'
5
+ require 'pathname'
6
+
7
+ require 'pwdhash/pwdhash'
8
+ require 'pwdhash/extract_domain'
9
+ require 'pwdhash/version'
10
+
11
+ require 'backports'
12
+
13
+ def usage
14
+ puts "pwdhash.rb #{PwdHash::VERSION} - Chris Yuen, Chris Roos (2012) Eric Duminil (2019)"
15
+ puts "Usage: pwdhash2 URI [SALT] [ITERATIONS]"
16
+ puts "Example: pwdhash2 https://mail.google.com"
17
+ puts "Example: pwdhash2 https://mail.google.com SomeSalt"
18
+ puts "Example: pwdhash2 https://mail.google.com SomeSalt 10_000"
19
+ puts
20
+ puts "SALT can also be defined in PWDHASH2_SALT environment variable."
21
+ puts "ITERATIONS can also be defined in PWDHASH2_ITERATIONS environment variable."
22
+ exit
23
+ end
24
+
25
+ usage if ARGV.length == 0
26
+
27
+ realm = extract_domain(ARGV[0])
28
+
29
+ salt = ARGV[1] || ENV['PWDHASH2_SALT']
30
+ iterations = (ARGV[2] || ENV['PWDHASH2_ITERATIONS'] || 50_000).to_i
31
+
32
+ hl = HighLine.new($stdin, $stderr)
33
+ hl.say("WARNING: Empty salt!") if salt.empty?
34
+ password = hl.ask("Password for #{realm} (salt = '#{salt}', iterations = #{iterations}): ") {|q| q.echo = false}
35
+
36
+ print get_hashed_password2(password, realm, salt, iterations)
@@ -26,7 +26,7 @@ def contains(result, regex)
26
26
  end
27
27
 
28
28
  def apply_constraints(hash, size, nonalphanumeric)
29
- startingSize = size - 4 # Leave room for some extra characters
29
+ startingSize = [size - 4, 0].max # Leave room for some extra characters
30
30
  result = hash[0, startingSize]
31
31
  extras = (hash[startingSize, hash.length] || "").split('')
32
32
 
@@ -46,8 +46,8 @@ def apply_constraints(hash, size, nonalphanumeric)
46
46
  return result.join('')
47
47
  end
48
48
 
49
- require 'hmac-md5'
50
49
  require 'base64'
50
+ require 'openssl'
51
51
 
52
52
  module PwdHash
53
53
  class Hash
@@ -65,12 +65,28 @@ module PwdHash
65
65
  end
66
66
  private
67
67
  def hash!
68
- @hash = Base64.encode64(HMAC::MD5.digest(@password, @realm)).strip
68
+ @hash = Base64.encode64(OpenSSL::HMAC.digest("MD5", @password, @realm)).strip
69
69
  end
70
70
  def remove_base64_pad_character
71
71
  @hash.sub!(/=+$/, '')
72
72
  end
73
73
  end
74
+
75
+ class Hash2 < Hash
76
+ DIGEST = OpenSSL::Digest::SHA256.new
77
+
78
+ def initialize(realm, password, salt, iterations)
79
+ @salt, @iterations = salt, iterations
80
+ super(realm, password)
81
+ end
82
+
83
+ private
84
+
85
+ def hash!
86
+ # Based on https://github.com/GWuk/PwdHash2/blob/gh-pages/pwdhash2/hashed-password.js#L44
87
+ @hash = Base64.encode64(OpenSSL::PKCS5.pbkdf2_hmac([@password , @salt].join, @realm, @iterations, (2 * size / 3) + 16, DIGEST))
88
+ end
89
+ end
74
90
  end
75
91
 
76
92
  def get_hashed_password(password, realm)
@@ -78,3 +94,8 @@ def get_hashed_password(password, realm)
78
94
  apply_constraints(hash.hash, hash.size, hash.contains_non_alphanumeric?)
79
95
  end
80
96
 
97
+ def get_hashed_password2(password, realm, salt, iterations)
98
+ hash = PwdHash::Hash2.new(realm, password, salt, iterations)
99
+ apply_constraints(hash.hash, hash.size, hash.contains_non_alphanumeric?)
100
+ end
101
+
@@ -1,3 +1,3 @@
1
1
  module PwdHash
2
- VERSION = "0.3.2"
2
+ VERSION = "0.3.5"
3
3
  end
data/pwdhash.gemspec CHANGED
@@ -19,7 +19,5 @@ Gem::Specification.new do |gem|
19
19
  gem.require_paths = ["lib"]
20
20
  gem.version = PwdHash::VERSION
21
21
 
22
- gem.add_dependency('highline', '~> 1.6', '>= 1.6.12')
23
- gem.add_dependency('ruby-hmac', '~> 0.4', '>= 0.4.0')
24
- gem.add_dependency('backports', '~> 3.6', '>= 3.6.4')
22
+ gem.add_dependency('highline', '~> 3.1.2')
25
23
  end
data/pwdhash_test.rb CHANGED
@@ -1,18 +1,72 @@
1
+ require 'minitest'
1
2
  require 'minitest/unit'
2
3
  require 'minitest/pride'
3
4
  require 'minitest/autorun'
4
5
 
5
6
  require './lib/pwdhash/pwdhash'
7
+ require './lib/pwdhash/extract_domain'
6
8
 
7
- class PwdHashTest < MiniTest::Unit::TestCase
8
- def test_passwords
9
+ class PwdHashTest < Minitest::Test
10
+ def test_passwords_with_domains
9
11
  [
10
12
  ['v0F0B', 'foo', 'skype.com'],
11
13
  ['paZTVGZwtewiq1+uCk', 'a l0ng p4assw0rd', 'google.com'],
12
14
  ['nRDL7WNyFODhF29gAkNmpA', 'qwertyuiop0987654321', 'google.com'],
13
15
  ['edi6wHWRQVA1rK8o9zaluwAAAA', 'qwertyuiop0987654321bingo', 'google.com'],
16
+ ['8JyURsRs', 'foobar', 'thetimes.co.uk'],
14
17
  ].each do |expected, password, realm|
15
18
  assert_equal expected, get_hashed_password(password, realm)
16
19
  end
17
20
  end
21
+
22
+ def test_passwords_with_complete_urls
23
+ [
24
+ ['v0F0B', 'foo', 'https://www.whatever.skype.com'],
25
+ ['paZTVGZwtewiq1+uCk', 'a l0ng p4assw0rd', 'https://images.google.com'],
26
+ ['nRDL7WNyFODhF29gAkNmpA', 'qwertyuiop0987654321', 'http://google.com'],
27
+ ['edi6wHWRQVA1rK8o9zaluwAAAA', 'qwertyuiop0987654321bingo', 'https://news.google.com'],
28
+ ['8JyURsRs', 'foobar', 'https://www.thetimes.co.uk/'],
29
+ ].each do |expected, password, url|
30
+ assert_equal expected, get_hashed_password(password, extract_domain(url))
31
+ end
32
+ end
33
+ end
34
+
35
+ class PwdHash2Test < Minitest::Test
36
+ def test_passwords_with_complete_urls
37
+ # expected results calculated with https://gwuk.github.io/PwdHash2/pwdhash2/
38
+ [
39
+ ['5YrAI', 'foo', 10000, 'SomeSalt', 'https://www.skype.com/en/'],
40
+ ['r8oIM4CR', 'foobar', 1, 'ChangeMe', 'https://google.com'],
41
+ ['3PvCifzNoYaTNBMcJzVvDfDBeVK', 'correcthorsebatterystaple', 50000, 'COVwVNWVhwCsd7vlQ2T5BuIJBccYCu1RzR8rQFVHYVkGVQkZXHLkglnttWFQJYIN', 'https://about.google/intl/en/?fg=1&utm_source=google-EN&utm_medium=referral&utm_campaign=hp-header'],
42
+ ['APC8mNJI', 'foobar', 1000, 'ChangeMe', 'https://google.com'],
43
+ ].each do |expected, password, iterations, salt, url|
44
+ assert_equal expected, get_hashed_password2(password, extract_domain(url), salt, iterations)
45
+ end
46
+ end
47
+
48
+ def test_collisions_with_weak_passwords
49
+ # => Use a longer password!
50
+ [
51
+ ['foo', 1000, 'bar', 'https://manifolds.org', 'https://boxwoods.com'],
52
+ ['foo', 50_000, 'aYcErTYgi0AoB2tDbP80fwR5GAWwUvg8', 'http://dainty.co.uk', 'http://polemic.com'],
53
+ ['foobar', 100, 'salt', 'https://abounds.edu.au', 'https://coaxed.co.nz'],
54
+ ].each do |password, iterations, salt, url1, url2|
55
+ assert_equal get_hashed_password2(password, extract_domain(url1), salt, iterations),
56
+ get_hashed_password2(password, extract_domain(url2), salt, iterations)
57
+ end
58
+ end
59
+
60
+ def test_edge_cases
61
+ # For testing only! Please always define salt and password. Number of iterations shouldn't be too low and password should be long enough.
62
+ [
63
+ ['WWNEC9x1', 'foobar', 1000, '', 'https://google.com'],
64
+ ['EBr2', '', 1000, '', 'https://google.com'],
65
+ ['w0WD', '', 1, '', 'https://google.com'],
66
+ ['w0WD', '', 0, '', 'https://google.com'],
67
+ ['w0WD', '', -1, '', 'https://google.com'],
68
+ ].each do |expected, password, iterations, salt, url|
69
+ assert_equal expected, get_hashed_password2(password, extract_domain(url), salt, iterations)
70
+ end
71
+ end
18
72
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pwdhash
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.3.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Yuen
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-16 00:00:00.000000000 Z
11
+ date: 2025-03-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: highline
@@ -16,65 +16,20 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.6'
20
- - - ">="
21
- - !ruby/object:Gem::Version
22
- version: 1.6.12
23
- type: :runtime
24
- prerelease: false
25
- version_requirements: !ruby/object:Gem::Requirement
26
- requirements:
27
- - - "~>"
28
- - !ruby/object:Gem::Version
29
- version: '1.6'
30
- - - ">="
31
- - !ruby/object:Gem::Version
32
- version: 1.6.12
33
- - !ruby/object:Gem::Dependency
34
- name: ruby-hmac
35
- requirement: !ruby/object:Gem::Requirement
36
- requirements:
37
- - - "~>"
38
- - !ruby/object:Gem::Version
39
- version: '0.4'
40
- - - ">="
41
- - !ruby/object:Gem::Version
42
- version: 0.4.0
19
+ version: 3.1.2
43
20
  type: :runtime
44
21
  prerelease: false
45
22
  version_requirements: !ruby/object:Gem::Requirement
46
23
  requirements:
47
24
  - - "~>"
48
25
  - !ruby/object:Gem::Version
49
- version: '0.4'
50
- - - ">="
51
- - !ruby/object:Gem::Version
52
- version: 0.4.0
53
- - !ruby/object:Gem::Dependency
54
- name: backports
55
- requirement: !ruby/object:Gem::Requirement
56
- requirements:
57
- - - "~>"
58
- - !ruby/object:Gem::Version
59
- version: '3.6'
60
- - - ">="
61
- - !ruby/object:Gem::Version
62
- version: 3.6.4
63
- type: :runtime
64
- prerelease: false
65
- version_requirements: !ruby/object:Gem::Requirement
66
- requirements:
67
- - - "~>"
68
- - !ruby/object:Gem::Version
69
- version: '3.6'
70
- - - ">="
71
- - !ruby/object:Gem::Version
72
- version: 3.6.4
26
+ version: 3.1.2
73
27
  description: Command line version of Stanford PwdHash
74
28
  email:
75
29
  - chris@kizzx2.com
76
30
  executables:
77
31
  - pwdhash
32
+ - pwdhash2
78
33
  extensions: []
79
34
  extra_rdoc_files: []
80
35
  files:
@@ -84,6 +39,7 @@ files:
84
39
  - README.markdown
85
40
  - Rakefile
86
41
  - bin/pwdhash
42
+ - bin/pwdhash2
87
43
  - lib/pwdhash/extract_domain.rb
88
44
  - lib/pwdhash/pwdhash.rb
89
45
  - lib/pwdhash/version.rb
@@ -93,7 +49,7 @@ homepage: https://github.com/kizzx2/pwdhash.rb
93
49
  licenses:
94
50
  - GPL-3.0
95
51
  metadata: {}
96
- post_install_message:
52
+ post_install_message:
97
53
  rdoc_options: []
98
54
  require_paths:
99
55
  - lib
@@ -108,9 +64,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
108
64
  - !ruby/object:Gem::Version
109
65
  version: '0'
110
66
  requirements: []
111
- rubyforge_project:
112
- rubygems_version: 2.2.2
113
- signing_key:
67
+ rubygems_version: 3.4.19
68
+ signing_key:
114
69
  specification_version: 4
115
70
  summary: Command line version of Stanford PwdHash
116
71
  test_files: []