webauthn 0.2.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5909a9f479ed26b128466cf3843acb514a669e81f0d751d88ff2c5a5cd0a9c7c
4
- data.tar.gz: d03b48fa85cf79bae08461ca31635d3b02f21f421ae4fe6ce1f2257e1c50a1f3
3
+ metadata.gz: 004107dfab888cb866245f75d634764ffb859974f12e5d70b30304a6d8c25ce1
4
+ data.tar.gz: 2cdfacf2e938a030f494717d644ae394f1f55a759e5eff125face25f7eda16d7
5
5
  SHA512:
6
- metadata.gz: 232ffa7b3009a5c955711d50fcd16f90f60b8ddc2034f5c626090e42c50175cae27217cad53abf1c09fec8448d3fb507cfb93ca2ed2377ed273084f61ddd010a
7
- data.tar.gz: bf6633710657c45f5ef153eaa234fc278f533b2b429f9c475e366194d65e8d06a321c8ef33e01c79d5bf0170fe19c19f60a77d7298912df6cff629eb5dee1c3c
6
+ metadata.gz: c3080d2ca2560908ff75ab0a100226c9526e3909cdbadc6d166050fbea710b0f48f52f56ea315ff7e2e98d4a877ad5da1e85a12cb9f3f57784b99f5a8416e76a
7
+ data.tar.gz: e1d08103e408ec0e9b4561d1b24b886a013392ddf13044cf62b13046ea8754aec2ff184f75d48ec1710d4c53bb841f87289e8bbe5c2d5c496f40b683a1b353be
data/.rubocop.yml CHANGED
@@ -28,8 +28,164 @@ Performance:
28
28
  Security:
29
29
  Enabled: true
30
30
 
31
+ Style/BlockComments:
32
+ Enabled: true
33
+
34
+ Style/BracesAroundHashParameters:
35
+ Enabled: true
36
+
37
+ Style/CaseEquality:
38
+ Enabled: true
39
+
40
+ Style/ClassAndModuleChildren:
41
+ Enabled: true
42
+
43
+ Style/ClassMethods:
44
+ Enabled: true
45
+
46
+ Style/ClassVars:
47
+ Enabled: true
48
+
49
+ Style/CommentAnnotation:
50
+ Enabled: true
51
+
52
+ Style/ConditionalAssignment:
53
+ Enabled: true
54
+
55
+ Style/DefWithParentheses:
56
+ Enabled: true
57
+
58
+ Style/Dir:
59
+ Enabled: true
60
+
61
+ Style/EachForSimpleLoop:
62
+ Enabled: true
63
+
64
+ Style/EachWithObject:
65
+ Enabled: true
66
+
67
+ Style/EmptyBlockParameter:
68
+ Enabled: true
69
+
70
+ Style/EmptyCaseCondition:
71
+ Enabled: true
72
+
73
+ Style/EmptyElse:
74
+ Enabled: true
75
+
76
+ Style/EmptyLambdaParameter:
77
+ Enabled: true
78
+
79
+ Style/EmptyLiteral:
80
+ Enabled: true
81
+
82
+ Style/EvenOdd:
83
+ Enabled: true
84
+
85
+ Style/ExpandPathArguments:
86
+ Enabled: true
87
+
88
+ Style/For:
89
+ Enabled: true
90
+
31
91
  Style/FrozenStringLiteralComment:
32
92
  Enabled: true
33
93
 
