Skip to content

Commit 81806d2

Browse files
committed
TRYING OUT STUFF
1 parent 657a278 commit 81806d2

11 files changed

+90
-55
lines changed

lib/webauthn/encoder.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# frozen_string_literal: true
22

3-
require "base64"
4-
53
module WebAuthn
64
def self.standard_encoder
75
@standard_encoder ||= Encoder.new

lib/webauthn/u2f_migrator.rb

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,22 +43,36 @@ def attestation_type
4343
end
4444

4545
def attestation_trust_path
46-
@attestation_trust_path ||= [OpenSSL::X509::Certificate.new(Base64.strict_decode64(@certificate))]
46+
@attestation_trust_path ||= [OpenSSL::X509::Certificate.new(base64_strict_decode64(@certificate))]
4747
end
4848

4949
private
5050

51+
def base64_strict_decode64(data)
52+
data.unpack1("m0")
53+
end
54+
55+
def base64_urlsafe_decode64(data)
56+
if !data.end_with?("=") && data.length % 4 != 0
57+
data = data.ljust((data.length + 3) & ~3, "=")
58+
data.tr!("-_", "+/")
59+
else
60+
data = data.tr("-_", "+/")
61+
end
62+
data.unpack1("m0")
63+
end
64+
5165
# https://fidoalliance.org/specs/fido-v2.0-rd-20180702/fido-client-to-authenticator-protocol-v2.0-rd-20180702.html#u2f-authenticatorMakeCredential-interoperability
5266
# Let credentialId be a credentialIdLength byte array initialized with CTAP1/U2F response key handle bytes.
5367
def credential_id
54-
Base64.urlsafe_decode64(@key_handle)
68+
base64_urlsafe_decode64(@key_handle)
5569
end
5670

5771
# Let x9encodedUserPublicKey be the user public key returned in the U2F registration response message [U2FRawMsgs].
5872
# Let coseEncodedCredentialPublicKey be the result of converting x9encodedUserPublicKey’s value from ANS X9.62 /
5973
# Sec-1 v2 uncompressed curve point representation [SEC1V2] to COSE_Key representation ([RFC8152] Section 7).
6074
def credential_cose_key
61-
decoded_public_key = Base64.strict_decode64(@public_key)
75+
decoded_public_key = base64_strict_decode64(@public_key)
6276
if WebAuthn::AttestationStatement::FidoU2f::PublicKey.uncompressed_point?(decoded_public_key)
6377
COSE::Key::EC2.new(
6478
alg: COSE::Algorithm.by_name("ES256").id,

spec/spec_helper.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,3 +186,27 @@ def fake_certificate_chain_validation_time(attestation_statement, time)
186186
store
187187
end
188188
end
189+
190+
def base64_strict_encode64(data)
191+
[data].pack("m0")
192+
end
193+
194+
def base64_strict_decode64(data)
195+
data.unpack1("m0")
196+
end
197+
198+
def base64_urlsafe_decode64(data)
199+
if !data.end_with?("=") && data.length % 4 != 0
200+
data = data.ljust((data.length + 3) & ~3, "=")
201+
data.tr!("-_", "+/")
202+
else
203+
data = data.tr("-_", "+/")
204+
end
205+
data.unpack1("m0")
206+
end
207+
208+
def base64_urlsafe_encode64(data)
209+
str = base64_strict_encode64(data)
210+
str.tr!("+/", "-_")
211+
str
212+
end

spec/webauthn/attestation_statement/android_safetynet_spec.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
payload,
1818
attestation_key,
1919
"RS256",
20-
x5c: [Base64.strict_encode64(leaf_certificate.to_der)]
20+
x5c: [base64_strict_encode64(leaf_certificate.to_der)]
2121
)
2222
end
2323

@@ -26,7 +26,7 @@
2626
end
2727
let(:timestamp) { Time.now }
2828
let(:cts_profile_match) { true }
29-
let(:nonce) { Base64.strict_encode64(OpenSSL::Digest::SHA256.digest(authenticator_data_bytes + client_data_hash)) }
29+
let(:nonce) { base64_strict_encode64(OpenSSL::Digest::SHA256.digest(authenticator_data_bytes + client_data_hash)) }
3030
let(:attestation_key) { create_rsa_key }
3131

3232
let(:leaf_certificate) do
@@ -63,7 +63,7 @@
6363
end
6464

6565
context "when nonce is not set to the base64 of the SHA256 of authData + clientDataHash" do
66-
let(:nonce) { Base64.strict_encode64(OpenSSL::Digest.digest("SHA256", "something else")) }
66+
let(:nonce) { base64_strict_encode64(OpenSSL::Digest.digest("SHA256", "something else")) }
6767

6868
it "returns false" do
6969
expect(statement.valid?(authenticator_data, client_data_hash)).to be_falsy

