web_authn 0.1.1 → 0.2.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: 89d25f455fdd1323936c0c32072be162f888df15e7ddd86fb65549e9f37736fb
4
- data.tar.gz: ecb31a66853aeaca039da91aeb66ca5a24b5ee9f103153ed76ae6593fc1071ea
3
+ metadata.gz: 07b7a1b06a7ad5f04c3d303de0f8f099c0ce71038e78934268bf99243600d86c
4
+ data.tar.gz: 60a474a75148dff57396fc3e939fc94a83a58496ef95bca71f5a29747674651b
5
5
  SHA512:
6
- metadata.gz: dee33babaf79b1ba80f86321223206c56e59c7c3e5adc113bb8a4f51d8d9c185d5eb1b62219a408e98130265d75e9ee1fa648794d3db8f60ab32551cbd5c83bb
7
- data.tar.gz: 70fdbe9c79f25a5044eea4ac2b06815d6f5c128e0db61c03f930577cba78dc2d5e6fcf46324823fefa9dcefab2b76ccd648e3e769a12020f123f7f0d128b7798
6
+ metadata.gz: 5876b9449153f9309057f48632121f0302b3a7fb663d968b441a374b40c09f9b88447b64101d44e92c2b1be6287e2f11c0373b44ca2c2532aa96d1b658d7899d
7
+ data.tar.gz: b598691bcb6d42ef76f72ae650931d47888cf573f5ad45759d2d834c3174256f69521f9496a101caf206386d366b9f476efe99864100e8bc9ad78cee7d4be7ae
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.2.0
@@ -5,7 +5,7 @@ module WebAuthn
5
5
  alias_method :att_stmt, :attestation_statement
6
6
  alias_method :auth_data, :authenticator_data
7
7
 
8
- %i(credential_id rp_id_hash flags public_key sign_count).each do |method|
8
+ %i(credential_id rp_id_hash flags public_key public_cose_key sign_count).each do |method|
9
9
  delegate method, to: :authenticator_data
10
10
  end
11
11
 
@@ -1,11 +1,12 @@
1
1
  module WebAuthn
2
2
  class AttestedCredentialData
3
- attr_accessor :aaguid, :credential_id, :public_key
3
+ attr_accessor :aaguid, :credential_id, :public_key, :public_cose_key
4
4
 
5
- def initialize(aaguid:, credential_id:, public_key:)
5
+ def initialize(aaguid:, credential_id:, public_key:, public_cose_key:)
6
6
  self.aaguid = aaguid
7
7
  self.credential_id = credential_id
8
8
  self.public_key = public_key
9
+ self.public_cose_key = public_cose_key
9
10
  end
10
11
 
11
12
  class << self
@@ -21,10 +22,12 @@ module WebAuthn
21
22
  attested_credential_data.byteslice(18...(18 + length)),
22
23
  attested_credential_data.byteslice((18 + length)..-1),
23
24
  ]
25
+ cose_key = COSE::Key.decode(cose_key_cbor)
24
26
  new(
25
27
  aaguid: Base64.urlsafe_encode64(aaguid, padding: false),
26
28
  credential_id: Base64.urlsafe_encode64(credential_id, padding: false),
27
- public_key: COSE::Key.decode(cose_key_cbor).to_key
29
+ public_key: cose_key.to_key,
30
+ public_cose_key: cose_key
28
31
  )
29
32
  end
30
33
  end
@@ -2,7 +2,7 @@ module WebAuthn
2
2
  class AuthenticatorData
3
3
  attr_accessor :rp_id_hash, :flags, :sign_count, :attested_credential_data, :raw
4
4
 
5
- %i(credential_id public_key).each do |method|
5
+ %i(credential_id public_key public_cose_key).each do |method|
6
6
  delegate method, to: :attested_credential_data, allow_nil: true
7
7
  end
8
8
 
@@ -12,13 +12,17 @@ module WebAuthn
12
12
  true
13
13
  end
14
14
 
