Skip to content

Commit

Permalink
TRYING OUT STUFF
Browse files Browse the repository at this point in the history
  • Loading branch information
olleolleolle committed Feb 9, 2024
1 parent 657a278 commit 81806d2
Show file tree
Hide file tree
Showing 11 changed files with 90 additions and 55 deletions.
2 changes: 0 additions & 2 deletions lib/webauthn/encoder.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# frozen_string_literal: true

require "base64"

module WebAuthn
def self.standard_encoder
@standard_encoder ||= Encoder.new
Expand Down
20 changes: 17 additions & 3 deletions lib/webauthn/u2f_migrator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,22 +43,36 @@ def attestation_type
end

def attestation_trust_path
@attestation_trust_path ||= [OpenSSL::X509::Certificate.new(Base64.strict_decode64(@certificate))]
@attestation_trust_path ||= [OpenSSL::X509::Certificate.new(base64_strict_decode64(@certificate))]
end

private

def base64_strict_decode64(data)
data.unpack1("m0")
end

def base64_urlsafe_decode64(data)
if !data.end_with?("=") && data.length % 4 != 0
data = data.ljust((data.length + 3) & ~3, "=")
data.tr!("-_", "+/")
else
data = data.tr("-_", "+/")
end
data.unpack1("m0")
end

# https://fidoalliance.org/specs/fido-v2.0-rd-20180702/fido-client-to-authenticator-protocol-v2.0-rd-20180702.html#u2f-authenticatorMakeCredential-interoperability
# Let credentialId be a credentialIdLength byte array initialized with CTAP1/U2F response key handle bytes.
def credential_id
Base64.urlsafe_decode64(@key_handle)
base64_urlsafe_decode64(@key_handle)
end

# Let x9encodedUserPublicKey be the user public key returned in the U2F registration response message [U2FRawMsgs].
# Let coseEncodedCredentialPublicKey be the result of converting x9encodedUserPublicKey’s value from ANS X9.62 /
# Sec-1 v2 uncompressed curve point representation [SEC1V2] to COSE_Key representation ([RFC8152] Section 7).
def credential_cose_key
decoded_public_key = Base64.strict_decode64(@public_key)
decoded_public_key = base64_strict_decode64(@public_key)
if WebAuthn::AttestationStatement::FidoU2f::PublicKey.uncompressed_point?(decoded_public_key)
COSE::Key::EC2.new(
alg: COSE::Algorithm.by_name("ES256").id,
Expand Down
24 changes: 24 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,27 @@ def fake_certificate_chain_validation_time(attestation_statement, time)
store
end
end

def base64_strict_encode64(data)
[data].pack("m0")
end

def base64_strict_decode64(data)
data.unpack1("m0")
end

def base64_urlsafe_decode64(data)
if !data.end_with?("=") && data.length % 4 != 0
data = data.ljust((data.length + 3) & ~3, "=")
data.tr!("-_", "+/")
else
data = data.tr("-_", "+/")
end
data.unpack1("m0")
end

def base64_urlsafe_encode64(data)
str = base64_strict_encode64(data)
str.tr!("+/", "-_")
str
end
6 changes: 3 additions & 3 deletions spec/webauthn/attestation_statement/android_safetynet_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
payload,
attestation_key,
"RS256",
x5c: [Base64.strict_encode64(leaf_certificate.to_der)]
x5c: [base64_strict_encode64(leaf_certificate.to_der)]
)
end

Expand All @@ -26,7 +26,7 @@
end
let(:timestamp) { Time.now }
let(:cts_profile_match) { true }
let(:nonce) { Base64.strict_encode64(OpenSSL::Digest::SHA256.digest(authenticator_data_bytes + client_data_hash)) }
let(:nonce) { base64_strict_encode64(OpenSSL::Digest::SHA256.digest(authenticator_data_bytes + client_data_hash)) }
let(:attestation_key) { create_rsa_key }

let(:leaf_certificate) do
Expand Down Expand Up @@ -63,7 +63,7 @@
end

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

it "returns false" do
expect(statement.valid?(authenticator_data, client_data_hash)).to be_falsy
Expand Down
8 changes: 4 additions & 4 deletions spec/webauthn/authenticator_assertion_response_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -320,12 +320,12 @@
let(:assertion_data) { seeds[:u2f_migration][:assertion] }
let(:assertion_response) do
WebAuthn::AuthenticatorAssertionResponse.new(
client_data_json: Base64.strict_decode64(assertion_data[:response][:client_data_json]),
authenticator_data: Base64.strict_decode64(assertion_data[:response][:authenticator_data]),
signature: Base64.strict_decode64(assertion_data[:response][:signature])
client_data_json: base64_strict_decode64(assertion_data[:response][:client_data_json]),
authenticator_data: base64_strict_decode64(assertion_data[:response][:authenticator_data]),
signature: base64_strict_decode64(assertion_data[:response][:signature])
)
end
let(:original_challenge) { Base64.strict_decode64(assertion_data[:challenge]) }
let(:original_challenge) { base64_strict_decode64(assertion_data[:challenge]) }

