问题
I'm trying to understand how the jwt signature validation works.
This is how I'm doing it at the moment:
1) My app calls the attest api
2) My app sends the jwt to my server
3) My server verify the signature (third field of the jwt) using the certificate provided in the header of the jwt.
I understand that the signature is created by hashing the header and the payload of the jwt and then signing it (encrypting it) with Google's private key.
What I do in my step 3 is that I take the header + payload and decrypt it with certificate's public key and verify that it matches the signature. (when I say 'I' do I mean a lib does it)
My issue is that, what happens if there is a malware on the user device and amend on the fly the JWT that is sent to my server? The malware would add his own certificate (issued by a trusted CA) in the header, modify the payload as it wishes and created the signature.
Me server side... well I'm going to take the public key provided in the cert valid the signature with it which will matches.
Is this correct? Or I'am confused somewhere? Because in that case it would render this all flow a bit useless no? How doe insure myself 100% that the JWT comes from google?
回答1:
The key point is verify that the signing certificate is issued to attest.android.com
by a trusted Certificate Authority
Any trusted CA will issue a fake certificate to attest.android.com
. See what happens if they engage in bad practices https://security.googleblog.com/2016/10/distrusting-wosign-and-startcom.html?m=1
See Google's doc
Verify the compatibility check response
You should take steps to make sure that the compatibility check response actually came from the SafetyNet service and includes data that matches your request data.
Caution: You should send the entire JWS response to your own server, using a secure connection, for verification. We don't recommend that you perform the verification directly in your app because, in that case, there is no guarantee that the verification logic itself hasn't been modified.
Follow these steps to verify the origin of the JWS message:
Extract the SSL certificate chain from the JWS message.
Validate the SSL certificate chain and use SSL hostname matching to verify that the leaf certificate was issued to the hostname attest.android.com.
Use the certificate to verify the signature of the JWS message.
Check the data of the JWS message to make sure it matches the data within your original request. In particular, make sure that the nonce, timestamp, package name, and the SHA-256 hashes match.
The second dot requires to validate the certificate chain. It is assumed that it is used a Trust Manager containing the root certificate of the Certificate Authority
I have inspected Google's sample code in OfflineVerify to ensure the existence of a TrustManager because it is not explictly said, and it is effectively used during JWS verification. It uses the default system TrustManager, but you can use a custom one
Note that is used JWS (Json Web Signature), not JWT. A JWT is usually an authentication token signed with JWS
回答2:
You did grasp the concept correctly. However something that you overlooked is that the lib you use is probably verifying that the certificate from which it extracts the public keys is a valid and a 'trusted' certificate (AKA comes from a trusted CA)
Thanks to this (and like the doc points it out) you need to verify yourself that the certificate has been issued by a "attest.android.com". No one will be able to forge a certificate to make it comes from this CA because.
This is what I understood at least, please correct me if I am wrong.
来源:https://stackoverflow.com/questions/45291486/android-safetynet-jwt-signature-verification