Flowdalic/java-pinning

API suggestions

Rolf-Smit opened this issue · 4 comments

Currently we're using Java-pinning in our Android app and we need to do some more advanced stuff. As checking the certificate expire date.

While working with the library I found some difficulties, which can easily be solved by making the API a bit more flexible.

1. Make getPinBytes() public:
We needed to create an X509Certificate object (so we can obtain the expire date) and therefor we needed the raw certificate bytes, we could either do this by decoding the plain cert HEX string to a byte array, but since we we're already using some Pin objects it's way more convenient to get the bytes from those objects. Currently I have to extend the CertPlainPin in order to make the method public.

2. Add getX509Certificate() method to the CertPlainPin class
It makes sense to add some useful methods to the different Pin classes, especially obtaining the X509Certificate seems reasonable and useful. Using the library becomes way more fun with this in-place:

new CertPlainPin(hexString).getX509Certificate().checkValidity();

3. Make Pin constructors public
There is no reason to make the constructors protected. I can imagine many cases where I don't have a string with type-prefix (like: CERTPLAIN). For example in cases where I have a X509Certificate object I wan't to be able to create a Pin like this:

new CertPlainPin(tohex(x509certificate));

4. More constructors
To make it easier to create pins from things other than HEX strings it would be nice to have extra constructors, for example:

new PublicKeyPin(PublicKey publicKey);

new Pin(byte[] bytes); //This one is especially useful. Take for example my third suggestion, it can be simplified as the toHex method is not needed anymore.

new CertPlainPin(X509Certificate certificate);

5. Create a specialized exception
Currently this library reuses the java.security.cert.CertificateException exception type, this is fine however an sub type of this exception would be better, like CertificateNotPinnedException extends CertificateException as this makes it possible to differentiate between other CertificateExceptions and not pinned exceptions.

I'm willing to create a pull-request including test cases, just let me know!

Thanks for your feedback. I'm the rest of the week on a business trip, but I try to share my thoughts on your suggestions as soon as I'm back.

I'm not found of the idea of making it public because they bytes are sometimes not sufficient to re-create the certificate. It only works for 'plain' type pins. Instead I propose we create a convinince method which exaclty fits your use case: Pin.maybeGetX509Certificate(). That would be better API design IMHO.

Having CertPlainPin.getX509Certificate() seems sensible.

I do think there is a good reason to have the Pin constructors not part of the public API. Static factory methods like java-pinning currently uses are easier to handle when extending the API and also provider other benefits. It sounds what you really want is a static method Pin.fromX509Certificate(X509Certificate).

Boils to down to adding a static method Pin.fromPublicKey(PublicKey).

Creating CertificateNotPinnedException reads like a good idea.

You are welcome to contribute. I would perfer a single PR per semantic change. And sorry that it took me so long to respond.

Thanks for your response, I'm happy to contribute. I will create a few separate PR's for this.

1-2: Lets create CertPlainPin.getX509Certificate()
3-4: I agree, lets create static factory methods.
5. +1

Fixed via #9