context "when correct FIDO AppID is given as rp_id" do
it "verifies" do
Expand Down
48 changes: 24 additions & 24 deletions spec/webauthn/authenticator_attestation_response_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@

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

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

WebAuthn::AuthenticatorAttestationResponse.new(
attestation_object: Base64.strict_decode64(response[:attestation_object]),
client_data_json: Base64.strict_decode64(response[:client_data_json])
attestation_object: base64_strict_decode64(response[:attestation_object]),
client_data_json: base64_strict_decode64(response[:client_data_json])
)
end

Expand Down Expand Up @@ -98,7 +98,7 @@
let(:origin) { "https://localhost:13010" }

let(:original_challenge) do
Base64.strict_decode64(
base64_strict_decode64(
seeds[:security_key_packed_self][:credential_creation_options][:challenge]
)
end
Expand All @@ -107,8 +107,8 @@
response = seeds[:security_key_packed_self][:authenticator_attestation_response]

WebAuthn::AuthenticatorAttestationResponse.new(
attestation_object: Base64.strict_decode64(response[:attestation_object]),
client_data_json: Base64.strict_decode64(response[:client_data_json])
attestation_object: base64_strict_decode64(response[:attestation_object]),
client_data_json: base64_strict_decode64(response[:client_data_json])
)
end

Expand Down Expand Up @@ -140,7 +140,7 @@
let(:origin) { "http://localhost:3000" }

let(:original_challenge) do
Base64.strict_decode64(
base64_strict_decode64(
seeds[:security_key_packed_x5c][:credential_creation_options][:challenge]
)
end
Expand All @@ -149,8 +149,8 @@
response = seeds[:security_key_packed_x5c][:authenticator_attestation_response]

WebAuthn::AuthenticatorAttestationResponse.new(
attestation_object: Base64.strict_decode64(response[:attestation_object]),
client_data_json: Base64.strict_decode64(response[:client_data_json])
attestation_object: base64_strict_decode64(response[:attestation_object]),
client_data_json: base64_strict_decode64(response[:client_data_json])
)
end

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

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

WebAuthn::AuthenticatorAttestationResponse.new(
attestation_object: Base64.strict_decode64(response[:attestation_object]),
client_data_json: Base64.strict_decode64(response[:client_data_json])
attestation_object: base64_strict_decode64(response[:attestation_object]),
client_data_json: base64_strict_decode64(response[:client_data_json])
)
end

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

let(:original_challenge) do
Base64.strict_decode64(seeds[:android_safetynet_direct][:credential_creation_options][:challenge])
base64_strict_decode64(seeds[:android_safetynet_direct][:credential_creation_options][:challenge])
end

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

WebAuthn::AuthenticatorAttestationResponse.new(
attestation_object: Base64.strict_decode64(response[:attestation_object]),
client_data_json: Base64.strict_decode64(response[:client_data_json])
attestation_object: base64_strict_decode64(response[:attestation_object]),
client_data_json: base64_strict_decode64(response[:client_data_json])
)
end

Expand Down Expand Up @@ -288,15 +288,15 @@
let(:origin) { seeds[:android_key_direct][:origin] }

let(:original_challenge) do
Base64.urlsafe_decode64(seeds[:android_key_direct][:credential_creation_options][:challenge])
base64_urlsafe_decode64(seeds[:android_key_direct][:credential_creation_options][:challenge])
end

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

WebAuthn::AuthenticatorAttestationResponse.new(
attestation_object: Base64.urlsafe_decode64(response[:attestation_object]),
client_data_json: Base64.urlsafe_decode64(response[:client_data_json])
attestation_object: base64_urlsafe_decode64(response[:attestation_object]),
client_data_json: base64_urlsafe_decode64(response[:client_data_json])
)
end

Expand Down Expand Up @@ -332,15 +332,15 @@
let(:origin) { seeds[:macbook_touch_id][:origin] }

let(:original_challenge) do
Base64.urlsafe_decode64(seeds[:macbook_touch_id][:credential_creation_options][:challenge])
base64_urlsafe_decode64(seeds[:macbook_touch_id][:credential_creation_options][:challenge])
end

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

WebAuthn::AuthenticatorAttestationResponse.new(
attestation_object: Base64.urlsafe_decode64(response[:attestation_object]),
client_data_json: Base64.urlsafe_decode64(response[:client_data_json])
attestation_object: base64_urlsafe_decode64(response[:attestation_object]),
client_data_json: base64_urlsafe_decode64(response[:client_data_json])
)
end

Expand Down Expand Up @@ -546,7 +546,7 @@

describe "attestation statement verification" do
let(:original_challenge) do
Base64.strict_decode64(seeds[:security_key_direct][:credential_creation_options][:challenge])
base64_strict_decode64(seeds[:security_key_direct][:credential_creation_options][:challenge])
end

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

WebAuthn::AuthenticatorAttestationResponse.new(
attestation_object: Base64.strict_decode64(response[:attestation_object]),
client_data_json: Base64.strict_decode64(response[:client_data_json])
attestation_object: base64_strict_decode64(response[:attestation_object]),
client_data_json: base64_strict_decode64(response[:client_data_json])
)
end

Expand Down
12 changes: 6 additions & 6 deletions spec/webauthn/public_key_credential_with_assertion_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@
RSpec.describe "PublicKeyCredentialWithAssertion" do
describe "#verify" do
let(:client) { WebAuthn::FakeClient.new(origin, encoding: false) }
let(:challenge) { Base64.urlsafe_encode64(raw_challenge) }
let(:challenge) { base64_urlsafe_encode64(raw_challenge) }
let(:raw_challenge) { fake_challenge }
let(:origin) { fake_origin }

let!(:credential) { create_credential(client: client) }
let(:credential_raw_id) { credential[0] }
let(:credential_id) { Base64.urlsafe_encode64(credential_raw_id) }
let(:credential_id) { base64_urlsafe_encode64(credential_raw_id) }
let(:credential_type) { "public-key" }
let(:credential_authenticator_attachment) { 'platform' }
let(:credential_public_key) { Base64.urlsafe_encode64(credential[1]) }
let(:credential_public_key) { base64_urlsafe_encode64(credential[1]) }
let(:credential_sign_count) { credential[2] }

let(:assertion_response) do
Expand Down Expand Up @@ -105,7 +105,7 @@
end

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

it "fails" do
expect do
Expand All @@ -132,7 +132,7 @@
end

context "when challenge is invalid" do
let(:challenge) { Base64.urlsafe_encode64("another challenge") }
let(:challenge) { base64_urlsafe_encode64("another challenge") }

it "fails" do
expect do
Expand Down Expand Up @@ -273,7 +273,7 @@

let(:assertion_response) do
WebAuthn::AuthenticatorAssertionResponse.new(
**seeds[:u2f_migration][:assertion][:response].transform_values { |v| Base64.strict_decode64(v) }
**seeds[:u2f_migration][:assertion][:response].transform_values { |v| base64_strict_decode64(v) }
)
end

Expand Down
8 changes: 4 additions & 4 deletions spec/webauthn/public_key_credential_with_attestation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
end

let(:type) { "public-key" }
let(:id) { Base64.urlsafe_encode64(raw_id) }
let(:id) { base64_urlsafe_encode64(raw_id) }
let(:raw_id) { SecureRandom.random_bytes(16) }
let(:authenticator_attachment) { 'platform' }

Expand All @@ -35,7 +35,7 @@
end

let(:client) { WebAuthn::FakeClient.new(origin, encoding: false) }
let(:challenge) { Base64.urlsafe_encode64(raw_challenge) }
let(:challenge) { base64_urlsafe_encode64(raw_challenge) }
let(:raw_challenge) { fake_challenge }
let(:origin) { fake_origin }

Expand Down Expand Up @@ -79,7 +79,7 @@
end

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

it "fails" do
expect { public_key_credential.verify(challenge) }.to raise_error(RuntimeError)
Expand All @@ -98,7 +98,7 @@
context "when challenge value is invalid" do
it "fails" do
expect {
public_key_credential.verify(Base64.urlsafe_encode64("another challenge"))
public_key_credential.verify(base64_urlsafe_encode64("another challenge"))
}.to raise_error(WebAuthn::ChallengeVerificationError)
end
end
Expand Down
10 changes: 5 additions & 5 deletions spec/webauthn/public_key_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@

RSpec.describe "PublicKey" do
let(:uncompressed_point_public_key) do
Base64.strict_decode64(seeds[:u2f_migration][:stored_credential][:public_key])
base64_strict_decode64(seeds[:u2f_migration][:stored_credential][:public_key])
end
let(:cose_public_key) do
Base64.urlsafe_decode64(
base64_urlsafe_decode64(
"pQECAyYgASFYIPJKd_-Rl0QtQwbLggjGC_EbUFIMriCkdc2yuaukkBuNIlggaBsBjCwnMzFL7OUGJNm4b-HVpFNUa_NbsHGARuYKHfU"
)
end
Expand Down Expand Up @@ -94,14 +94,14 @@

context "when signature was signed with public key" do
let(:signature) do
Base64.strict_decode64(seeds[:u2f_migration][:assertion][:response][:signature])
base64_strict_decode64(seeds[:u2f_migration][:assertion][:response][:signature])
end
let(:authenticator_data) do
Base64.strict_decode64(seeds[:u2f_migration][:assertion][:response][:authenticator_data])
base64_strict_decode64(seeds[:u2f_migration][:assertion][:response][:authenticator_data])
end
let(:client_data_hash) do
WebAuthn::ClientData.new(
Base64.strict_decode64(seeds[:u2f_migration][:assertion][:response][:client_data_json])
base64_strict_decode64(seeds[:u2f_migration][:assertion][:response][:client_data_json])
).hash
end
let(:verification_data) { authenticator_data + client_data_hash }
Expand Down
Loading

0 comments on commit 81806d2

Please sign in to comment.