class WebAuthn::AttestationStatement::Apple
Constants
- CERTIFICATE_EXTENSION_OID
- ROOT_CERTIFICATE
Attributes
certs[RW]
x5c[RW]
Public Class Methods
new(x5c:)
click to toggle source
# File lib/web_authn/attestation_statement/apple.rb, line 24 def initialize(x5c:) self.x5c = Array(x5c) self.certs = self.x5c.collect do |x5c| OpenSSL::X509::Certificate.new x5c end end
Private Class Methods
decode(att_stmt)
click to toggle source
# File lib/web_authn/attestation_statement/apple.rb, line 78 def decode(att_stmt) new( x5c: att_stmt[:x5c] ) end
Public Instance Methods
verify!(authenticator_data, client_data_json)
click to toggle source
# File lib/web_authn/attestation_statement/apple.rb, line 31 def verify!(authenticator_data, client_data_json) verify_nonce! authenticator_data, client_data_json verify_certificate! authenticator_data.attested_credential_data end
Private Instance Methods
verify_certificate!(attested_credential_data)
click to toggle source
# File lib/web_authn/attestation_statement/apple.rb, line 52 def verify_certificate!(attested_credential_data) attested_cert = certs.first remaining_chain = certs[1..-1] store = OpenSSL::X509::Store.new store.add_cert OpenSSL::X509::Certificate.new ROOT_CERTIFICATE valid_chain = store.verify(attested_cert, remaining_chain) valid_timestamp = ( attested_cert.not_after > Time.now && attested_cert.not_before < Time.now ) valid_attested_public_key = ( attested_credential_data.public_key.to_pem == attested_cert.public_key.to_pem ) # TODO: do we need CRL check? unless valid_chain && valid_attested_public_key && valid_timestamp raise InvalidAttestation, 'Invalid Apple Response: certificate' end end
verify_nonce!(authenticator_data, client_data_json)
click to toggle source
# File lib/web_authn/attestation_statement/apple.rb, line 38 def verify_nonce!(authenticator_data, client_data_json) nonce = OpenSSL::Digest::SHA256.digest [ authenticator_data.raw, OpenSSL::Digest::SHA256.digest(client_data_json.raw) ].join extension = certs.first.find_extension(CERTIFICATE_EXTENSION_OID) expected_nonce = OpenSSL::ASN1.decode(extension.value_der).first.value.first.value unless expected_nonce == nonce raise InvalidAttestation, 'Invalid Apple Response: nonce' end end