94
+ Style/GlobalVars:
95
+ Enabled: true
96
+
97
+ Style/HashSyntax:
98
+ Enabled: true
99
+
100
+ Style/IdenticalConditionalBranches:
101
+ Enabled: true
102
+
103
+ Style/IfInsideElse:
104
+ Enabled: true
105
+
106
+ Style/InverseMethods:
107
+ Enabled: true
108
+
109
+ Style/MethodCallWithoutArgsParentheses:
110
+ Enabled: true
111
+
112
+ Style/MethodDefParentheses:
113
+ Enabled: true
114
+
115
+ Style/MultilineMemoization:
116
+ Enabled: true
117
+
118
+ Style/MutableConstant:
119
+ Enabled: true
120
+
121
+ Style/NestedParenthesizedCalls:
122
+ Enabled: true
123
+
124
+ Style/OptionalArguments:
125
+ Enabled: true
126
+
127
+ Style/ParenthesesAroundCondition:
128
+ Enabled: true
129
+
130
+ Style/RedundantBegin:
131
+ Enabled: true
132
+
133
+ Style/RedundantConditional:
134
+ Enabled: true
135
+
136
+ Style/RedundantException:
137
+ Enabled: true
138
+
34
139
  Style/RedundantFreeze:
35
140
  Enabled: true
141
+
142
+ Style/RedundantParentheses:
143
+ Enabled: true
144
+
145
+ Style/RedundantReturn:
146
+ Enabled: true
147
+
148
+ Style/RedundantSelf:
149
+ Enabled: true
150
+
151
+ Style/Semicolon:
152
+ Enabled: true
153
+
154
+ Style/SingleLineMethods:
155
+ Enabled: true
156
+
157
+ Style/SpecialGlobalVars:
158
+ Enabled: true
159
+
160
+ Style/SymbolLiteral:
161
+ Enabled: true
162
+
163
+ Style/TrailingBodyOnClass:
164
+ Enabled: true
165
+
166
+ Style/TrailingBodyOnMethodDefinition:
167
+ Enabled: true
168
+
169
+ Style/TrailingBodyOnModule:
170
+ Enabled: true
171
+
172
+ Style/TrailingMethodEndStatement:
173
+ Enabled: true
174
+
175
+ Style/TrivialAccessors:
176
+ Enabled: true
177
+
178
+ Style/UnneededInterpolation:
179
+ Enabled: true
180
+
181
+ Style/UnneededPercentQ:
182
+ Enabled: true
183
+
184
+ Style/UnpackFirst:
185
+ Enabled: true
186
+
187
+ Style/YodaCondition:
188
+ Enabled: true
189
+
190
+ Style/ZeroLengthPredicate:
191
+ Enabled: true
data/CHANGELOG.md CHANGED
@@ -1,6 +1,18 @@
1
1
  # Changelog
2
2
 
3
- ## [Unreleased]
3
+ ## [v1.0.0] - 2018-09-07
4
+
5
+ ### Added
6
+
7
+ - _Authentication_ ceremony
8
+ - Support multiple credentials per user by letting `WebAuthn::AuthenticatorAssertionResponse.valid?` receive multiple allowed credentials
9
+
10
+ ### Changed
11
+
12
+ - _Registration_ ceremony
13
+ - Use 32-byte challenge instead of 16-byte
14
+ - _Authentication_ ceremony
15
+ - Use 32-byte challenge instead of 16-byte
4
16
 
5
17
  ## [v0.2.0] - 2018-06-08
6
18
 
@@ -39,6 +51,6 @@
39
51
  - `WebAuthn::AuthenticatorAttestationResponse.valid?` can be used to validate fido-u2f attestations returned by the browser
40
52
  - Works with ruby 2.5
41
53
 
42
- [Unreleased]: https://github.com/cedarcode/webauthn-ruby/compare/v0.2.0...HEAD/
54
+ [v1.0.0]: https://github.com/cedarcode/webauthn-ruby/compare/v0.2.0...v1.0.0/
43
55
  [v0.2.0]: https://github.com/cedarcode/webauthn-ruby/compare/v0.1.0...v0.2.0/
44
56
  [v0.1.0]: https://github.com/cedarcode/webauthn-ruby/compare/v0.0.0...v0.1.0/
data/README.md CHANGED
@@ -1,12 +1,10 @@
1
1
  # WebAuthn :key:
2
2
 
3
- Easily implement WebAuthn in your ruby web server
3
+ Easily implement WebAuthn in your ruby/rails app
4
4
 
