How can I do public key pinning in Flutter?
Asked Answered
N

2

5

I want to the pin the public key of my server so that any request made to the server has to have that public key (this is to prevent proxies like Charles sniffing the data).

I had done something similar in Android with Volley.

How can I do the same with Flutter?

Nottinghamshire answered 16/2, 2019 at 18:40 Comment(2)
Possible duplicate of How to do SSL pinning via self generated signed certificates in flutter?Pasteur
I found this before. I want to pin Public Key and not the cert.Nottinghamshire
P
8

Create your client with a SecurityContext with no trusted roots to force the bad certificate callback, even for a good certificate.

SecurityContext(withTrustedRoots: false);

In the bad certificate callback, parse the DER encoded certificate using the asn1lib package. For example:

ASN1Parser p = ASN1Parser(der);
ASN1Sequence signedCert = p.nextObject() as ASN1Sequence;
ASN1Sequence cert = signedCert.elements[0] as ASN1Sequence;
ASN1Sequence pubKeyElement = cert.elements[6] as ASN1Sequence;

ASN1BitString pubKeyBits = pubKeyElement.elements[1] as ASN1BitString;

List<int> encodedPubKey = pubKeyBits.stringValue;
// could stop here and compare the encoded key parts, or...

// parse them into their modulus/exponent parts, and test those
// (assumes RSA public key)
ASN1Parser rsaParser = ASN1Parser(encodedPubKey);
ASN1Sequence keySeq = rsaParser.nextObject() as ASN1Sequence;
ASN1Integer modulus = keySeq.elements[0] as ASN1Integer;
ASN1Integer exponent = keySeq.elements[1] as ASN1Integer;

print(modulus.valueAsBigInteger);
print(exponent);
Pasteur answered 23/2, 2019 at 4:51 Comment(17)
the library and code you mentioned is giving public key of Intermediate Certificate instead of the leaf certificate for Let's Encrypt certificateNottinghamshire
paste the der or pem into lapo.it/asn1js to confirm which ASN.1 fields you need to extract and adapt as necessary.Pasteur
looks like the badCertificateCallback is being called with the parent cert (issuer cert of Lets Encrypt)Nottinghamshire
That feels like you might need to open an issue.Pasteur
Have posted it on gitter chat of dart. meanwhile you can look into the pem cert that i am receiving in the callback : shorturl.at/bwFQXNottinghamshire
as a temporary implementation I am thinking of pinning and validating the PublicKey of Let'sCrypt(5yr validity) and also checking the hostname passed in the callback if it is of the server. what do you think?Nottinghamshire
as Let'sCrypt is in general a "trusted" issuer and has a good mechanism of validating the domain owner, hence we can assume that no attacker would be issued cert with my domain by LetsCrypt. Considering that i want to prevent charles procy like server to snoop the trafic.Nottinghamshire
@HarshBhikadia Have you logged this issue under dart? Can you share the link here?Fromm
@SahilPatel Check this issue github.com/dart-lang/sdk/issues/39425Nottinghamshire
@HarshBhikadia can you please elaborate on your thinking. I am also studying these things. may be we can work together to fix these things.Reduce
@JitenBasnet are you planning to use self signed cert? then the solution in the answer will work for you. but if you are using CA issued certificate then badCertificateCallback would not be called with your certificate but the certificate of the CA, which is an unexpected behaviour for which I have filed an issueNottinghamshire
@HarshBhikadia we are a payment service provider. I think of buying/registering CA issued certificate as well. Also what would that be best self signed needed to be updated client with new app when it expires or CA issued certificate ? so quite in delemma.Reduce
if the service is also going to run on browser or something then I suggest you go with some trusted CA.Nottinghamshire
Currently we want to secure the api only to know that only valid client has been using our app. yes trusted CA are recommended. One thing though,do trusted CA also provides with der,cert,pem kind of file for us after we register them so that we use them just like setting up self signed certificate ?Reduce
Yes, with a CA you can still end up with the relevant PEM and PFX etc files. (Your private key never leaves your building, just the CSR.) Please note that certificate pinning does NOT ensure that only valid clients access the server. To achieve that you could use client side certificates, credentials, some shared secret, etcPasteur
@RichardHeap can you please tell where do i buy/register client side certificate. If i use client certificate, do i need server side certification as well ? How do client side certificate make sure they are valid user, server need to have some mechanism right ? And what would that be ?Reduce
That's not related to this question. Best to ask a new one.Pasteur
M
1

Key rotation reduces risk. When an attacker obtains an old server hard drive or backup file and gets an old server private key from it, they cannot impersonate the current server if the key has been rotated. Therefore always generate a new key when updating certificates. Configure the client to trust the old key and the new key. Wait for your users to update to the new version of the client. Then deploy the new key to your servers. Then you can remove the old key from the client.

Server key pinning is only needed if you're not rotating keys. That's bad security practice.

You should do certificate pinning with rotation. I have added example code in How to do SSL pinning via self generated signed certificates in flutter?

Monster answered 28/9, 2019 at 0:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.