<?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>SSL Pinning in iOS Swift Edition | Infinum</title>
		<atom:link href="https://infinum.com/blog/ssl-pinning-revisited/feed/" rel="self" type="application/rss+xml" />
		<link>https://infinum.com/blog/ssl-pinning-revisited/</link>
		<description>Building digital products</description>
		<lastBuildDate>Fri, 03 Apr 2026 12:58:20 +0000</lastBuildDate>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>

					<item>
				<image>
					<url>8050https://infinum.com/uploads/2017/11/ssl-pinning-revisited-0.webp</url>
				</image>
				<title>SSL Pinning in iOS  Swift Edition</title>
				<link>https://infinum.com/blog/ssl-pinning-revisited/</link>
				<pubDate>Thu, 26 Oct 2017 17:23:00 +0000</pubDate>
				<dc:creator>Adis Mustedanagic</dc:creator>
				<guid isPermaLink="false">https://infinum.com/the-capsized-eight/ssl-pinning-revisited/</guid>
				<description>
					<![CDATA[<p>A follow up on our article on the benefits of SSL pinning.</p>
<p>The post <a href="https://infinum.com/blog/ssl-pinning-revisited/">SSL Pinning in iOS  Swift Edition</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-209"
	 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'
	>
	<strong>[Update]</strong> As of January 2021, the code samples and the article has been updated to reflect recent changes in Alamofire 5 and Firefox. Cheers!</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'
	>
	Some time ago, we published <a href="https://infinum.com/blog/how-to-make-your-ios-apps-more-secure-with-ssl-pinning/">an article regarding the benefits of SSL pinning</a>. If you haven’t done so already, read it – it covers a lot of basics taken for granted in this follow-up article.</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'
	>
	Since almost the entire iOS development community has moved from Objective-C to Swift, preferences in libraries and networking have also shifted.</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-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-102"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-103">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2017/11/ssl-pinning-revisited-1.webp"
					class="image__img block-media__image-img"
					alt=""
										height="423"
															width="705"
										loading="lazy"
					 />
					</picture>

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

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-107"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-105">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-106'
	>
	Swift-wise, our networking library of choice is usually <a href="https://github.com/Alamofire/Alamofire">Alamofire</a>. As stated in the previous article, Alamofire handles pinning differently than AFNetworking and while neither implementation is wrong, sometimes you might have a preference for a certain method.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-110"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-108">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-109'
	>
	The two pinning methods</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-113"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-111">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-112'
	>
	While AFNetworking talks only to the servers whose certificates you have pinned, <em>Alamofire does it differently</em> – you pin a certificate per domain, so the certificate check will occur only if you talk to the list of predetermined domains. For all other domains, no check will be enforced. AFNetworking, on the other hand, will block all requests that don’t pass checks for the certificates you have pinned in your app.</p></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'
	>
	While Alamofire’s implementation may seem a bit weird at first glance, this kind of pinning offers greater freedom when defining different policies for different domains, e.g., a self-signed certificate for your development environment can easily be set up separately from your production environment without any preprocessor macros or common Objective-C practices.</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'
	>
	However, for some apps, the only endpoints you want to communicate with are those you trust and have certificates for (e.g. mobile banking applications). In that case, you will have to do some handiwork to bring back the AFNetworking-like behavior.</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-heading" data-id="es-120">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-121'
	>
	SSL pinning cookbook</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-125"
	 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-123"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-124">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2017/11/ssl-pinning-revisited-2.webp"
					class="image__img block-media__image-img"
					alt=""
										height="600"
															width="1000"
										loading="lazy"
					 />
					</picture>

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

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-128"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-126">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-127'
	>
	Alright, so your app is almost ready, and you want to add that one more layer of security with SSL pinning.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-131"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-129">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-130'
	>
	Getting the certificate</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-134"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-132">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-133'
	>
	If your API is live, you can easily swipe the certificate yourself using <code>openssl</code>:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-136"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-shellscript github-light" data-language="shellscript" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">openssl</span><span class="token"> </span><span class="token" style="color: #032f62;">s_client</span><span class="token"> </span><span class="token" style="color: #005cc5;">-</span><span class="token" style="color: #005cc5;">showcerts</span><span class="token"> </span><span class="token" style="color: #005cc5;">-</span><span class="token" style="color: #005cc5;">connect</span><span class="token"> </span><span class="token" style="color: #032f62;">www.infinum.co:443</span><span class="token"> </span><span class="token" style="color: #d73a49;">&lt;</span><span class="token"> </span><span class="token" style="color: #032f62;">/dev/null</span><span class="token"> </span><span class="token" style="color: #d73a49;">|</span><span class="token"> </span><span class="token" style="color: #6f42c1;">openssl</span><span class="token"> </span><span class="token" style="color: #032f62;">x509</span><span class="token"> </span><span class="token" style="color: #005cc5;">-</span><span class="token" style="color: #005cc5;">outform</span><span class="token"> </span><span class="token" style="color: #032f62;">DER</span><span class="token"> </span><span class="token" style="color: #d73a49;">&gt;</span><span class="token"> </span><span class="token" style="color: #032f62;">infinumco.cer</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-139"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-137">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-138'
	>
	Pinning with Swift and Alamofire</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-142"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-140">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-141'
	>
	An example of security policy for Alamofire and pinning might look something like this:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-144"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-swift github-light" data-language="swift" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">     </span><span class="token">let evaluators:</span><span class="token"> </span><span class="token">[</span><span class="token" style="color: #005cc5;">String</span><span class="token">:</span><span class="token"> ServerTrustEvaluating</span><span class="token">]</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> [
</span></span><span class="line"><span class="token">         </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">infinum.com</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #d73a49;">:</span><span class="token"> </span><span class="token">PublicKeysTrustEvaluator(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">         ]
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">     </span><span class="token" style="color: #d73a49;">let</span><span class="token"> manager </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">ServerTrustManager(</span><span class="token">evaluators:</span><span class="token"> evaluators</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-147"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-145">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-146'
	>
	In this example, we’re pinning public keys from certificates. You can either pin the certificates themselves (in which case you do a byte per byte data comparison), or just compare the public keys in the certificates. Public keys have the advantage of being a bit more robust since the server certificate can be renewed retaining its public key, so no app update is needed on certificate change. In practice, this isn’t a typical case, but more on this issue later.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-150"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-148">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-149'
	>
	To replicate the AFNetworking behavior we had before, you’ll have to subclass the <code>Server Trust Policy Manager</code> and override the default implementation. An example that simply stops the app from communicating if there’s no pinned certificate will look similar to this:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-152"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-swift github-light" data-language="swift" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">import</span><span class="token"> </span><span class="token" style="color: #6f42c1;">Foundation</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">import</span><span class="token"> </span><span class="token" style="color: #6f42c1;">Alamofire</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">final</span><span class="token"> </span><span class="token">class DenyEvaluator</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #6f42c1;">ServerTrustEvaluating </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">func evaluate</span><span class="token">(</span><span class="token">_ trust</span><span class="token">: </span><span class="token">SecTrust</span><span class="token">, </span><span class="token">forHost host</span><span class="token">: </span><span class="token" style="color: #005cc5;">String</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #d73a49;">throws</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #d73a49;">throw</span><span class="token"> AFError.</span><span class="token">serverTrustEvaluationFailed(</span><span class="token">reason:</span><span class="token"> .</span><span class="token">noPublicKeysFound</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">final</span><span class="token"> </span><span class="token">class CustomServerTrustPolicyManager</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #6f42c1;">ServerTrustManager </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">init</span><span class="token">(</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #005cc5;">super</span><span class="token">.</span><span class="token" style="color: #d73a49;">init</span><span class="token">(</span><span class="token">evaluators:</span><span class="token"> [</span><span class="token" style="color: #d73a49;">:</span><span class="token">]</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">override</span><span class="token"> </span><span class="token">func serverTrustEvaluator</span><span class="token">(</span><span class="token">forHost host</span><span class="token">: </span><span class="token" style="color: #005cc5;">String</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #d73a49;">throws</span><span class="token"> </span><span class="token" style="color: #d73a49;">-&gt;</span><span class="token"> </span><span class="token">ServerTrustEvaluating</span><span class="token" style="color: #d73a49;">?</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token">var policy:</span><span class="token"> ServerTrustEvaluating</span><span class="token" style="color: #d73a49;">?</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #6a737d;">///</span><span class="token" style="color: #6a737d;"> Smarter check would be beneficial here, theoretically, MITM attack can have an URL containing this string</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #d73a49;">if</span><span class="token"> host.</span><span class="token" style="color: #005cc5;">contains</span><span class="token">(</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">stackoverflow.com</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">            </span><span class="token" style="color: #6a737d;">///</span><span class="token" style="color: #6a737d;"> You could dig even deeper and write your own evaluator</span><span class="token">
</span></span><span class="line"><span class="token">            policy </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">PublicKeysTrustEvaluator(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token">}</span><span class="token"> </span><span class="token" style="color: #d73a49;">else</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">            </span><span class="token" style="color: #6a737d;">///</span><span class="token" style="color: #6a737d;"> Deny all other connections</span><span class="token">
</span></span><span class="line"><span class="token">            policy </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">DenyEvaluator(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #d73a49;">return</span><span class="token"> policy
</span></span><span class="line"><span class="token">    </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></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'
	>
	Everything is exactly the same as the default pinning implementation, except now this class needs to be used instead.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-158"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-156">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-157'
	>
	If your project uses the default networking, you have the option of not using AFNetworking or Alamofire at all, and just implementing the pinning on NSURLSession level. This is probably the cleaner way to do it than messing around with Alamofire since it allows more flexibility, and will not break in case the Alamofire API changes in the future.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-161"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-159">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-160'
	>
	You can either pin a <strong>certificate</strong>:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-163"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-swift github-light" data-language="swift" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;"> Compare the server certificate with our own stored</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">if</span><span class="token"> </span><span class="token" style="color: #d73a49;">let</span><span class="token"> serverCertificate </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">SecTrustGetCertificateAtIndex(</span><span class="token">trust</span><span class="token">, </span><span class="token" style="color: #005cc5;">0</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">let</span><span class="token"> serverCertificateData </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">SecCertificateCopyData(</span><span class="token">serverCertificate</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #d73a49;">as</span><span class="token"> Data
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">if</span><span class="token"> </span><span class="token">pinnedCertificates(</span><span class="token">)</span><span class="token">.</span><span class="token" style="color: #005cc5;">contains</span><span class="token">(</span><span class="token">serverCertificateData</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token">completionHandler(</span><span class="token">.</span><span class="token">useCredential</span><span class="token">, </span><span class="token">URLCredential(</span><span class="token">trust:</span><span class="token"> trust</span><span class="token">)</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #d73a49;">return</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-166"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-164">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-165'
	>
	Or a <strong>public key</strong>:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-168"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-swift github-light" data-language="swift" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;"> Or, compare the public keys</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">if</span><span class="token"> </span><span class="token" style="color: #d73a49;">let</span><span class="token"> serverCertificate </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">SecTrustGetCertificateAtIndex(</span><span class="token">trust</span><span class="token">, </span><span class="token" style="color: #005cc5;">0</span><span class="token">)</span><span class="token">, </span><span class="token" style="color: #d73a49;">let</span><span class="token"> serverCertificateKey </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">publicKey(</span><span class="token">for:</span><span class="token"> serverCertificate</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">if</span><span class="token"> </span><span class="token">pinnedKeys(</span><span class="token">)</span><span class="token">.</span><span class="token" style="color: #005cc5;">contains</span><span class="token">(</span><span class="token">serverCertificateKey</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token">completionHandler(</span><span class="token">.</span><span class="token">useCredential</span><span class="token">, </span><span class="token">URLCredential(</span><span class="token">trust:</span><span class="token"> trust</span><span class="token">)</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #d73a49;">return</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-171"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-169">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-170'
	>
	Find the full code example in the repo here:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-174"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<a	class="btn btn--color-infinum btn--size-medium btn--width-default btn__as-link btn__no-icon block-button__btn js-block-button-btn"
	data-id="es-172"
	 target='_blank' rel='noopener noreferrer' href='https://github.com/Adis/swift-ssl-pin-examples'>
		<div class="btn__inner">
					<div	class='typography typography--size-none js-typography btn__label'
	data-id='es-173'
	>
	https://github.com/Adis/swift-ssl-pin-examples</div>		
			</div>
	</a>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-177"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-175">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-176'
	>
	Common pitfalls</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-180"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-178">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-179'
	>
	Testing your pin</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-183"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-181">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-182'
	>
	Unlike most types of software testing where the important part is to check whether something works, for pinning, you want to test that something fails as well. Specifically, you need to test that your app cancels potentially compromised connections. While setting up a man-in-the-middle attack might be a bit of an overkill, there’s a simpler way to test, depending on which of the two versions of the pin are implemented.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-186"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-184">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-185'
	>
	If your app allows communication with only one endpoint, then testing is as simple as making a GET request to an arbitrary site (just make sure it also has a certificate). <strong>The app should cancel the connection</strong> and the request should fail. Additionally, just make sure your API works as expected and you’re set to go.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-189"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-187">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-188'
	>
	Testing the case above might be a bit more tricky if your app is pinning a certificate per domain since making an arbitrary request to another domain will succeed as expected. In this case, you might want to pin a certificate from a different domain and attempt to communicate with your API – <strong>which, again, should fail</strong>. This, in combination with a successful test with the proper certificate and successful communication with your API will usually be enough.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-192"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-190">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-191'
	>
	Handling the certificate change/update</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-195"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-193">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-194'
	>
	Although renewing a certificate for a domain can retain the private/public key pair (meaning your app will continue working), this is usually not the case. Fortunately, if you plan your update cycle right, you can avoid any downtime for the end users.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-198"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-196">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-197'
	>
	<strong>Before</strong> the new certificate becomes active on the website, you should pin it in your application, along with the currently active certificate, and release an update. Pinning more than one certificate is possible and works with the code samples above. In this scenario, be mindful that you convert the certificate to a proper binary DER format.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-201"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-199">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-200'
	>
	If possible, perform a quick test of the app with the new certificate. For this test, the developers handling the certificate on the API should temporarily use the new certificate and test your app with both certificates pinned. Everything should work, and if it does, they should revert to the old certificate until the app update is ready.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-204"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-202">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-203'
	>
	Parting words</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-207"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-205">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-206'
	>
	This is where I nail the last argument and entirely convince you to use SSL pinning wherever possible, but that’s almost certainly unnecessary. Some apps won’t benefit from additional security measures, but for apps involving sensitive data, an additional layer of protection is never a bad idea. In that case, I hope the article was of some use.</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/ssl-pinning-revisited/">SSL Pinning in iOS  Swift Edition</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
		
	</channel>
</rss>