<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/">
	<channel>
		<title>Securing Mobile Banking on Android with SSL Certificate Pinning | Infinum</title>
		<atom:link href="https://infinum.com/blog/securing-mobile-banking-on-android-with-ssl-certificate-pinning/feed/" rel="self" type="application/rss+xml" />
		<link>https://infinum.com/blog/securing-mobile-banking-on-android-with-ssl-certificate-pinning/</link>
		<description>Building digital products</description>
		<lastBuildDate>Fri, 17 Apr 2026 13:59:15 +0000</lastBuildDate>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>

					<item>
				<image>
					<url>8092https://infinum.com/uploads/2014/03/securing-mobile-banking-on-android-with-ssl-certificate-pinning-0.webp</url>
				</image>
				<title>Securing Mobile Banking on Android with SSL Certificate Pinning</title>
				<link>https://infinum.com/blog/securing-mobile-banking-on-android-with-ssl-certificate-pinning/</link>
				<pubDate>Wed, 12 Mar 2014 09:08:00 +0000</pubDate>
				<dc:creator>Ivan Kust</dc:creator>
				<guid isPermaLink="false">https://infinum.com/the-capsized-eight/securing-mobile-banking-on-android-with-ssl-certificate-pinning/</guid>
				<description>
					<![CDATA[<p>If you want to exchange some sensitive data between your application and a server. SSL should do the trick, right? Right, but that&#8217;s only half of the story.</p>
<p>The post <a href="https://infinum.com/blog/securing-mobile-banking-on-android-with-ssl-certificate-pinning/">Securing Mobile Banking on Android with SSL Certificate Pinning</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-157"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-92">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-95"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-93">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-94'
	>
	Let’s say you want to exchange some sensitive data between your application and a server. SSL should do the trick, right? Right, but that’s only half of the story.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-98"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-96">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-97'
	>
	In many cases, you’ll have to send sensitive data between your application and server. Take mobile banking applications for example. The last thing you want is a malicious hacker to steal someone’s bank account info – or worse, their money.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-101"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-99">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-100'
	>
	Security is crucial for a mobile banking solution, so you’ll be using <a href="http://en.wikipedia.org/wiki/Secure_Sockets_Layer">SSL</a> to keep that data safe and secret. But there’s a catch.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-104"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-102">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-103'
	>
	What is certificate pinning?</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-107"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-105"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-106">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2014/03/securing-mobile-banking-on-android-with-ssl-certificate-pinning-1.webp"
					class="image__img block-media__image-img"
					alt=""
										height="544"
															width="959"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-110"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-108">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-109'
	>
	By default, when making an SSL connection, the client checks that the server’s certificate:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-113"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-111">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-112'
	>
	<li>has a verifiable chain of trust back to a <strong>trusted (root) certificate</strong></li><li>matches the <strong>requested hostname</strong></li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-116"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-114">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-115'
	>
	What it doesn’t do is check if the certificate in question is a <strong>specific certificate</strong>, namely the one you know your server is using.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-119"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-117">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-118'
	>
	Relying on matching certificates between the device’s trust store and the remote server opens up a <strong>security hole</strong>. The device’s trust store can easily be compromised – the user can install unsafe certificates, thus allowing potential <a href="https://www.owasp.org/index.php/Man-in-the-middle_attack">man-in-the-middle attacks</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-122"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-120">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-121'
	>
	<strong>Certificate pinning</strong> is the solution to this problem. It means hard-coding the certificate known to be used by the server in the mobile application. The app can then ignore the device’s trust store and rely on its own, and allow only SSL connections to hosts signed with certificates stored inside the application.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-125"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-123">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-124'
	>
	This also gives a possibility of trusting a host with a self-signed certificate without the need to install additional certificates on the device.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-128"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-126">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-127'
	>
	benefits</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-131"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-129">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-130'
	>
	<li><strong>Increased security</strong> – with pinned SSL certificates, the app is independent of the device’s trust store. Compromising the hard coded trust store in the app is not so easy – the app would need to be decompiled, changed and then recompiled again – and it can’t be signed using the same Android keystore that the original developer of the app used.</li><li><strong>Reduced costs</strong> – SSL certificate pinning gives you the possibility to use a self-signed certificate that can be trusted. For example, you’re developing an app that uses your own API server. You can reduce the costs by using a self-signed certificate on your server (and pinning that certificate in your app) instead of paying for a certificate. Although a bit convoluted, this way, you’ve actually improved security and saved yourself some money.</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-134"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-132">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-133'
	>
	drawbacks</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-137"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-135">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-136'
	>
	<li><strong>Less flexibility</strong> – when you do SSL certificate pinning, changing the SSL certificate is not that easy. For every SSL certificate change, you have to make an update to the app, push it to Google Play and hope the users will install it.</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-140"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-138">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-139'
	>
	How does this work on Android?</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-143"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-141">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-142'
	>
	Surprisingly, pinning SSL certificates on Android isn’t very straightforward. We needed a solution that would work on Android 2.2 and up, so I had to do some hard digging before finding one that worked.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-146"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-144">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-145'
	>
	There are three important steps in the process:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-149"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-147">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-148'
	>
	<li>obtain a certificate for the desired host (preferably the whole certificate chain)</li><li>make sure the certificate is in <a href="http://www.bouncycastle.org">.bks format</a> – this step is crucial in order for pinning to work properly across all devices</li><li>use <a href="http://developer.android.com/reference/org/apache/http/impl/client/DefaultHttpClient.html">Apache HTTP client</a> shipped with Android – initialize it to use the obtained .bks keystore for SSL connections</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-152"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-150">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-151'
	>
	A fully functioning example that demonstrates the solution that we’re using <a href="https://github.com/ikust/hello-pinnedcerts">can be found here</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-155"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-153">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-154'
	>
	SSL pinning isn’t something you want to do in all your applications, but for high-risk apps that require increased levels of security, it might just make sense.</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/securing-mobile-banking-on-android-with-ssl-certificate-pinning/">Securing Mobile Banking on Android with SSL Certificate Pinning</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
		
	</channel>
</rss>