spec/webauthn/authenticator_assertion_response_spec.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -320,12 +320,12 @@
320320
let(:assertion_data) { seeds[:u2f_migration][:assertion] }
321321
let(:assertion_response) do
322322
WebAuthn::AuthenticatorAssertionResponse.new(
323-
client_data_json: Base64.strict_decode64(assertion_data[:response][:client_data_json]),
324-
authenticator_data: Base64.strict_decode64(assertion_data[:response][:authenticator_data]),
325-
signature: Base64.strict_decode64(assertion_data[:response][:signature])
323+
client_data_json: base64_strict_decode64(assertion_data[:response][:client_data_json]),
324+
authenticator_data: base64_strict_decode64(assertion_data[:response][:authenticator_data]),
325+
signature: base64_strict_decode64(assertion_data[:response][:signature])
326326
)
327327
end
328-
let(:original_challenge) { Base64.strict_decode64(assertion_data[:challenge]) }
328+
let(:original_challenge) { base64_strict_decode64(assertion_data[:challenge]) }
329329

330330
context "when correct FIDO AppID is given as rp_id" do
331331
it "verifies" do

spec/webauthn/authenticator_attestation_response_spec.rb

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050

5151
context "when fido-u2f attestation" do
5252
let(:original_challenge) do
53-
Base64.strict_decode64(seeds[:security_key_direct][:credential_creation_options][:challenge])
53+
base64_strict_decode64(seeds[:security_key_direct][:credential_creation_options][:challenge])
5454
end
5555

5656
let(:origin) { "http://localhost:3000" }
@@ -59,8 +59,8 @@
5959
response = seeds[:security_key_direct][:authenticator_attestation_response]
6060

6161
WebAuthn::AuthenticatorAttestationResponse.new(
62-
attestation_object: Base64.strict_decode64(response[:attestation_object]),
63-
client_data_json: Base64.strict_decode64(response[:client_data_json])
62+
attestation_object: base64_strict_decode64(response[:attestation_object]),
63+
client_data_json: base64_strict_decode64(response[:client_data_json])
6464
)
6565
end
6666

@@ -98,7 +98,7 @@
9898
let(:origin) { "https://localhost:13010" }
9999

