simplicity_client 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/fido2_client.rb +91 -0
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3283578b786c0a520eeaee6b46290f1459e9075925f8fdf172534ac533270e33
|
4
|
+
data.tar.gz: cee5f3f5ac077c4cea0bc246d7f1a4b2ea03a23db7ad21795485730685ba3959
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2ddd8ee90c05b00ba4ed232846f5c2e546e087c93c7e2c3a58965c74480640fe04823bea6d94c9b3b0f58e64f41cd738b8b157420b71d5864846cb74e0600185
|
7
|
+
data.tar.gz: fbf5d020b63bae7fd804154b34513d95e9991afa39023877905072e69df66879b4afd3e7028251204e314720c4ca472860dc9e81d86d4a90e521202791dd7bbe
|
data/lib/fido2_client.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
require "json"
|
2
|
+
require "digest"
|
3
|
+
require "openssl"
|
4
|
+
require "base64"
|
5
|
+
|
6
|
+
module Fido2Client
|
7
|
+
Passkey = Data.define(:credentialId, :keyAlgorithm, :keyCurve, :keyValue, :userHandle)
|
8
|
+
Assertion = Data.define(:authenticator_data, :client_data_json, :credential_id, :user_handle, :signature)
|
9
|
+
|
10
|
+
class Client
|
11
|
+
def initialize
|
12
|
+
@origin = "https://app.simplicity.kiwi"
|
13
|
+
@rp_id = "simplicity.kiwi"
|
14
|
+
end
|
15
|
+
|
16
|
+
def get_assertion(passkey, challenge)
|
17
|
+
collected_client_data = {
|
18
|
+
type: "webauthn.get",
|
19
|
+
challenge: challenge,
|
20
|
+
origin: @origin,
|
21
|
+
crossOrigin: false,
|
22
|
+
}
|
23
|
+
client_data_json = JSON.dump(collected_client_data)
|
24
|
+
client_data_hash = Digest::SHA256.digest(client_data_json)
|
25
|
+
|
26
|
+
# Assertion
|
27
|
+
auth_data = generate_auth_data
|
28
|
+
private_key = parse_private_key(passkey.keyAlgorithm, passkey.keyCurve, passkey.keyValue)
|
29
|
+
signature = generate_signature(auth_data, client_data_hash, private_key)
|
30
|
+
|
31
|
+
Assertion.new(
|
32
|
+
authenticator_data: Base64.urlsafe_encode64(auth_data.pack("c*"), padding: false),
|
33
|
+
client_data_json: Base64.urlsafe_encode64(client_data_json, padding: false),
|
34
|
+
credential_id: Base64.urlsafe_encode64(guid_to_raw_format(passkey.credentialId), padding: false),
|
35
|
+
user_handle: passkey.userHandle,
|
36
|
+
signature: Base64.urlsafe_encode64(signature, padding: false),
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def box(tag, lines)
|
43
|
+
lines.unshift "-----BEGIN #{tag}-----"
|
44
|
+
lines.push "-----END #{tag}-----"
|
45
|
+
lines.join("\n")
|
46
|
+
end
|
47
|
+
|
48
|
+
def der_to_pem(tag, der)
|
49
|
+
box tag, Base64.strict_encode64(der).scan(/.{1,64}/)
|
50
|
+
end
|
51
|
+
|
52
|
+
def parse_private_key(key_algorithm, key_curve, key_value)
|
53
|
+
raise "Unsupported key algorithm: #{key_algorithm}" unless key_algorithm == "ECDSA"
|
54
|
+
raise "Unsupported key curve: #{key_curve}" unless key_curve == "P-256"
|
55
|
+
|
56
|
+
# Decode the Base64 key value
|
57
|
+
key_value_bin = Base64.urlsafe_decode64(key_value)
|
58
|
+
|
59
|
+
pem = der_to_pem("PRIVATE KEY", key_value_bin)
|
60
|
+
OpenSSL::PKey::EC.new(pem)
|
61
|
+
end
|
62
|
+
|
63
|
+
def generate_signature(auth_data, client_data_hash, private_key)
|
64
|
+
sig_base = [*auth_data, *client_data_hash.bytes]
|
65
|
+
digest = OpenSSL::Digest.new("SHA256")
|
66
|
+
private_key.sign(digest, sig_base.pack("c*"))
|
67
|
+
end
|
68
|
+
|
69
|
+
def generate_auth_data
|
70
|
+
auth_data = []
|
71
|
+
rp_id_hash = Digest::SHA256.digest(@rp_id)
|
72
|
+
auth_data += rp_id_hash.bytes
|
73
|
+
|
74
|
+
# Flags asserted: Backup eligibility, Backup State, User Verification, User Presence
|
75
|
+
flags = 0x1D
|
76
|
+
auth_data.push(flags)
|
77
|
+
|
78
|
+
# Counter
|
79
|
+
auth_data += [0, 0, 0, 0]
|
80
|
+
|
81
|
+
auth_data
|
82
|
+
end
|
83
|
+
|
84
|
+
def guid_to_raw_format(guid)
|
85
|
+
raise TypeError, "GUID parameter is invalid" unless guid.match?(/\A[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\z/)
|
86
|
+
|
87
|
+
# Remove the hyphens and pack the string into raw binary
|
88
|
+
[guid.delete("-")].pack("H*")
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simplicity_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- George Dewar
|
@@ -101,6 +101,7 @@ executables: []
|
|
101
101
|
extensions: []
|
102
102
|
extra_rdoc_files: []
|
103
103
|
files:
|
104
|
+
- lib/fido2_client.rb
|
104
105
|
- lib/simplicity_client.rb
|
105
106
|
homepage: https://github.com/GeorgeDewar/simplicity_client
|
106
107
|
licenses:
|