aws-srp 0.1.0
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 +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.travis.yml +6 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +40 -0
- data/LICENSE.txt +21 -0
- data/README.md +60 -0
- data/Rakefile +6 -0
- data/aws-srp.gemspec +28 -0
- data/bin/console +7 -0
- data/bin/setup +8 -0
- data/lib/aws-srp.rb +3 -0
- data/lib/aws_srp.rb +12 -0
- data/lib/aws_srp/flow.rb +54 -0
- data/lib/aws_srp/flow/password_verifier_response.rb +41 -0
- data/lib/aws_srp/hasher.rb +52 -0
- data/lib/aws_srp/hex.rb +94 -0
- data/lib/aws_srp/srp.rb +118 -0
- data/lib/aws_srp/version.rb +5 -0
- metadata +64 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: bc27e086070a47ca1d6035d3c058ac7865e72bc527c748e584f6edf3f2e65a77
|
4
|
+
data.tar.gz: f939b7bd528cd2d1aad17e5651eabf88581e9ed28c70ba4d01d1574c344a7c15
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0e641bdbb5e55d8e9694f952a14cc16d2f6783e7f43787bb2ce7ce37f767d69a40c1c1aeeb135e072ab13273afc8b87bc6cd324ae4d1c41a97e7bbe1bbd9e624
|
7
|
+
data.tar.gz: f57c6d80d0fc372b2d70a329c60a78f928aa570e798b6272e806dc72fc83a34efd4b9f404a08e2b21f5ea4544b1b2ba2e09615f3d1763fcc4231de97d3c2a174
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
aws-srp (0.1.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
coderay (1.1.3)
|
10
|
+
diff-lcs (1.4.4)
|
11
|
+
method_source (1.0.0)
|
12
|
+
pry (0.13.1)
|
13
|
+
coderay (~> 1.1)
|
14
|
+
method_source (~> 1.0)
|
15
|
+
rake (12.3.3)
|
16
|
+
rspec (3.9.0)
|
17
|
+
rspec-core (~> 3.9.0)
|
18
|
+
rspec-expectations (~> 3.9.0)
|
19
|
+
rspec-mocks (~> 3.9.0)
|
20
|
+
rspec-core (3.9.2)
|
21
|
+
rspec-support (~> 3.9.3)
|
22
|
+
rspec-expectations (3.9.2)
|
23
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
24
|
+
rspec-support (~> 3.9.0)
|
25
|
+
rspec-mocks (3.9.1)
|
26
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
27
|
+
rspec-support (~> 3.9.0)
|
28
|
+
rspec-support (3.9.3)
|
29
|
+
|
30
|
+
PLATFORMS
|
31
|
+
ruby
|
32
|
+
|
33
|
+
DEPENDENCIES
|
34
|
+
aws-srp!
|
35
|
+
pry
|
36
|
+
rake (~> 12.0)
|
37
|
+
rspec (~> 3.0)
|
38
|
+
|
39
|
+
BUNDLED WITH
|
40
|
+
2.1.4
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2020 Tim Masliuchenko
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# aws-srp [](https://travis-ci.org/timsly/aws-srp)
|
2
|
+
|
3
|
+
AWS Cognito SRP Utility
|
4
|
+
|
5
|
+
This is a ruby implementation of [the AWS Cognito flow helpers](https://github.com/aws-amplify/amplify-js/blob/main/packages/amazon-cognito-identity-js/src/AuthenticationHelper.js)
|
6
|
+
using some ideas from [the SIRP gem](https://github.com/grempe/sirp)
|
7
|
+
|
8
|
+
By design the `AwsSRP::Flow` only processes params but doesn't trigger any requests.
|
9
|
+
Requests should be handled on the client side.
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Add this line to your application's Gemfile:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
gem 'aws-srp'
|
17
|
+
```
|
18
|
+
|
19
|
+
And then execute:
|
20
|
+
|
21
|
+
$ bundle install
|
22
|
+
|
23
|
+
Or install it yourself as:
|
24
|
+
|
25
|
+
$ gem install aws-srp
|
26
|
+
|
27
|
+
## Usage
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
flow = AwsSRP::Flow.new
|
31
|
+
init_params = flow.init_auth
|
32
|
+
|
33
|
+
# Do the init AWS Congnito request by sending `init_params`
|
34
|
+
# Parse the JSON response and pass it to the `AwsSRP::Flow#verify_password`
|
35
|
+
|
36
|
+
challange_request_params = flow.verify_password(challange_response_body)
|
37
|
+
|
38
|
+
# Send the `challange_request_params` and parse the response.
|
39
|
+
# The session token should be there
|
40
|
+
```
|
41
|
+
|
42
|
+
## TODO
|
43
|
+
|
44
|
+
- Test coverage for `AwsSRP::SRP` and `AwsSRP::Flow` classes
|
45
|
+
- Handle more AWS Cognito features(2FA, etc)
|
46
|
+
|
47
|
+
## Development
|
48
|
+
|
49
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
50
|
+
|
51
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
52
|
+
|
53
|
+
## Contributing
|
54
|
+
|
55
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/timsly/aws-srp.
|
56
|
+
|
57
|
+
|
58
|
+
## License
|
59
|
+
|
60
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/aws-srp.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lib/aws_srp/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'aws-srp'
|
7
|
+
spec.version = AwsSRP::VERSION
|
8
|
+
spec.authors = ['Tim Masliuchenko']
|
9
|
+
spec.email = ['insside@gmail.com']
|
10
|
+
|
11
|
+
spec.summary = %q{AWS Cognito SRP Utility}
|
12
|
+
spec.description = %q{AWS Cognito SRP Utility}
|
13
|
+
spec.homepage = 'https://github.com/timsly/aws-srp'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0')
|
16
|
+
|
17
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
18
|
+
spec.metadata['source_code_uri'] = 'https://github.com/timsly/aws-srp'
|
19
|
+
|
20
|
+
# Specify which files should be added to the gem when it is released.
|
21
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
22
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
23
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
24
|
+
end
|
25
|
+
spec.bindir = 'exe'
|
26
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
|
+
spec.require_paths = ['lib']
|
28
|
+
end
|
data/bin/console
ADDED
data/bin/setup
ADDED
data/lib/aws-srp.rb
ADDED
data/lib/aws_srp.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'openssl'
|
4
|
+
require 'base64'
|
5
|
+
require 'securerandom'
|
6
|
+
|
7
|
+
require 'aws_srp/version'
|
8
|
+
require 'aws_srp/hasher'
|
9
|
+
require 'aws_srp/hex'
|
10
|
+
require 'aws_srp/srp'
|
11
|
+
require 'aws_srp/flow'
|
12
|
+
require 'aws_srp/flow/password_verifier_response'
|
data/lib/aws_srp/flow.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AwsSRP
|
4
|
+
# AWS Cognito flow
|
5
|
+
class Flow
|
6
|
+
attr_reader :pool_id, :username, :password, :srp
|
7
|
+
|
8
|
+
def initialize(pool_id, username, password)
|
9
|
+
@pool_id = pool_id
|
10
|
+
@username = username
|
11
|
+
@password = password
|
12
|
+
|
13
|
+
@srp = SRP.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def now
|
17
|
+
@now ||= Time.now.utc.strftime('%a %b %-e %H:%M:%S UTC %Y')
|
18
|
+
end
|
19
|
+
|
20
|
+
def init_auth
|
21
|
+
{
|
22
|
+
AuthParameters: {
|
23
|
+
USERNAME: username,
|
24
|
+
SRP_A: srp.aa.str
|
25
|
+
}
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def verify_password(response)
|
30
|
+
response = PasswordVerifierResponse.new(response)
|
31
|
+
|
32
|
+
srp.username = [pool_id, response.user_id].join
|
33
|
+
srp.password = password
|
34
|
+
srp.salt = response.salt
|
35
|
+
srp.bb = response.bb
|
36
|
+
|
37
|
+
hmac = Hasher.new(srp.hkdf)
|
38
|
+
.update(pool_id)
|
39
|
+
.update(response.user_id)
|
40
|
+
.update(response.secret_block, base64: true)
|
41
|
+
.update(now)
|
42
|
+
|
43
|
+
{
|
44
|
+
ChallengeName: response.challenge_name,
|
45
|
+
ChallengeResponses: {
|
46
|
+
USERNAME: response.user_id,
|
47
|
+
PASSWORD_CLAIM_SECRET_BLOCK: response.secret_block,
|
48
|
+
TIMESTAMP: now,
|
49
|
+
PASSWORD_CLAIM_SIGNATURE: hmac.digest64
|
50
|
+
}
|
51
|
+
}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AwsSRP
|
4
|
+
class Flow
|
5
|
+
# Password Verifier Challange response wrapper
|
6
|
+
class PasswordVerifierResponse
|
7
|
+
attr_reader :response
|
8
|
+
|
9
|
+
def initialize(response)
|
10
|
+
@response = response
|
11
|
+
end
|
12
|
+
|
13
|
+
def challenge_name
|
14
|
+
dig!('ChallengeName')
|
15
|
+
end
|
16
|
+
|
17
|
+
def salt
|
18
|
+
dig!('ChallengeParameters', 'SALT')
|
19
|
+
end
|
20
|
+
|
21
|
+
def secret_block
|
22
|
+
dig!('ChallengeParameters', 'SECRET_BLOCK')
|
23
|
+
end
|
24
|
+
|
25
|
+
def bb
|
26
|
+
dig!('ChallengeParameters', 'SRP_B')
|
27
|
+
end
|
28
|
+
|
29
|
+
def user_id
|
30
|
+
dig!('ChallengeParameters', 'USER_ID_FOR_SRP')
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def dig!(*path)
|
36
|
+
response.dig(*path) ||
|
37
|
+
raise(ArgumentError, "#{path.join('/')} not found in the response")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AwsSRP
|
4
|
+
# Depends on the `msg` presence acts as a digest or a hmac
|
5
|
+
class Hasher
|
6
|
+
ALGORITHM = 'sha256'
|
7
|
+
|
8
|
+
def self.digest(key, msg = nil)
|
9
|
+
new(key, msg).digest
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.hexdigest(key, msg = nil)
|
13
|
+
new(key, msg).hexdigest
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(key, msg = nil)
|
17
|
+
@key = key
|
18
|
+
@digest = OpenSSL::Digest.new(ALGORITHM)
|
19
|
+
|
20
|
+
update(msg) if msg
|
21
|
+
end
|
22
|
+
|
23
|
+
def update(msg, base64: false)
|
24
|
+
msg = Base64.strict_decode64(msg) if base64
|
25
|
+
hmac.update(msg)
|
26
|
+
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
def digest
|
31
|
+
perform :digest
|
32
|
+
end
|
33
|
+
|
34
|
+
def hexdigest
|
35
|
+
perform :hexdigest
|
36
|
+
end
|
37
|
+
|
38
|
+
def digest64
|
39
|
+
Base64.strict_encode64(digest)
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def hmac
|
45
|
+
@hmac ||= OpenSSL::HMAC.new(@key, @digest)
|
46
|
+
end
|
47
|
+
|
48
|
+
def perform(method)
|
49
|
+
@hmac ? hmac.public_send(method) : @digest.public_send(method, @key)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/aws_srp/hex.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AwsSRP
|
4
|
+
# Hexadecimal number represntation.
|
5
|
+
class Hex
|
6
|
+
HEX_STRING_PATTERN = /^[a-fA-F0-9]+$/.freeze
|
7
|
+
DOUBLE_ZERO_PADDING_PATTERN = /^[a-fA-F89]/.freeze
|
8
|
+
ARITHMETIC_OPERATORS = %i[+ - * / %].freeze
|
9
|
+
|
10
|
+
# Return a hex string (e.g. \x9F)
|
11
|
+
def self.str(str)
|
12
|
+
[str].pack('H*')
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :str
|
16
|
+
|
17
|
+
def initialize(val)
|
18
|
+
@str, @int = if val.is_a?(Integer)
|
19
|
+
[val.to_s(16), val]
|
20
|
+
else
|
21
|
+
validate_str!(val.to_s)
|
22
|
+
end
|
23
|
+
|
24
|
+
@str = @str.downcase
|
25
|
+
end
|
26
|
+
|
27
|
+
def int
|
28
|
+
@int ||= str.hex
|
29
|
+
end
|
30
|
+
alias to_i int
|
31
|
+
|
32
|
+
def padding
|
33
|
+
if str.length.odd?
|
34
|
+
'0'
|
35
|
+
elsif str =~ DOUBLE_ZERO_PADDING_PATTERN
|
36
|
+
'00'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_s
|
41
|
+
"#{padding}#{str}"
|
42
|
+
end
|
43
|
+
|
44
|
+
# to hex string (e.g. \x9F)
|
45
|
+
def to_hs
|
46
|
+
self.class.str(to_s)
|
47
|
+
end
|
48
|
+
|
49
|
+
def concat(other)
|
50
|
+
to_s + other.to_s
|
51
|
+
end
|
52
|
+
|
53
|
+
ARITHMETIC_OPERATORS.each do |method|
|
54
|
+
class_eval <<-CODE, __FILE__, __LINE__ + 1
|
55
|
+
def #{method}(other)
|
56
|
+
self.class.new(to_i.#{method}(other.to_i))
|
57
|
+
end
|
58
|
+
CODE
|
59
|
+
end
|
60
|
+
|
61
|
+
def zero?
|
62
|
+
to_i.zero?
|
63
|
+
end
|
64
|
+
|
65
|
+
def mod_exp(b, m)
|
66
|
+
self.class.new(_mod_exp(to_i, b.to_i, m.to_i))
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def validate_str!(val)
|
72
|
+
return val if val =~ HEX_STRING_PATTERN
|
73
|
+
|
74
|
+
raise ArgumentError, "'#{val}' must be a hex string"
|
75
|
+
end
|
76
|
+
|
77
|
+
# Modular Exponentiation
|
78
|
+
# https://en.wikipedia.org/wiki/Modular_exponentiation
|
79
|
+
# http://rosettacode.org/wiki/Modular_exponentiation#Ruby
|
80
|
+
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.5')
|
81
|
+
class_eval <<-CODE, __FILE__, __LINE__ + 1
|
82
|
+
def _mod_exp(a, b, m)
|
83
|
+
a.to_bn.mod_exp(b, m).to_i
|
84
|
+
end
|
85
|
+
CODE
|
86
|
+
else
|
87
|
+
class_eval <<-CODE, __FILE__, __LINE__ + 1
|
88
|
+
def _mod_exp(a, b, m)
|
89
|
+
a.pow(b, m)
|
90
|
+
end
|
91
|
+
CODE
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/lib/aws_srp/srp.rb
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AwsSRP
|
4
|
+
# SRP related logic
|
5
|
+
# Titleized methods are not common in ruby so `A` becomes `aa`
|
6
|
+
class SRP
|
7
|
+
N = %w[
|
8
|
+
FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08
|
9
|
+
8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B
|
10
|
+
302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9
|
11
|
+
A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6
|
12
|
+
49286651 ECE45B3D C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8
|
13
|
+
FD24CF5F 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D
|
14
|
+
670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B E39E772C
|
15
|
+
180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 DE2BCBF6 95581718
|
16
|
+
3995497C EA956AE5 15D22618 98FA0510 15728E5A 8AAAC42D AD33170D
|
17
|
+
04507A33 A85521AB DF1CBA64 ECFB8504 58DBEF0A 8AEA7157 5D060C7D
|
18
|
+
B3970F85 A6E1E4C7 ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226
|
19
|
+
1AD2EE6B F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C
|
20
|
+
BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 43DB5BFC
|
21
|
+
E0FD108E 4B82D120 A93AD2CA FFFFFFFF FFFFFFFF
|
22
|
+
].freeze
|
23
|
+
INFO_BITS = "Caldera Derived Key\u0001"
|
24
|
+
|
25
|
+
attr_reader :nn, :g, :a, :username, :password, :salt, :bb
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
@nn = Hex.new(N.join)
|
29
|
+
@g = Hex.new(2)
|
30
|
+
@a = Hex.new(SecureRandom.hex(128))
|
31
|
+
end
|
32
|
+
|
33
|
+
# A = g^a (mod N)
|
34
|
+
def aa
|
35
|
+
@aa ||= g.mod_exp(a, nn)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Multiplier parameter
|
39
|
+
# k = H(N, g) (in SRP-6a)
|
40
|
+
def k
|
41
|
+
@k ||= hash(nn.concat(g), hex: true)
|
42
|
+
end
|
43
|
+
|
44
|
+
# u = H(A, B)
|
45
|
+
def u
|
46
|
+
srp_6a_safety_check! do
|
47
|
+
hash(aa.concat(bb), hex: true)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def credentials_hash
|
52
|
+
hash([username, password].join(':'))
|
53
|
+
end
|
54
|
+
|
55
|
+
# Private key (derived from username, raw password and salt)
|
56
|
+
# x = H(salt || H(username || ':' || password))
|
57
|
+
def x
|
58
|
+
@x ||= hash(salt.concat(credentials_hash), hex: true)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Client secret
|
62
|
+
# S = (B - (k * g^x)) ^ (a + (u * x)) % N
|
63
|
+
def ss
|
64
|
+
((bb - k * g.mod_exp(x, nn)) % nn).mod_exp(a + x * u, nn)
|
65
|
+
end
|
66
|
+
|
67
|
+
def username=(val)
|
68
|
+
reset
|
69
|
+
@username = val
|
70
|
+
end
|
71
|
+
|
72
|
+
def password=(val)
|
73
|
+
reset
|
74
|
+
@password = val
|
75
|
+
end
|
76
|
+
|
77
|
+
def salt=(val)
|
78
|
+
reset
|
79
|
+
@salt = Hex.new(val)
|
80
|
+
end
|
81
|
+
|
82
|
+
def bb=(val)
|
83
|
+
bb = Hex.new(val)
|
84
|
+
srp_6a_safety_check!(bb % nn)
|
85
|
+
|
86
|
+
reset
|
87
|
+
@bb = bb
|
88
|
+
end
|
89
|
+
|
90
|
+
def hkdf
|
91
|
+
prk = Hasher.digest(u.to_hs, ss.to_hs)
|
92
|
+
Hasher.digest(prk, INFO_BITS)[0, 16]
|
93
|
+
end
|
94
|
+
|
95
|
+
def reset
|
96
|
+
@x = nil
|
97
|
+
|
98
|
+
self
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
def hash(str, hex: false)
|
104
|
+
str = Hex.str(str) if hex
|
105
|
+
hexdigest = Hasher.hexdigest(str)
|
106
|
+
|
107
|
+
hex ? Hex.new(hexdigest) : hexdigest
|
108
|
+
end
|
109
|
+
|
110
|
+
def srp_6a_safety_check!(val = nil)
|
111
|
+
val ||= yield
|
112
|
+
|
113
|
+
raise ArgumentError, 'SRP-6a safety check failed' if val.zero?
|
114
|
+
|
115
|
+
val
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: aws-srp
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tim Masliuchenko
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-09-08 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: AWS Cognito SRP Utility
|
14
|
+
email:
|
15
|
+
- insside@gmail.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- ".gitignore"
|
21
|
+
- ".rspec"
|
22
|
+
- ".travis.yml"
|
23
|
+
- Gemfile
|
24
|
+
- Gemfile.lock
|
25
|
+
- LICENSE.txt
|
26
|
+
- README.md
|
27
|
+
- Rakefile
|
28
|
+
- aws-srp.gemspec
|
29
|
+
- bin/console
|
30
|
+
- bin/setup
|
31
|
+
- lib/aws-srp.rb
|
32
|
+
- lib/aws_srp.rb
|
33
|
+
- lib/aws_srp/flow.rb
|
34
|
+
- lib/aws_srp/flow/password_verifier_response.rb
|
35
|
+
- lib/aws_srp/hasher.rb
|
36
|
+
- lib/aws_srp/hex.rb
|
37
|
+
- lib/aws_srp/srp.rb
|
38
|
+
- lib/aws_srp/version.rb
|
39
|
+
homepage: https://github.com/timsly/aws-srp
|
40
|
+
licenses:
|
41
|
+
- MIT
|
42
|
+
metadata:
|
43
|
+
homepage_uri: https://github.com/timsly/aws-srp
|
44
|
+
source_code_uri: https://github.com/timsly/aws-srp
|
45
|
+
post_install_message:
|
46
|
+
rdoc_options: []
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 2.3.0
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
59
|
+
requirements: []
|
60
|
+
rubygems_version: 3.0.3
|
61
|
+
signing_key:
|
62
|
+
specification_version: 4
|
63
|
+
summary: AWS Cognito SRP Utility
|
64
|
+
test_files: []
|