scrypt-ruby 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0b6d46b9b645c57061fb80d42fbea4b05574550c
4
+ data.tar.gz: 200ba6e9b43d9f7a04c78e60676922ca89e6ae5b
5
+ SHA512:
6
+ metadata.gz: 456336fb58d7ad005a5557850bb562e4a83cbf5936b0276a24e1857e842b8a413ff4edf1aa80e2da65b051fc2149e80b57b1f54606790463c8d1f5411bcc706a
7
+ data.tar.gz: 6f428784c04c4c55e0ad18aefe013f14971b03942003ac476a6e46743ffad5e7a04d3599ad8f7a6771a5469e7e3dd282ffaa0bc97985ecd872ab2ff6314088c0
Binary file
Binary file
@@ -0,0 +1,7 @@
1
+ Copyright (c) 2016 Barry Allard barry (dot) allard (at) gmail (dot).com
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,61 @@
1
+ # [scrypt-ruby](https://github.com/steakknife/scrypt-ruby)
2
+
3
+
4
+ ## Universal SCrypt adapter library
5
+
6
+
7
+ ### Usage
8
+
9
+ ```ruby
10
+ require 'scrypt-ruby' # instead of require 'scrypt'
11
+ ```
12
+
13
+ The API is basically the same as [https://github.com/pbhogan/scrypt](), so it's a drop-in replacement for scrypt on JRuby or regular Rubies
14
+
15
+
16
+ ### Installation
17
+ #### Gem
18
+ ```shell
19
+ gem install scrypt-ruby
20
+ ```
21
+
22
+ #### Bundler
23
+ ```ruby
24
+ # Gemfile
25
+ gem 'scrypt-ruby'
26
+ ```
27
+
28
+ ### Supported Platforms
29
+ #### JRuby
30
+ - FreeBSD
31
+ - Linux
32
+ - Mac OS X
33
+ - Windows (uncertain/untested)
34
+
35
+ Support provided by [https://github.com/wg/scrypt]()
36
+
37
+ #### MRI / CRuby / Rubinius
38
+ - FreeBSD
39
+ - Linux
40
+ - Mac OS X
41
+ - Windows
42
+
43
+ Support provided by [https://github.com/pbhogan/scrypt]()
44
+
45
+ #### Patches
46
+
47
+ PR's welcome!
48
+
49
+ For bonus points, use feature branches in your head fork to keep things clearer.
50
+
51
+ #### Issues
52
+
53
+ [Issue tracker](https://github.com/steakknife/scrypt-ruby/issues)
54
+
55
+ #### License
56
+
57
+ [MIT License](MIT-LICENSE.txt)
58
+
59
+ #### Copyright
60
+
61
+ Copyright (C) 2016 Barry Allard
@@ -0,0 +1,32 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ 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
31
+ 8m+dgfPonsYSqnDDfLuAmtKhLAA=
32
+ -----END CERTIFICATE-----
Binary file
@@ -0,0 +1,231 @@
1
+ if RUBY_ENGINE == 'jruby'
2
+ autoload :Benchmark, 'benchmark'
3
+ autoload :Digest, 'digest'
4
+ autoload :OpenSSL, 'openssl'
5
+ require File.expand_path('../scrypt-1.4.0.jar', __FILE__)
6
+ module SCrypt
7
+ @@debug = false
8
+ def self.debug=(d)
9
+ @@debug = d
10
+ end
11
+
12
+ def self.debug(*args)
13
+ return @@debug if args.length == 0
14
+ $stderr.puts(*args) if @@debug
15
+ end
16
+
17
+ module Errors
18
+ class InvalidHash < StandardError; end
19
+ class InvalidSalt < StandardError; end
20
+ class InvalidSecret < StandardError; end
21
+ end
22
+
23
+ class Password < String
24
+ attr_reader :cost, :digest, :salt
25
+
26
+ def initialize(encrypted_password)
27
+ encrypted_password = encrypted_password.to_s
28
+ raise Errors::InvalidHash, "invalid hash" unless valid_hash? encrypted_password
29
+ @cost, @salt, @digest = split_hash(replace(encrypted_password))
30
+ end
31
+
32
+ def self.create(plaintext_password, options = {})
33
+ options = Engine::DEFAULTS.merge(options)
34
+ key_len = [[options.delete(:key_len), 16].max, 512].min
35
+ options[:salt_size] = [[options[:salt_size], 8].max, 32].min
36
+ salt = Engine.generate_salt(options)
37
+ hash = Engine.hash_secret(plaintext_password, salt, key_len)
38
+ new(hash)
39
+ end
40
+
41
+ def ==(plaintext_password)
42
+ self.class.secure_compare(self, Engine.hash_secret(plaintext_password, @cost + @salt, self.digest.length / 2))
43
+ end
44
+
45
+ alias :is_password? :==
46
+
47
+ private
48
+ def self.secure_compare(x, y)
49
+ x.bytesize == y.bytesize && x.bytes.zip(y.bytes).inject(0) { |res, b| res |= b.inject(:^) } == 0
50
+ end
51
+
52
+ def split_hash(h)
53
+ n, v, r, salt, hash = h.to_s.split('$')
54
+ [[n, v, r].join('$') + "$", salt, hash]
55
+ end
56
+
57
+ def valid_hash?(h)
58
+ !!h.match(/^[0-9a-z]+\$[0-9a-z]+\$[0-9a-z]+\$[A-Za-z0-9]{16,64}\$[A-Za-z0-9]{32,1024}$/)
59
+ end
60
+ end # Password
61
+
62
+ class Engine
63
+ DEFAULTS = {
64
+ key_len: 32,
65
+ salt_size: 32,
66
+ max_mem: 16 * 1024 * 1024, # 16 MiB
67
+ max_memfrac: 0.5,
68
+ max_time: 0.2,
69
+ cost: nil
70
+ }
71
+
72
+ # @param plaintext_password String
73
+ # @param salt String
74
+ # @param args [String, key_len] or [n, r, p, key_len]
75
+ def self.scrypt(plaintext_password, salt, *args)
76
+ key_len = args.last
77
+ n = r = p = nil
78
+ case args.length
79
+ when 2
80
+ n, r, p = args[0].split('$').map{ |x| x.to_i(16) }
81
+ when 4
82
+ n, r, p = args
83
+ else
84
+ raise ArgumentError, 'only 4 or 6 arguments allowed'
85
+ end
86
+ raw_encrypted_password = com.lambdaworks.crypto.SCrypt.scrypt(plaintext_password.to_s.to_java_bytes, salt.to_java_bytes, n, r, p, key_len)
87
+ String.from_java_bytes raw_encrypted_password
88
+ end
89
+
90
+ # "4000$8$4$c6d101522d3cb045"
91
+ def self.generate_salt(options = {})
92
+ options = DEFAULTS.merge(options)
93
+ cost = options[:cost] || calibrate(options)
94
+ salt_size = options.delete :salt_size
95
+ salt = OpenSSL::Random.random_bytes(salt_size).unpack('H*').first.rjust(16,'0')
96
+ if salt.length == 40
97
+ #If salt is 40 characters, the regexp will think that it is an old-style hash, so add a '0'.
98
+ salt = '0' + salt
99
+ end
100
+ cost + salt
101
+ end
102
+
103
+ # N r p
104
+ # "4000$8$4$"
105
+ def self.calibrate!(options = {})
106
+ DEFAULTS[:cost] = calibrate(options)
107
+ end
108
+
109
+ def self.debug(*args)
110
+ SCrypt.debug(*args)
111
+ end
112
+
113
+ # N r p
114
+ # "400$8$25$"
115
+ def self.calibrate(options = {})
116
+ options = DEFAULTS.merge(options)
117
+ max_mem = options.delete :max_mem
118
+ max_memfrac = options.delete :max_memfrac
119
+ max_time = options.delete :max_time
120
+
121
+ mem_limit = memtouse(max_mem, max_memfrac)
122
+ ops_limit = [cpuperf * max_time, 32768].min
123
+ debug "ops_limit #{ops_limit} ops"
124
+
125
+ n, r, p = nil, 8, nil
126
+
127
+ if ops_limit < mem_limit/32
128
+ debug "pick based on CPU limit"
129
+ # Set p = 1 and choose N based on the CPU limit.
130
+ p = 1
131
+ max_n = ops_limit / (r * 4)
132
+ n = 1 << (1...63).find { |i| (1 << i) > max_n / 2 }
133
+ else
134
+ debug "pick based on memory limit"
135
+ # Set N based on the memory limit. */
136
+ max_n = mem_limit / (r * 128)
137
+ n = 1 << (1..63).find { |i| (1 << i) > max_n / 2 }
138
+
139
+ # Choose p based on the CPU limit. */
140
+ max_rp = [(ops_limit / 4) / (1 << n), 0x3fffffff].min
141
+ p = max_rp / r
142
+ end
143
+ debug "calibrated using: N #{n} r #{r} p #{p}"
144
+ "#{n.to_s(16)}$#{r.to_s(16)}$#{p.to_s(16)}$"
145
+ end
146
+
147
+ # @returns Boolean
148
+ def self.valid_cost?(cost)
149
+ !!cost.match(/^[0-9a-z]+\$[0-9a-z]+\$[0-9a-z]+\$$/)
150
+ end
151
+
152
+ # @returns Boolean
153
+ def self.valid_salt?(salt)
154
+ !!salt.match(/^[0-9a-z]+\$[0-9a-z]+\$[0-9a-z]+\$[A-Za-z0-9]{16,64}$/)
155
+ end
156
+
157
+ # @returns Boolean
158
+ def self.valid_secret?(secret)
159
+ secret.respond_to?(:to_s)
160
+ end
161
+
162
+ def self.hash_secret_old(secret, salt, cost)
163
+ salt + "$" + Digest::SHA1.hexdigest(scrypt(secret.to_s, salt, cost, 256))
164
+ end
165
+
166
+ def self.hash_secret_new(secret, salt_only, cost, key_len)
167
+ salt_only = [salt_only.sub(/^(00)+/, '')].pack('H*')
168
+ scrypt(secret.to_s, salt_only, cost, key_len).unpack('H*').first.rjust(key_len * 2, '0')
169
+ end
170
+
171
+ # "400$8$26$b62e0f787a5fc373$0399ccd4fa26642d92741b17c366b7f6bd12ccea5214987af445d2bed97bc6a2"
172
+ def self.hash_secret(secret, salt, key_len = DEFAULTS[:key_len])
173
+ raise Errors::InvalidSalt, "invalid salt" unless valid_salt? salt
174
+ raise Errors::InvalidSecret, "invalid secret" unless valid_secret? secret
175
+
176
+ cost = cost_from_salt(salt)
177
+ salt_only = salt_only(salt)
178
+
179
+ if salt_only.length == 40
180
+ hash_secret_old(secret, salt, cost)
181
+ else
182
+ salt + "$" + hash_secret_new(secret, salt_only, cost, key_len)
183
+ end
184
+ end
185
+
186
+ private
187
+
188
+ def self.cost_from_salt(salt)
189
+ salt[/^[0-9a-z]+\$[0-9a-z]+\$[0-9a-z]+\$/]
190
+ end
191
+
192
+ def self.salt_only(salt)
193
+ salt[/\$([A-Za-z0-9]{16,64})$/, 1]
194
+ end
195
+
196
+ # Estimate how many scrypts / second
197
+ def self.cpuperf
198
+ iterations = 1000
199
+ empty_array = "".to_java_bytes.freeze
200
+ run = -> { iterations.times { com.lambdaworks.crypto.SCrypt.scrypt(empty_array, empty_array, 128, 1, 1, 1) } }
201
+ # warm-up
202
+ run.()
203
+ loop do
204
+ time = Benchmark.realtime { |x| run.() }
205
+ if time > 0.33
206
+ per_sec = iterations/time
207
+ debug "cpuperf #{per_sec} ops/s"
208
+ return per_sec
209
+ end
210
+ iterations *= 10
211
+ end
212
+ end
213
+
214
+ #
215
+ def self.memtouse(max_mem, max_memfrac)
216
+ max_memfrac = 0.5 if max_memfrac > 0.5 || max_memfrac == 0
217
+
218
+ memlimit_min = java.lang.Runtime.getRuntime.freeMemory
219
+ debug "free mem #{memlimit_min / 1048576} MiB"
220
+
221
+ mem_avail = max_memfrac * memlimit_min
222
+ mem_avail = [mem_avail, max_mem].min if max_mem > 0
223
+ mem_avail = [mem_avail, 1024*1024].max
224
+ debug "memtouse #{mem_avail / 1048576} MiB"
225
+ mem_avail
226
+ end
227
+ end # Engine
228
+ end # SCrypt
229
+ else
230
+ require 'scrypt'
231
+ end
@@ -0,0 +1,29 @@
1
+ Gem::Specification::new do |s|
2
+ s.name = 'scrypt-ruby'
3
+ s.version = '2.0.0'
4
+ s.summary = 'Universal SCrypt adapter'
5
+ s.description = 'Universal SCrypt PBKDF adapter (for CRuby (MRI) and JRuby)'
6
+ s.license = 'MIT'
7
+
8
+ s.files = [
9
+ 'README.md',
10
+ 'MIT-LICENSE.txt',
11
+ 'gem-public_cert.pem',
12
+ 'scrypt-ruby.gemspec',
13
+ 'lib/scrypt-1.4.0.jar',
14
+ 'lib/scrypt-ruby.rb',
15
+ ]
16
+
17
+ s.required_ruby_version = '>= 1.9.3'
18
+ s.require_path = 'lib'
19
+ s.author = 'Barry Allard'
20
+ s.email = 'barry.allard@gmail.com'
21
+ s.homepage = 'https://github.com/steakknife/scrypt-ruby'
22
+
23
+ if RUBY_PLATFORM == 'java'
24
+ s.platform = 'java'
25
+ else
26
+ s.add_dependency 'scrypt', '~> 2.0'
27
+ end
28
+ end
29
+ .tap {|gem| pk = File.expand_path(File.join('~/.keys', 'gem-private_key.pem')); gem.signing_key = pk if File.exist? pk; gem.cert_chain = ['gem-public_cert.pem']} # pressed firmly by waxseal
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: scrypt-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Barry Allard
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ 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
42
+ 8m+dgfPonsYSqnDDfLuAmtKhLAA=
43
+ -----END CERTIFICATE-----
44
+ date: 2016-03-14 00:00:00.000000000 Z
45
+ dependencies:
46
+ - !ruby/object:Gem::Dependency
47
+ name: scrypt
48
+ requirement: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - "~>"
51
+ - !ruby/object:Gem::Version
52
+ version: '2.0'
53
+ type: :runtime
54
+ prerelease: false
55
+ version_requirements: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '2.0'
60
+ description: Universal SCrypt PBKDF adapter (for CRuby (MRI) and JRuby)
61
+ email: barry.allard@gmail.com
62
+ executables: []
63
+ extensions: []
64
+ extra_rdoc_files: []
65
+ files:
66
+ - MIT-LICENSE.txt
67
+ - README.md
68
+ - gem-public_cert.pem
69
+ - lib/scrypt-1.4.0.jar
70
+ - lib/scrypt-ruby.rb
71
+ - scrypt-ruby.gemspec
72
+ homepage: https://github.com/steakknife/scrypt-ruby
73
+ licenses:
74
+ - MIT
75
+ metadata: {}
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: 1.9.3
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubyforge_project:
92
+ rubygems_version: 2.6.1
93
+ signing_key:
94
+ specification_version: 4
95
+ summary: Universal SCrypt adapter
96
+ test_files: []
97
+ has_rdoc:
Binary file