Class: Devicecheck::Assertion
- Inherits:
-
Object
- Object
- Devicecheck::Assertion
- Defined in:
- lib/devicecheck/assertion.rb
Instance Method Summary collapse
-
#assert(client_data:, client_data_challenge:, expected_challenge:, assertion_object:, count: 0) ⇒ Integer
Verifies an assertion generated by the
generateAssertion
method from DCAppAttestService. -
#initialize(app_id:, pkey_der:) ⇒ Assertion
constructor
Initialize the assertion service by providing both the App ID and the DER-encoded key that is associated with that App instance that was previously saved after it was attested.
Constructor Details
#initialize(app_id:, pkey_der:) ⇒ Assertion
Initialize the assertion service by providing both the App ID and the DER-encoded key that is associated with that App instance that was previously saved after it was attested.
24 25 26 27 28 |
# File 'lib/devicecheck/assertion.rb', line 24 def initialize(app_id:, pkey_der:) @app_id = app_id @pkey = OpenSSL::PKey.read(pkey_der) @sha256 = OpenSSL::Digest.new('SHA256') end |
Instance Method Details
#assert(client_data:, client_data_challenge:, expected_challenge:, assertion_object:, count: 0) ⇒ Integer
Verifies an assertion generated by the generateAssertion
method from DCAppAttestService.
The app must obtain a one time unique value from the server,
which we will call challenge
. Then, it will compute an
assertion by embedding this challenge into the client_data
.
For example, if client_data
is:
{ "new_score": 100 }
Then it must embed the challenge into this data, for example:
{ "new_score": 100, "challenge": "..." }
Note that using JSON strings is just an example. It depends on
the use case and the interface must be established between the
mobile app and the server. This is why we expect another
parameter (client_data_challenge
) that contains the embedded
challenge value, since this library does not make any
assumption on the format or contents of client_data
.
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/devicecheck/assertion.rb', line 69 def assert(client_data:, client_data_challenge:, expected_challenge:, assertion_object:, count: 0) decoded_assertion_object = CBOR.decode(Base64.strict_decode64(assertion_object)) signature = decoded_assertion_object['signature'] authenticator_data = decoded_assertion_object['authenticatorData'] (rp_id_hash, _, sign_count,) = Data::AuthenticatorData.unpack(authenticator_data) validate_signature!(signature, client_data, authenticator_data) validate_rp_id!(rp_id_hash) raise 'Failed count check' if sign_count < count raise 'Failed challenge check' unless client_data_challenge == expected_challenge sign_count end |