{"id":612,"date":"2015-07-29T12:06:55","date_gmt":"2015-07-29T10:06:55","guid":{"rendered":"http:\/\/blog.ansuz.nl\/?p=612"},"modified":"2015-07-29T12:06:55","modified_gmt":"2015-07-29T10:06:55","slug":"using-ssl-right-on-android","status":"publish","type":"post","link":"http:\/\/blog.ansuz.nl\/index.php\/2015\/07\/29\/using-ssl-right-on-android\/","title":{"rendered":"Using SSL right on Android"},"content":{"rendered":"<p><strong>General information<\/strong><br \/>\nThere is no out of the box solution from Google to use stronger encryption for the communication between your Android client and a server. <\/p>\n<p>Google provides some information on how to use SSL on the Android developer website titled &#8220;<a href=\"https:\/\/developer.android.com\/training\/articles\/security-ssl.html\" target=\"_blank\">Security with HTTPS and SSL<\/a>&#8220;. This site contains two warnings you should not forget.<\/p>\n<ol>\n<li>Do not use a <a href=\"https:\/\/developer.android.com\/reference\/javax\/net\/ssl\/TrustManager.html\" target=\"_blank\">TrustManager<\/a> that does nothing.<\/li>\n<li>Replacing the <a href=\"https:\/\/developer.android.com\/reference\/javax\/net\/ssl\/HostnameVerifier.html\" target=\"_blank\">HostnameVerifier<\/a> can be very dangerous.<\/li>\n<\/ol>\n<p>A reason to use a TrustManager that does nothing could be for local or Alpha testing where you don&#8217;t have a valid SSL certificate on the server. Another could be to give QA the option to debug network traffic. If for some reason you do use a TrustManager that does nothing, make sure this implementation can never make it to a production version of the application. One way to do that is only include the empty TrustManager in one of the (testing) application flavors.<\/p>\n<p>If you do want to use a custom HostnameVerifier, use composition to reuse the system&#8217;s default HostnameVerifier. This way you can add your own verification and still benefit from the default verification. You should apply the same when building your own TrustManager, that way your validation is never worse than the default system validation.<\/p>\n<p><strong>Pinning certificates<\/strong><br \/>\nOne way to make the encryption stronger is by using pinned certificates. This will help your application protect itself from fraudulently issued certificates. I will explore two ways of pinning a certificate. One is including the actual certificate, the other is to use SPKI or <a href=\"https:\/\/tools.ietf.org\/html\/draft-ietf-websec-key-pinning-21\" target=\"_blank\">Subject Public Key Info<\/a>.<\/p>\n<p><strong>Getting the server certificate<\/strong><br \/>\nBefore getting started with either method for pinning a certificate, you need to get hold of the server certificate. The easiest way to optain that would be to ask your system administrator. If that is not possible, you could use <a href=\"https:\/\/www.openssl.org\/\" target=\"_blank\">OpenSSL<\/a> or <a href=\"https:\/\/www.mozilla.org\/en-US\/firefox\/\" target=\"_blank\">FireFox<\/a> to just save it from the browser. For more details, see &#8220;<a href=\"http:\/\/superuser.com\/questions\/97201\/how-to-save-a-remote-server-ssl-certificate-locally-as-a-file\" target=\"_blank\">How to save a remote server SSL certificate locally as a file<\/a>&#8221; on SuperUser.com.<\/p>\n<p><strong>Including the certificate<\/strong><br \/>\nStart by including the certificate file (as raw resource) in your APK.<br \/>\nAfter this, implement your own TrustManager that uses the following pseudo-code to analyse the received certificate.<\/p>\n<p>Get the key from the bundled certificate.<\/p>\n<div id=\"ig-sh-1\" class=\"syntax_hilite\">\n\n\t\t<div class=\"toolbar\">\n\n\t\t<div class=\"view-different-container\">\n\t\t\t\t\t\t<a href=\"#\" class=\"view-different\">&lt; View <span>plain text<\/span> &gt;<\/a>\n\t\t\t\t\t<\/div>\n\n\t\t<div class=\"language-name\">java<\/div>\n\n\t\t\n\t\t<br clear=\"both\">\n\n\t<\/div>\n\t\n\t<div class=\"code\">\n\t\t<ol class=\"java\" style=\"font-family:monospace\"><li style=\"font-weight: normal;vertical-align:top\"><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\"><span style=\"color: #003399\">FileInputStream<\/span> fis <span style=\"color: #339933\">=<\/span> <span style=\"color: #000000;font-weight: bold\">new<\/span> <span style=\"color: #003399\">FileInputStream<\/span><span style=\"color: #009900\">&#040;<\/span><span style=\"color: #0000ff\">&quot;path_to_pem&quot;<\/span><span style=\"color: #009900\">&#041;<\/span><span style=\"color: #339933\">;<\/span><\/div><\/li>\n<li style=\"font-weight: normal;vertical-align:top\"><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\"><span style=\"color: #003399\">CertificateFactory<\/span> cf <span style=\"color: #339933\">=<\/span> <span style=\"color: #003399\">CertificateFactory<\/span>.<span style=\"color: #006633\">getInstance<\/span><span style=\"color: #009900\">&#040;<\/span><span style=\"color: #0000ff\">&quot;X.509&quot;<\/span><span style=\"color: #009900\">&#041;<\/span><span style=\"color: #339933\">;<\/span><\/div><\/li>\n<li style=\"font-weight: normal;vertical-align:top\"><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\">java.<span style=\"color: #006633\">security<\/span>.<span style=\"color: #006633\">cert<\/span>.<span style=\"color: #003399\">Certificate<\/span> c <span style=\"color: #339933\">=<\/span> cf.<span style=\"color: #006633\">generateCertificate<\/span><span style=\"color: #009900\">&#040;<\/span>fis<span style=\"color: #009900\">&#041;<\/span><span style=\"color: #339933\">;<\/span><\/div><\/li>\n<li style=\"font-weight: normal;vertical-align:top\"><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\"><span style=\"color: #003399\">System<\/span>.<span style=\"color: #006633\">out<\/span>.<span style=\"color: #006633\">println<\/span><span style=\"color: #009900\">&#040;<\/span>c.<span style=\"color: #006633\">toString<\/span><span style=\"color: #009900\">&#040;<\/span><span style=\"color: #009900\">&#041;<\/span><span style=\"color: #009900\">&#041;<\/span><span style=\"color: #339933\">;<\/span><\/div><\/li>\n<li style=\"font-weight: normal;vertical-align:top\"><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\">&nbsp;<\/div><\/li>\n<li style=\"font-weight: normal;vertical-align:top\"><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\"><span style=\"color: #666666;font-style: italic\">\/\/ will get you the public key object you can compare against.<\/span><\/div><\/li>\n<li style=\"font-weight: normal;vertical-align:top\"><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\"><span style=\"color: #003399\">RSAPublicKey<\/span> pk <span style=\"color: #339933\">=<\/span> <span style=\"color: #009900\">&#040;<\/span><span style=\"color: #003399\">RSAPublicKey<\/span><span style=\"color: #009900\">&#041;<\/span> c.<span style=\"color: #006633\">getPublicKey<\/span><span style=\"color: #009900\">&#040;<\/span><span style=\"color: #009900\">&#041;<\/span><span style=\"color: #339933\">;<\/span><\/div><\/li>\n<li style=\"font-weight: normal;vertical-align:top\"><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\">&nbsp;<\/div><\/li>\n<li style=\"font-weight: normal;vertical-align:top\"><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\"><span style=\"color: #003399\">System<\/span>.<span style=\"color: #006633\">out<\/span>.<span style=\"color: #006633\">println<\/span><span style=\"color: #009900\">&#040;<\/span>pk.<span style=\"color: #006633\">toString<\/span><span style=\"color: #009900\">&#040;<\/span><span style=\"color: #009900\">&#041;<\/span><span style=\"color: #009900\">&#041;<\/span><span style=\"color: #339933\">;<\/span><\/div><\/li>\n<li style=\"font-weight: normal;vertical-align:top\"><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\"><span style=\"color: #003399\">String<\/span> s <span style=\"color: #339933\">=<\/span> <span style=\"color: #000000;font-weight: bold\">new<\/span> <span style=\"color: #003399\">BigInteger<\/span><span style=\"color: #009900\">&#040;<\/span><span style=\"color: #cc66cc\">1<\/span>, pk.<span style=\"color: #006633\">getEncoded<\/span><span style=\"color: #009900\">&#040;<\/span><span style=\"color: #009900\">&#041;<\/span><span style=\"color: #009900\">&#041;<\/span>.<span style=\"color: #006633\">toString<\/span><span style=\"color: #009900\">&#040;<\/span><span style=\"color: #cc66cc\">16<\/span><span style=\"color: #009900\">&#041;<\/span><span style=\"color: #339933\">;<\/span><\/div><\/li>\n<li style=\"font-weight: normal;vertical-align:top\"><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\"><span style=\"color: #003399\">System<\/span>.<span style=\"color: #006633\">out<\/span>.<span style=\"color: #006633\">println<\/span><span style=\"color: #009900\">&#040;<\/span>s<span style=\"color: #009900\">&#041;<\/span><span style=\"color: #339933\">;<\/span><\/div><\/li>\n<\/ol>\t<\/div>\n\n<\/div>\n\n<p>Get the server key.<\/p>\n<div id=\"ig-sh-2\" class=\"syntax_hilite\">\n\n\t\t<div class=\"toolbar\">\n\n\t\t<div class=\"view-different-container\">\n\t\t\t\t\t\t<a href=\"#\" class=\"view-different\">&lt; View <span>plain text<\/span> &gt;<\/a>\n\t\t\t\t\t<\/div>\n\n\t\t<div class=\"language-name\">java<\/div>\n\n\t\t\n\t\t<br clear=\"both\">\n\n\t<\/div>\n\t\n\t<div class=\"code\">\n\t\t<ol class=\"java\" style=\"font-family:monospace\"><li style=\"font-weight: normal;vertical-align:top\"><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\"><span style=\"color: #666666;font-style: italic\">\/\/ that gets the public key provided by the server out of the chain.<\/span><\/div><\/li>\n<li style=\"font-weight: normal;vertical-align:top\"><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\"><span style=\"color: #003399\">RSAPublicKey<\/span> pubkey <span style=\"color: #339933\">=<\/span> <span style=\"color: #009900\">&#040;<\/span><span style=\"color: #003399\">RSAPublicKey<\/span><span style=\"color: #009900\">&#041;<\/span> chain<span style=\"color: #009900\">&#091;<\/span><span style=\"color: #cc66cc\">0<\/span><span style=\"color: #009900\">&#093;<\/span>.<span style=\"color: #006633\">getPublicKey<\/span><span style=\"color: #009900\">&#040;<\/span><span style=\"color: #009900\">&#041;<\/span><span style=\"color: #339933\">;<\/span><\/div><\/li>\n<\/ol>\t<\/div>\n\n<\/div>\n\n<p>Compare the two keys.<\/p>\n<div id=\"ig-sh-3\" class=\"syntax_hilite\">\n\n\t\t<div class=\"toolbar\">\n\n\t\t<div class=\"view-different-container\">\n\t\t\t\t\t\t<a href=\"#\" class=\"view-different\">&lt; View <span>plain text<\/span> &gt;<\/a>\n\t\t\t\t\t<\/div>\n\n\t\t<div class=\"language-name\">java<\/div>\n\n\t\t\n\t\t<br clear=\"both\">\n\n\t<\/div>\n\t\n\t<div class=\"code\">\n\t\t<ol class=\"java\" style=\"font-family:monospace\"><li style=\"font-weight: normal;vertical-align:top\"><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\"><span style=\"color: #666666;font-style: italic\">\/\/ Where pk is the one loaded from your app file space.<\/span><\/div><\/li>\n<li style=\"font-weight: normal;vertical-align:top\"><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\">pubkey.<span style=\"color: #006633\">equals<\/span><span style=\"color: #009900\">&#040;<\/span>pk<span style=\"color: #009900\">&#041;<\/span><span style=\"color: #339933\">;<\/span><\/div><\/li>\n<\/ol>\t<\/div>\n\n<\/div>\n\n<p><strong>SPKI<\/strong><br \/>\nAn alternative approach to bundling the certificate with your application is to use the Subject Public Key Info method. This will just store the certificate&#8217;s fingerprint instead of a whole file.<\/p>\n<p>To generate the fingerprint for your certificate, follow the instructions in &#8220;<a href=\"https:\/\/tools.ietf.org\/html\/draft-ietf-websec-key-pinning-21#appendix-A\" target=\"_blank\">Appendix A<\/a>&#8221; of the &#8220;<a href=\"https:\/\/tools.ietf.org\/html\/draft-ietf-websec-key-pinning-21\" target=\"_blank\">Public Key Pinning Extension for HTTP<\/a>&#8221; document, example:<\/p>\n<div id=\"ig-sh-4\" class=\"syntax_hilite\">\n\n\t\t<div class=\"toolbar\">\n\n\t\t<div class=\"view-different-container\">\n\t\t\t\t\t\t<a href=\"#\" class=\"view-different\">&lt; View <span>plain text<\/span> &gt;<\/a>\n\t\t\t\t\t<\/div>\n\n\t\t<div class=\"language-name\">bash<\/div>\n\n\t\t\n\t\t<br clear=\"both\">\n\n\t<\/div>\n\t\n\t<div class=\"code\">\n\t\t<ol class=\"bash\" style=\"font-family:monospace\"><li style=\"font-weight: normal;vertical-align:top\"><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\">openssl x509 <span style=\"color: #660033\">-noout<\/span> <span style=\"color: #660033\">-in<\/span> certificate.pem <span style=\"color: #660033\">-pubkey<\/span> <span style=\"color: #000000;font-weight: bold\">|<\/span> \\<\/div><\/li>\n<li style=\"font-weight: normal;vertical-align:top\"><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\">&nbsp; &nbsp; openssl asn1parse <span style=\"color: #660033\">-noout<\/span> <span style=\"color: #660033\">-inform<\/span> pem <span style=\"color: #660033\">-out<\/span> public.key<\/div><\/li>\n<li style=\"font-weight: normal;vertical-align:top\"><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\">openssl dgst <span style=\"color: #660033\">-sha256<\/span> <span style=\"color: #660033\">-binary<\/span> public.key <span style=\"color: #000000;font-weight: bold\">|<\/span> openssl enc <span style=\"color: #660033\">-base64<\/span><\/div><\/li>\n<\/ol>\t<\/div>\n\n<\/div>\n\n<p>You can calculate the same fingerprint in Java using the snippet below:<\/p>\n<div id=\"ig-sh-5\" class=\"syntax_hilite\">\n\n\t\t<div class=\"toolbar\">\n\n\t\t<div class=\"view-different-container\">\n\t\t\t\t\t\t<a href=\"#\" class=\"view-different\">&lt; View <span>plain text<\/span> &gt;<\/a>\n\t\t\t\t\t<\/div>\n\n\t\t<div class=\"language-name\">java<\/div>\n\n\t\t\n\t\t<br clear=\"both\">\n\n\t<\/div>\n\t\n\t<div class=\"code\">\n\t\t<ol class=\"java\" style=\"font-family:monospace\"><li style=\"font-weight: normal;vertical-align:top\"><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\"><span style=\"color: #666666;font-style: italic\">\/\/ Assume the 'certificate' is a X509Certificate.<\/span><\/div><\/li>\n<li style=\"font-weight: normal;vertical-align:top\"><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\"><span style=\"color: #003399\">MessageDigest<\/span> digest <span style=\"color: #339933\">=<\/span> <span style=\"color: #003399\">MessageDigest<\/span>.<span style=\"color: #006633\">getInstance<\/span><span style=\"color: #009900\">&#040;<\/span><span style=\"color: #0000ff\">&quot;SHA-256&quot;<\/span><span style=\"color: #009900\">&#041;<\/span><span style=\"color: #339933\">;<\/span><\/div><\/li>\n<li style=\"font-weight: normal;vertical-align:top\"><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\"><span style=\"color: #000066;font-weight: bold\">byte<\/span><span style=\"color: #009900\">&#091;<\/span><span style=\"color: #009900\">&#093;<\/span> encodedKey <span style=\"color: #339933\">=<\/span> certificate.<span style=\"color: #006633\">getPublicKey<\/span><span style=\"color: #009900\">&#040;<\/span><span style=\"color: #009900\">&#041;<\/span>.<span style=\"color: #006633\">getEncoded<\/span><span style=\"color: #009900\">&#040;<\/span><span style=\"color: #009900\">&#041;<\/span><span style=\"color: #339933\">;<\/span><\/div><\/li>\n<li style=\"font-weight: normal;vertical-align:top\"><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\"><span style=\"color: #000066;font-weight: bold\">byte<\/span><span style=\"color: #009900\">&#091;<\/span><span style=\"color: #009900\">&#093;<\/span> hash <span style=\"color: #339933\">=<\/span> digest.<span style=\"color: #006633\">digest<\/span><span style=\"color: #009900\">&#040;<\/span>encodedKey<span style=\"color: #009900\">&#041;<\/span><span style=\"color: #339933\">;<\/span><\/div><\/li>\n<li style=\"font-weight: normal;vertical-align:top\"><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\"><span style=\"color: #003399\">String<\/span> fingerprint <span style=\"color: #339933\">=<\/span> Base64.<span style=\"color: #006633\">encodeToString<\/span><span style=\"color: #009900\">&#040;<\/span>hash, Base64.<span style=\"color: #006633\">NO_WRAP<\/span><span style=\"color: #009900\">&#041;<\/span><span style=\"color: #339933\">;<\/span><\/div><\/li>\n<\/ol>\t<\/div>\n\n<\/div>\n\n<p><strong>Notes<\/strong><br \/>\nSSL certificates can be invalidated for various reasons (they expire, get compromised, etc). Because of this you should consider showing a message to the user when pinning a certificate fails.<\/p>\n<p>To avoid your app breaking when a certificate gets invalidated, you can keep a list of valid public keys. Start with the first in the list, if that doesn&#8217;t work fall back to the next public key in the list.<\/p>\n<p>Update or change a certificate before the previous one expires. Unless the certificate is compromised, the public key will most likely stay the same. (If you use the same private key\/CSR.)<\/p>\n<!-- AddThis Advanced Settings generic via filter on the_content --><!-- AddThis Share Buttons generic via filter on the_content -->","protected":false},"excerpt":{"rendered":"<p>General information There is no out of the box solution from Google to use stronger encryption for the communication between your Android client and a server. Google provides some information on how to use SSL on the Android developer website &hellip; <a href=\"http:\/\/blog.ansuz.nl\/index.php\/2015\/07\/29\/using-ssl-right-on-android\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><!-- AddThis Advanced Settings generic via filter on get_the_excerpt --><!-- AddThis Share Buttons generic via filter on get_the_excerpt --><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[112,52],"tags":[125,134],"class_list":["post-612","post","type-post","status-publish","format-standard","hentry","category-android","category-java","tag-android-2","tag-ssl"],"_links":{"self":[{"href":"http:\/\/blog.ansuz.nl\/index.php\/wp-json\/wp\/v2\/posts\/612","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/blog.ansuz.nl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/blog.ansuz.nl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/blog.ansuz.nl\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/blog.ansuz.nl\/index.php\/wp-json\/wp\/v2\/comments?post=612"}],"version-history":[{"count":4,"href":"http:\/\/blog.ansuz.nl\/index.php\/wp-json\/wp\/v2\/posts\/612\/revisions"}],"predecessor-version":[{"id":616,"href":"http:\/\/blog.ansuz.nl\/index.php\/wp-json\/wp\/v2\/posts\/612\/revisions\/616"}],"wp:attachment":[{"href":"http:\/\/blog.ansuz.nl\/index.php\/wp-json\/wp\/v2\/media?parent=612"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.ansuz.nl\/index.php\/wp-json\/wp\/v2\/categories?post=612"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.ansuz.nl\/index.php\/wp-json\/wp\/v2\/tags?post=612"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}