5
5
  [![Gem](https://img.shields.io/gem/v/webauthn.svg?style=flat-square)](https://rubygems.org/gems/webauthn)
6
6
  [![Travis](https://img.shields.io/travis/cedarcode/webauthn-ruby.svg?style=flat-square)](https://travis-ci.org/cedarcode/webauthn-ruby)
7
7
 
8
- ## WARNING: This gem is in the early development phase. Use on production at your own risk.
9
-
10
8
  ## What is WebAuthn?
11
9
 
12
10
  - [WebAuthn article with Google IO 2018 talk](https://developers.google.com/web/updates/2018/05/webauthn)
@@ -16,7 +14,7 @@ Easily implement WebAuthn in your ruby web server
16
14
 
17
15
  ## Prerequisites
18
16
 
19
- This gem will help your ruby server act as a conforming [_Relying-Party_](https://www.w3.org/TR/webauthn/#relying-party), in WebAuthn terminology. But for the [_Registration_](https://www.w3.org/TR/webauthn/#registration) and [_Authentiction_](https://www.w3.org/TR/webauthn/#authentication) ceremonies to work, you will also need
17
+ This gem will help your ruby server act as a conforming [_Relying-Party_](https://www.w3.org/TR/webauthn/#relying-party), in WebAuthn terminology. But for the [_Registration_](https://www.w3.org/TR/webauthn/#registration) and [_Authentication_](https://www.w3.org/TR/webauthn/#authentication) ceremonies to work, you will also need
20
18
 
21
19
  ### A conforming User Agent
22
20
 
@@ -153,6 +151,24 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
153
151
 
154
152
  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).
155
153
 
154
+ ### Commit message format
155
+
156
+ Each commit message follows the `<type>: <message>` format.
157
+
158
+ The "message" starts with lowercase and the "type" is one of:
159
+
160
+ * __build__: Changes that affect the build system or external dependencies
161
+ * __ci__: Changes to the CI configuration files and scripts
162
+ * __docs__: Documentation only changes
163
+ * __feat__: A new feature
164
+ * __fix__: A bug fix
165
+ * __perf__: A code change that improves performance
166
+ * __refactor__: A code change that neither fixes a bug nor adds a feature
167
+ * __style__: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
168
+ * __test__: Adding missing tests or correcting existing tests
169
+
170
+ Inspired in a subset of [Angular's Commit Message Guidelines](https://github.com/angular/angular/blob/master/CONTRIBUTING.md#-commit-message-guidelines).
171
+
156
172
  ## Contributing
157
173
 
158
174
  Bug reports and pull requests are welcome on GitHub at https://github.com/cedarcode/webauthn-ruby.
data/Rakefile CHANGED
@@ -7,4 +7,4 @@ require "rubocop/rake_task"
7
7
  RSpec::Core::RakeTask.new(:spec)
8
8
  RuboCop::RakeTask.new
9
9
 
10
- task :default => [:rubocop, :spec]
10
+ task default: [:rubocop, :spec]
data/lib/cose/ecdsa.rb ADDED
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module COSE
4
+ module ECDSA
5
+ ALG_ES256 = -7
6
+ end
7
+ end
data/lib/webauthn.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "cose/ecdsa"
3
4
  require "webauthn/authenticator_attestation_response"
4
5
  require "webauthn/authenticator_assertion_response"
5
- require "webauthn/cose/ecdsa"
6
6
  require "webauthn/utils"
7
7
  require "webauthn/version"
8
8
 
@@ -34,7 +34,7 @@ module WebAuthn
34
34
  end
35
35
 
36
36
  def self.challenge
37
- SecureRandom.random_bytes(16)
37
+ SecureRandom.random_bytes(32)
38
38
  end
39
39
  private_class_method :challenge
40
40
  end
@@ -12,10 +12,10 @@ module WebAuthn
12
12
  @signature = signature
13
13
  end
14
14
 
15
- def valid?(original_challenge, original_origin, allowed_credential:)
15
+ def valid?(original_challenge, original_origin, allowed_credentials:)
16
16
  super(original_challenge, original_origin) &&
17
- valid_credential?(allowed_credential[:id]) &&
18
- valid_signature?(allowed_credential[:public_key])
17
+ valid_credential?(allowed_credentials) &&
18
+ valid_signature?(credential_public_key(allowed_credentials))
19
19
  end
20
20
 
21
21
  private
@@ -36,14 +36,24 @@ module WebAuthn
36
36
  )
37
37
  end
38
38
 
39
- def valid_credential?(allowed_credential_id)
40
- allowed_credential_id == credential_id
39
+ def valid_credential?(allowed_credentials)
40
+ allowed_credential_ids = allowed_credentials.map { |credential| credential[:id] }
41
+
42
+ allowed_credential_ids.include?(credential_id)
41
43
  end
42
44
 
43
45
  def authenticator_data
44
46
  @authenticator_data ||= WebAuthn::AuthenticatorData.new(authenticator_data_bytes)
45
47
  end
46
48
 
49
+ def credential_public_key(allowed_credentials)
50
+ matched_credential = allowed_credentials.find do |credential|
51
+ credential[:id] == credential_id
52
+ end
53
+
54
+ matched_credential[:public_key]
55
+ end
56
+
47
57
  def type
48
58
  WebAuthn::TYPES[:get]
49
59
  end
@@ -58,7 +58,7 @@ module WebAuthn
58
58
  end
59
59
 
60
60
  def flags
61
- @flags ||= data_at(flags_position, FLAGS_LENGTH).unpack("b*").first
61
+ @flags ||= data_at(flags_position, FLAGS_LENGTH).unpack1("b*")
62
62
  end
63
63
 
64
64
  def flags_position
@@ -48,10 +48,7 @@ module WebAuthn
48
48
  end
49
49
 
50
50
  def id_length
51
- @id_length ||=
52
- data_at(id_length_position, ID_LENGTH_LENGTH)
53
- .unpack(UINT16_BIG_ENDIAN_FORMAT)
54
- .first
51
+ @id_length ||= data_at(id_length_position, ID_LENGTH_LENGTH).unpack1(UINT16_BIG_ENDIAN_FORMAT)
55
52
  end
56
53
 
57
54
  def id_length_position
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "webauthn/cose/ecdsa"
4
- require "webauthn/cose/key/ec2"
3
+ require "cose/ecdsa"
4
+ require "cose/key/ec2"
5
5
 
6
6
  module WebAuthn
7
7
  class AuthenticatorData
@@ -17,7 +17,7 @@ module WebAuthn
17
17
  data.size >= COORDINATE_LENGTH * 2 &&
18
18
  cose_key.x_coordinate.length == COORDINATE_LENGTH &&
19
19
  cose_key.y_coordinate.length == COORDINATE_LENGTH &&
20
- cose_key.algorithm == WebAuthn::COSE::ECDSA::ALG_ES256
20
+ cose_key.algorithm == COSE::ECDSA::ALG_ES256
21
21
  end
22
22
 
23
23
  def to_str
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module WebAuthn
4
- VERSION = "0.2.0"
4
+ VERSION = "1.0.0"
5
5
  end
data/webauthn.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- lib = File.expand_path("../lib", __FILE__)
3
+ lib = File.expand_path('lib', __dir__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
  require "webauthn/version"
6
6
 
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.authors = ["Gonzalo Rodriguez", "Braulio Martinez"]
11
11
  spec.email = ["gonzalo@cedarcode.com", "braulio@cedarcode.com"]
12
12
 
13
- spec.summary = %q{Web Authentication API Relying Party in ruby}
13
+ spec.summary = "WebAuthn in ruby ― Ruby implementation of a WebAuthn Relying Party"
14
14
  spec.homepage = "https://github.com/cedarcode/webauthn-ruby"
15
15
  spec.license = "MIT"
16
16
 
@@ -28,6 +28,7 @@ Gem::Specification.new do |spec|
28
28
  spec.require_paths = ["lib"]
29
29
 
30
30
  spec.add_dependency "cbor", "~> 0.5.9.2"
31
+ spec.add_dependency "cose", "~> 0.1.0"
31
32
 
32
33
  spec.add_development_dependency "bundler", "~> 1.16"
33
34
  spec.add_development_dependency "byebug", "~> 10.0"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: webauthn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gonzalo Rodriguez
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2018-06-08 00:00:00.000000000 Z
12
+ date: 2018-09-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: cbor
@@ -25,6 +25,20 @@ dependencies:
25
25
  - - "~>"
26
26
  - !ruby/object:Gem::Version
27
27
  version: 0.5.9.2
28
+ - !ruby/object:Gem::Dependency
29
+ name: cose
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: 0.1.0
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: 0.1.0
28
42
  - !ruby/object:Gem::Dependency
29
43
  name: bundler
30
44
  requirement: !ruby/object:Gem::Requirement
@@ -114,6 +128,7 @@ files:
114
128
  - Rakefile
115
129
  - bin/console
116
130
  - bin/setup
131
+ - lib/cose/ecdsa.rb
117
132
  - lib/webauthn.rb
118
133
  - lib/webauthn/attestation_statement.rb
119
134
  - lib/webauthn/attestation_statement/base.rb
@@ -126,8 +141,6 @@ files:
126
141
  - lib/webauthn/authenticator_data/attested_credential_data/public_key_u2f.rb
127
142
  - lib/webauthn/authenticator_response.rb
128
143
  - lib/webauthn/client_data.rb
129
- - lib/webauthn/cose/ecdsa.rb
130
- - lib/webauthn/cose/key/ec2.rb
131
144
  - lib/webauthn/utils.rb
132
145
  - lib/webauthn/version.rb
133
146
  - webauthn.gemspec
@@ -157,5 +170,5 @@ rubyforge_project:
157
170
  rubygems_version: 2.7.7
158
171
  signing_key:
159
172
  specification_version: 4
160
- summary: Web Authentication API Relying Party in ruby
173
+ summary: WebAuthn in ruby ― Ruby implementation of a WebAuthn Relying Party
161
174
  test_files: []
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module WebAuthn
4
- module COSE
5
- module ECDSA
6
- ALG_ES256 = -7
7
- end
8
- end
9
- end
@@ -1,53 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module WebAuthn
4
- # COSE module has the potential to being extracted out of WebAuthn
5
- module COSE
6
- module Key
7
- class EC2
8
- KTY_LABEL = 1
9
- ALG_LABEL = 3
10
-
11
- CRV_LABEL = -1
12
- X_LABEL = -2
13
- Y_LABEL = -3
14
-
15
- KTY_EC2 = 2
16
-
17
- attr_reader :algorithm, :curve, :x_coordinate, :y_coordinate
18
-
19
- def initialize(algorithm: nil, curve:, x_coordinate:, y_coordinate:)
20
- if !curve
21
- raise ArgumentError, "Required curve is missing"
22
- elsif !x_coordinate
23
- raise ArgumentError, "Required x-coordinate is missing"
24
- elsif !y_coordinate
25
- raise ArgumentError, "Required y-coordinate is missing"
26
- else
27
- @algorithm = algorithm
28
- @curve = curve
29
- @x_coordinate = x_coordinate
30
- @y_coordinate = y_coordinate
31
- end
32
- end
33
-
34
- def self.from_map(map)
35
- if map[KTY_LABEL] == KTY_EC2
36
- new(
37
- algorithm: map[ALG_LABEL],
38
- curve: map[CRV_LABEL],
39
- x_coordinate: map[X_LABEL],
40
- y_coordinate: map[Y_LABEL]
41
- )
42
- else
43
- raise "Not an EC2 key"
44
- end
45
- end
46
-
47
- def self.from_cbor(cbor)
48
- from_map(CBOR.decode(cbor))
49
- end
50
- end
51
- end
52
- end
53
- end