| GitHub Issue | n/a |
| Type | New Feature |
| Priority | Critical |
| Status | Closed |
| Resolution | Fixed |
| Resolution Date | 2017-10-22T08:42:10.000+0000 |
| Affected Version/s | n/a |
| Fix Version/s | appcelerator.https 2.1.0 |
| Components | Https |
| Labels | leaf-certificate, trust-chain |
| Reporter | David Bankier |
| Assignee | Hans Knöchel |
| Created | 2017-07-03T02:58:00.000+0000 |
| Updated | 2018-08-06T17:49:36.000+0000 |
Basically you currently compare the public key of the provided certificate with the public key of the 0-indexed certificate in the site's certificate chain - the leaf certificate. I would prefer to make the index a variable. That way we can pin to the CA (or intermediate CA) so that the app does not need to be updated with every site's certificate update.
Can you please describe what's exactly is not working when specifying a CA certificate (including an example to reproduce)? Also, is this relevant for both iOS and Android? Please let us know, so we can schedule it, thanks!
Basically you currently compare the public key of the provided certificate with the public key of the 0-indexed certificate in the site's certificate chain - the leaf certificate. I would prefer to make the index a variable. That way we can pin to the CA (or intermediate CA) so that the app does not need to be updated with every site's certificate update. I am happy to implement it my self - it is pretty straight forward - it is just this is a closed source (pro) module.
While we cannot provide the module source, we will be able to implement the feature for you. Would it fit for you to have a third argument passed to
createX509CertificatePinningSecurityManagercalledtrustChainIndex, defaulting to 0 (leaf) when not set? We would support it for both platforms of course.Sounds good. Thanks.
PR: https://github.com/appcelerator-modules/appcelerator.https/pull/45/ Test-case:
var https = require('appcelerator.https'); /* * Create a Security Manager for Titanium.Network.HTTPClient that * authenticates a currated set of HTTPS servers. It does this by * "pinning" an HTTPS server's DNS name to the public key contained in * the X509 certificate it uses for TLS communication. The public key * is embedded in an app by adding this X509 certificate to the app's * Resources directory. * * With such a "pin" in place, the security manager will guarantee * that all HTTPClient connections to this HTTPS server are to a * server that holds the private key corresponding to the public key * embedded in the app, therefore authenticating the server. * * This is what prevents "Man-in-the-Middle" attack. * * This example pins two URLs. * * The first URL, https://www.americanexpress.com, is pinned to the * public key in the X.509 certificate in the file named * wellsfargo.cer. This is intentionally an incorrect configuration. * Connections to https://www.americanexpress.com must fail since the * public key presented by the host will not match the configuration of the * security manager * * The second URL, https://www.wellsfargo.com, is pinned to the public * key in the X.509 certificate in the file named * wellsfargo.cer. This is configured correctly. Connections to * https://www.wellsfargo.com must succeed. Note that these request redirect. * The redirected request is not handled by the security manager since it is * not configured but will succeed if the system is able to validate the * certificate chain presented by the redirected host. * * The X.509 certificate files can have any name and extension you * wish, but they must be in the standard DER binary format. */ var securityManager = https.createX509CertificatePinningSecurityManager([{ url: "https://www.wellsfargo.com", serverCertificate: "wellsfargo.cer", trustChainIndex: 1 // 2nd certificate in the cert-chain (Symantec Class 3 Secure Server CA) }]); var win = Titanium.UI.createWindow({ title: 'Pin Example', backgroundColor: 'white' }); var view = Ti.UI.createView({ backgroundColor: 'white', layout: 'vertical', width: Ti.UI.SIZE, height: Ti.UI.SIZE, top:20 }); var button1 = Titanium.UI.createButton({ title: 'Load wellsfargo', color: 'green', top:20, }); var label1 = Titanium.UI.createLabel({ text: 'Desc:', color: 'black', top:20, }); var label2 = Titanium.UI.createLabel({ text: 'Status:', color: 'black', top:20, }); view.add(button1); view.add(label1); view.add(label2); win.add(view); win.open(); /* * Create an HTTP client the same way you always have, but pass in an * (optional) Security Manager. In this example, we pass in the * "Certificate Pinning Security Manager " that I configured above. */ function getXHR(url) { var xhr = Ti.Network.createHTTPClient({ onload: function(e) { label2.text = 'onload called. Request succeeded'; }, onerror: function(e) { label2.text = 'onerror called. Request failed.'; }, timeout : 30000, securityManager: securityManager }); xhr.open('GET',url); return xhr; } var wf = "https://www.wellsfargo.com"; button1.addEventListener('click',function(e){ var xhr = getXHR(wf); label1.text = 'SecurityManager is configured correctly for this request. Request must succeed. '; label1.color = 'green'; label2.text = 'Desc:'; xhr.send(); });Hans, I'm just looking at the test case for the following snippet:
I'd expect that the{ url: "https://www.wellsfargo.com", serverCertificate: "wellsfargo.cer", trustChainIndex: 1 // 2nd certificate in certificate chain }serverCertificatethat would be provided would be the Symantic Class 3 Secure Server CA (intermediate CA) and that it could be reused for other server that are signed with that CA. (Rather than providing the current service certificate). The need for this is that the CAs generally last longer than a server certificate and it avoids the need for timing an update with a certificate update. Does that make sense?[~dbankier] Yes, you are correct. In my case, I'm just assuming the user renames the CA certificate to match the example certificate, but in the end it's all about the certificate itself, not the name :-). *EDIT*: For QE: I've added the
Symantec Class 3 Secure Server CA - G4certificate that is linked with Wells Fargo.Thank you.
@hknoechel, any chance that I can an early release of the module? I'm happy to run with a beta build. Thanks.
Just checking in to see if there has been any updates. It has been In Review for a couple of months and curious whether it has already been completed and Jira not updated or just forgotten about. Thanks. David
[~dbankier] It is still in review since we had two major releases that intercepted, sorry for that! Let me send you the module via mail today and we update the ticket once 6.3.0.GA is out of the door. *EDIT*: Your JIRA email-address does not seem to exist, please reach out to me via Twitter (@hansemannnn), thx!
Thanks Hans. I just sent you an email. I don't really use twitter anymore.
Got your email, but your provider keeps blocking the response. Sorry ...
SMTP error from remote mail server after pipelined end of data: 552-5.7.0 This message was blocked because its content presents a potential 552-5.7.0 security issue. Please visit 552-5.7.0 https://support.google.com/mail/?p=BlockedMessage to review our 552 5.7.0 message content and attachment content guidelines. f22si13471345wrf.172 - gsmtp Reporting-MTA: dns; smtprelay04.ispgateway.deMy guess is it is a zip file and gmail is blocking it. Can you send me a link? Or share via dropbox (same email address).
Hi Hans, I have been testing the build you sent me and the
trustChainIndexproperty doesn't seem to do anything. DavidForget to mention, testing on iOS.
Hans, for the builds you sent me, it works on Android but not on iOS.
Thanks David, we'll revisit iOS! Can you specify what exactly does not work? Does it still select the leaf only? During my testing, I was able to see the CA-cert when selecting a different index which indicated everything works. Did you ensure that the version of the module in your project was updated? *EDIT*: I added some debugging by looping through the available certs:
The second one (index = 1) is selected and the connection gets approved properly.2017-10-21 13:42:54.092 test_https[4421:133780] 0: <cert(0x7fe9e9d25310) s: www.wellsfargo.com i: Symantec Class 3 Secure Server CA - G4> 2017-10-21 13:42:59.994 test_https[4421:133780] 1: <cert(0x7fe9ea03f800) s: Symantec Class 3 Secure Server CA - G4 i: VeriSign Class 3 Public Primary Certification Authority - G5> 2017-10-21 13:43:04.133 test_https[4421:133780] 2: <cert(0x7fe9ea063a00) s: VeriSign Class 3 Public Primary Certification Authority - G5 i: VeriSign Class 3 Public Primary Certification Authority - G5>Cleaning up older fixed issues. If this issue should not have been closed as fixed, please reopen.