100100
let(:original_challenge) do
101-
Base64.strict_decode64(
101+
base64_strict_decode64(
102102
seeds[:security_key_packed_self][:credential_creation_options][:challenge]
103103
)
104104
end
@@ -107,8 +107,8 @@
107107
response = seeds[:security_key_packed_self][:authenticator_attestation_response]
108108

109109
WebAuthn::AuthenticatorAttestationResponse.new(
110-
attestation_object: Base64.strict_decode64(response[:attestation_object]),
111-
client_data_json: Base64.strict_decode64(response[:client_data_json])
110+
attestation_object: base64_strict_decode64(response[:attestation_object]),
111+
client_data_json: base64_strict_decode64(response[:client_data_json])
112112
)
113113
end
114114

@@ -140,7 +140,7 @@
140140
let(:origin) { "http://localhost:3000" }
141141

142142
let(:original_challenge) do
143-
Base64.strict_decode64(
143+
base64_strict_decode64(
144144
seeds[:security_key_packed_x5c][:credential_creation_options][:challenge]
145145
)
146146
end
@@ -149,8 +149,8 @@
149149
response = seeds[:security_key_packed_x5c][:authenticator_attestation_response]
150150

151151
WebAuthn::AuthenticatorAttestationResponse.new(
152-
attestation_object: Base64.strict_decode64(response[:attestation_object]),
153-
client_data_json: Base64.strict_decode64(response[:client_data_json])
152+
attestation_object: base64_strict_decode64(response[:attestation_object]),
153+
client_data_json: base64_strict_decode64(response[:client_data_json])
154154
)
155155
end
156156

@@ -185,14 +185,14 @@
185185
context "when TPM attestation" do
186186
let(:origin) { seeds[:tpm][:origin] }
187187
let(:time) { Time.utc(2019, 8, 13, 22, 6) }
188-
let(:challenge) { Base64.strict_decode64(seeds[:tpm][:credential_creation_options][:challenge]) }
188+
let(:challenge) { base64_strict_decode64(seeds[:tpm][:credential_creation_options][:challenge]) }
189189

190190
let(:attestation_response) do
191191
response = seeds[:tpm][:authenticator_attestation_response]
192192

193193
WebAuthn::AuthenticatorAttestationResponse.new(
194-
attestation_object: Base64.strict_decode64(response[:attestation_object]),
195-
client_data_json: Base64.strict_decode64(response[:client_data_json])
194+
attestation_object: base64_strict_decode64(response[:attestation_object]),
195+
client_data_json: base64_strict_decode64(response[:client_data_json])
196196
)
197197
end
198198

@@ -244,15 +244,15 @@
244244
let(:origin) { "https://7f41ac45.ngrok.io" }
245245

246246
let(:original_challenge) do
247-
Base64.strict_decode64(seeds[:android_safetynet_direct][:credential_creation_options][:challenge])
247+
base64_strict_decode64(seeds[:android_safetynet_direct][:credential_creation_options][:challenge])
248248
end
249249

250250
let(:attestation_response) do
251251
response = seeds[:android_safetynet_direct][:authenticator_attestation_response]
252252

253253
WebAuthn::AuthenticatorAttestationResponse.new(
254-
attestation_object: Base64.strict_decode64(response[:attestation_object]),
255-
client_data_json: Base64.strict_decode64(response[:client_data_json])
254+
attestation_object: base64_strict_decode64(response[:attestation_object]),
255+
client_data_json: base64_strict_decode64(response[:client_data_json])
256256
)
257257
end
258258

@@ -288,15 +288,15 @@
288288
let(:origin) { seeds[:android_key_direct][:origin] }
289289

290290
let(:original_challenge) do
291-
Base64.urlsafe_decode64(seeds[:android_key_direct][:credential_creation_options][:challenge])
291+
base64_urlsafe_decode64(seeds[:android_key_direct][:credential_creation_options][:challenge])
292292
end
293293

294294
let(:attestation_response) do
295295
response = seeds[:android_key_direct][:authenticator_attestation_response]
296296

297297
WebAuthn::AuthenticatorAttestationResponse.new(
298-
attestation_object: Base64.urlsafe_decode64(response[:attestation_object]),
299-
client_data_json: Base64.urlsafe_decode64(response[:client_data_json])
298+
attestation_object: base64_urlsafe_decode64(response[:attestation_object]),
299+
client_data_json: base64_urlsafe_decode64(response[:client_data_json])
300300
)
301301
end
302302

@@ -332,15 +332,15 @@
332332
let(:origin) { seeds[:macbook_touch_id][:origin] }
333333

334334
let(:original_challenge) do
335-
Base64.urlsafe_decode64(seeds[:macbook_touch_id][:credential_creation_options][:challenge])
335+
base64_urlsafe_decode64(seeds[:macbook_touch_id][:credential_creation_options][:challenge])
336336
end
337337

338338
let(:attestation_response) do
339339
response = seeds[:macbook_touch_id][:authenticator_attestation_response]
340340

341341
WebAuthn::AuthenticatorAttestationResponse.new(
342-
attestation_object: Base64.urlsafe_decode64(response[:attestation_object]),
343-
client_data_json: Base64.urlsafe_decode64(response[:client_data_json])
342+
attestation_object: base64_urlsafe_decode64(response[:attestation_object]),
343+
client_data_json: base64_urlsafe_decode64(response[:client_data_json])
344344
)
345345
end
346346

@@ -546,7 +546,7 @@
546546

547547
describe "attestation statement verification" do
548548
let(:original_challenge) do
549-
Base64.strict_decode64(seeds[:security_key_direct][:credential_creation_options][:challenge])
549+
base64_strict_decode64(seeds[:security_key_direct][:credential_creation_options][:challenge])
550550
end
551551

552552
let(:origin) { "http://localhost:3000" }
@@ -555,8 +555,8 @@
555555
response = seeds[:security_key_direct][:authenticator_attestation_response]
556556

557557
WebAuthn::AuthenticatorAttestationResponse.new(
558-
attestation_object: Base64.strict_decode64(response[:attestation_object]),
559-
client_data_json: Base64.strict_decode64(response[:client_data_json])
558+
attestation_object: base64_strict_decode64(response[:attestation_object]),
559+
client_data_json: base64_strict_decode64(response[:client_data_json])
560560
)
561561
end
562562

spec/webauthn/public_key_credential_with_assertion_spec.rb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,16 @@
1313
RSpec.describe "PublicKeyCredentialWithAssertion" do
1414
describe "#verify" do
1515
let(:client) { WebAuthn::FakeClient.new(origin, encoding: false) }
16-
let(:challenge) { Base64.urlsafe_encode64(raw_challenge) }
16+
let(:challenge) { base64_urlsafe_encode64(raw_challenge) }
1717
let(:raw_challenge) { fake_challenge }
1818
let(:origin) { fake_origin }
1919

2020
let!(:credential) { create_credential(client: client) }
2121
let(:credential_raw_id) { credential[0] }
22-
let(:credential_id) { Base64.urlsafe_encode64(credential_raw_id) }
22+
let(:credential_id) { base64_urlsafe_encode64(credential_raw_id) }
2323
let(:credential_type) { "public-key" }
2424
let(:credential_authenticator_attachment) { 'platform' }
25-
let(:credential_public_key) { Base64.urlsafe_encode64(credential[1]) }
25+
let(:credential_public_key) { base64_urlsafe_encode64(credential[1]) }
2626
let(:credential_sign_count) { credential[2] }
2727

2828
let(:assertion_response) do
@@ -105,7 +105,7 @@
105105
end
106106

107107
context "because it is not the base64url of raw id" do
108-
let(:credential_id) { Base64.urlsafe_encode64(credential_raw_id + "a") }
108+
let(:credential_id) { base64_urlsafe_encode64(credential_raw_id + "a") }
109109

110110
it "fails" do
111111
expect do
@@ -132,7 +132,7 @@
132132
end
133133

134134
context "when challenge is invalid" do
135-
let(:challenge) { Base64.urlsafe_encode64("another challenge") }
135+
let(:challenge) { base64_urlsafe_encode64("another challenge") }
136136

137137
it "fails" do
138138
expect do
@@ -273,7 +273,7 @@
273273

274274
let(:assertion_response) do
275275
WebAuthn::AuthenticatorAssertionResponse.new(
276-
**seeds[:u2f_migration][:assertion][:response].transform_values { |v| Base64.strict_decode64(v) }
276+
**seeds[:u2f_migration][:assertion][:response].transform_values { |v| base64_strict_decode64(v) }
277277
)
278278
end
279279

spec/webauthn/public_key_credential_with_attestation_spec.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
end
2222

2323
let(:type) { "public-key" }
24-
let(:id) { Base64.urlsafe_encode64(raw_id) }
24+
let(:id) { base64_urlsafe_encode64(raw_id) }
2525
let(:raw_id) { SecureRandom.random_bytes(16) }
2626
let(:authenticator_attachment) { 'platform' }
2727

@@ -35,7 +35,7 @@
3535
end
3636

3737
let(:client) { WebAuthn::FakeClient.new(origin, encoding: false) }
38-
let(:challenge) { Base64.urlsafe_encode64(raw_challenge) }
38+
let(:challenge) { base64_urlsafe_encode64(raw_challenge) }
3939
let(:raw_challenge) { fake_challenge }
4040
let(:origin) { fake_origin }
4141

@@ -79,7 +79,7 @@
7979
end
8080

8181
context "because it is not the base64url of raw id" do
82-
let(:id) { Base64.urlsafe_encode64(raw_id + "a") }
82+
let(:id) { base64_urlsafe_encode64(raw_id + "a") }
8383

8484
it "fails" do
8585
expect { public_key_credential.verify(challenge) }.to raise_error(RuntimeError)
@@ -98,7 +98,7 @@
9898
context "when challenge value is invalid" do
9999
it "fails" do
100100
expect {
101-
public_key_credential.verify(Base64.urlsafe_encode64("another challenge"))
101+
public_key_credential.verify(base64_urlsafe_encode64("another challenge"))
102102
}.to raise_error(WebAuthn::ChallengeVerificationError)
103103
end
104104
end

spec/webauthn/public_key_spec.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99

1010
RSpec.describe "PublicKey" do
1111
let(:uncompressed_point_public_key) do
12-
Base64.strict_decode64(seeds[:u2f_migration][:stored_credential][:public_key])
12+
base64_strict_decode64(seeds[:u2f_migration][:stored_credential][:public_key])
1313
end
1414
let(:cose_public_key) do
15-
Base64.urlsafe_decode64(
15+
base64_urlsafe_decode64(
1616
"pQECAyYgASFYIPJKd_-Rl0QtQwbLggjGC_EbUFIMriCkdc2yuaukkBuNIlggaBsBjCwnMzFL7OUGJNm4b-HVpFNUa_NbsHGARuYKHfU"
1717
)
1818
end
@@ -94,14 +94,14 @@
9494

9595
context "when signature was signed with public key" do
9696
let(:signature) do
97-
Base64.strict_decode64(seeds[:u2f_migration][:assertion][:response][:signature])
97+
base64_strict_decode64(seeds[:u2f_migration][:assertion][:response][:signature])
9898
end
9999
let(:authenticator_data) do
100-
Base64.strict_decode64(seeds[:u2f_migration][:assertion][:response][:authenticator_data])
100+
base64_strict_decode64(seeds[:u2f_migration][:assertion][:response][:authenticator_data])
101101
end
102102
let(:client_data_hash) do
103103
WebAuthn::ClientData.new(
104-
Base64.strict_decode64(seeds[:u2f_migration][:assertion][:response][:client_data_json])
104+
base64_strict_decode64(seeds[:u2f_migration][:assertion][:response][:client_data_json])
105105
).hash
106106
end
107107
let(:verification_data) { authenticator_data + client_data_hash }

0 commit comments

Comments
 (0)