15
- def verify!(encoded_authenticator_data, public_key:, sign_count:, signature:)
15
+ def verify!(encoded_authenticator_data, sign_count:, signature:, public_key: nil, public_cose_key: nil, digest: OpenSSL::Digest::SHA256.new)
16
+ unless public_key || public_cose_key
17
+ raise ArgumentError, 'missing keyword: public_key or public_cose_key'
18
+ end
19
+
16
20
  self.authenticator_data = AuthenticatorData.decode(
17
21
  Base64.urlsafe_decode64 encoded_authenticator_data
18
22
  )
19
23
  verify_flags!
20
24
  verify_sign_count!(sign_count)
21
- verify_signature!(public_key, signature)
25
+ verify_signature!(public_key, public_cose_key, signature, digest)
22
26
  self
23
27
  end
24
28
 
@@ -39,16 +43,23 @@ module WebAuthn
39
43
  end
40
44
  end
41
45
 
42
- def verify_signature!(public_key, signature)
43
- # TODO:
44
- # needs to handle digest size based on COSE key algorithm.
45
- # how to get COSE key alg header at this point?
46
+ def verify_signature!(public_key, public_cose_key, signature, digest)
46
47
  signature_base_string = [
47
48
  authenticator_data.raw,
48
49
  OpenSSL::Digest::SHA256.digest(client_data_json.raw)
49
50
  ].join
50
- result = public_key.verify(
51
- OpenSSL::Digest::SHA256.new,
51
+ if public_cose_key
52
+ public_key, digest = [public_cose_key, public_cose_key.digest]
53
+ end
54
+ verification_method = case public_key
55
+ when OpenSSL::PKey::RSA
56
+ :verify_pss
57
+ when OpenSSL::PKey::EC
58
+ :verify
59
+ end
60
+ result = public_key.send(
61
+ verification_method,
62
+ digest,
52
63
  Base64.urlsafe_decode64(signature),
53
64
  signature_base_string
54
65
  )
@@ -4,7 +4,7 @@ module WebAuthn
4
4
  attr_accessor :attestation_object
5
5
 
6
6
  # TODO: will need more methods, or let developers access deep methods by themselves.
7
- %i(credential_id rp_id_hash flags public_key sign_count).each do |method|
7
+ %i(credential_id rp_id_hash flags public_key public_cose_key sign_count).each do |method|
8
8
  delegate method, to: :attestation_object
9
9
  end
10
10
 
@@ -30,7 +30,12 @@ raise unless context.authentication?
30
30
 
31
31
  context.verify!(
32
32
  authenticator_data,
33
+ # NOTE:
34
+ # either 'public_key' or 'public_cose_key' is required.
35
+ # if `public_key` is given, you can also specify `digest` (default: `OpenSSL::Digest::SHA256.new`).
36
+ # if `public_cose_key` is given, it includes digest size information, so no `digest` is required.
33
37
  public_key: public_key,
38
+ # public_cose_key: public_cose_key,
34
39
  sign_count: sign_count,
35
40
  signature: signature
36
41
  )
@@ -36,6 +36,9 @@ ex: #{context.flags.ex}
36
36
  # Public Key
37
37
  #{context.public_key.to_pem}
38
38
 
39
+ # Public COSE Key
40
+ #{context.public_cose_key.raw}
41
+
39
42
  # Sign Count
40
43
  #{context.sign_count}
41
44
  OUT
@@ -38,6 +38,7 @@ RSpec.describe WebAuthn::Context::Registration do
38
38
  its(:rp_id_hash) { should == rp_id_hash }
39
39
  its(:flags) { should == flags }
40
40
  its(:public_key) { should be_instance_of OpenSSL::PKey::EC }
41
+ its(:public_cose_key) { should be_instance_of COSE::Key::EC2 }
41
42
  its(:public_key_pem) do
42
43
  subject.public_key.to_pem.should == public_key_pem
43
44
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: web_authn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - nov matake
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-08 00:00:00.000000000 Z
11
+ date: 2018-09-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport