<?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>Author at Infinum</title>
		<atom:link href="https://infinum.com/blog/author/adis/feed/" rel="self" type="application/rss+xml" />
		<link></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>7888https://infinum.com/uploads/2019/02/jailbreaking-bad-why-jailbreak-detection-in-ios-apps-is-pointless-0.webp</url>
				</image>
				<title>Why Jailbreak Detection in iOS Apps Is Pointless</title>
				<link>https://infinum.com/blog/jailbreaking-bad-why-jailbreak-detection-in-ios-apps-is-pointless/</link>
				<pubDate>Wed, 20 Feb 2019 18:00:00 +0000</pubDate>
				<dc:creator>Adis Mustedanagic</dc:creator>
				<guid isPermaLink="false">https://infinum.com/the-capsized-eight/jailbreaking-bad-why-jailbreak-detection-in-ios-apps-is-pointless/</guid>
				<description>
					<![CDATA[<p>When developing apps that have the need for extra security, we often get requests to detect jailbroken phones. Here&#8217;s what we&#8217;ve learned.</p>
<p>The post <a href="https://infinum.com/blog/jailbreaking-bad-why-jailbreak-detection-in-ios-apps-is-pointless/">Why Jailbreak Detection in iOS Apps Is Pointless</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-109"
	 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'
	>
	When <a href="https://infinum.com/work/">developing apps</a> that have the need for extra security, we often get requests to detect jailbroken phones. The reason for detection is to either disable some, or most of the app’s functionalities due to security concerns that come from a jailbroken system.</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 my opinion, these kinds of checks don’t contribute too much to the security side, since they can be targeted and disabled, and might just alienate some of your power users.</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'
	>
	Let’s demonstrate how.</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 isn’t a jailbreak?</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-paragraph" data-id="es-105">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-106'
	>
	In order to understand what a jailbreak is, it’s best to start from what a jailbreak isn’t. By default on iOS, every app runs inside a sandbox of its own. In a nutshell, this means that every app has a very limited access to system resources, and almost no access* to other apps and their data.</p></div>	</div>
</div>
</div>		</div>
	</div>

<div
	class="wrapper"
	data-id="es-112"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-110"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-111">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2021/02/jailbreaking-bad-why-jailbreak-detection-in-ios-apps-is-pointless-1.webp"
					class="image__img block-media__image-img"
					alt=""
										height="241"
															width="641"
										loading="lazy"
					 />
					</picture>

			<figcaption class="image__figcaption block-media__image-figcaption">
			Source: Apple&#8217;s Sandbox Design Guide		</figcaption>
	</figure></div></div>		</div>
	</div>

<div
	class="wrapper"
	data-id="es-189"
	 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-113">
	</div>

<div class="block-blog-content-main">
	
<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'
	>
	Interested in learning more? It’s covered in the <a href="https://developer.apple.com/library/archive/documentation/Security/Conceptual/AppSandboxDesignGuide/AboutAppSandbox/AboutAppSandbox.html">official docs</a>.</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'
	>
	*<em>sometimes there are mechanisms for exchanging data between apps, that are implemented intentionally</em></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'
	>
	What is a jailbreak?</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-paragraph" data-id="es-123">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-124'
	>
	If we rename <strong>sandbox</strong> to <strong>jail</strong>, then the term <strong>jailbreak</strong> makes more sense. By definition, a jailbreak is a privilege escalation for the purpose of removing software restrictions imposed by Apple on iOS, tvOS and watchOS.</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-paragraph" data-id="es-126">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-127'
	>
	In case you didn’t understand a word from above, it means giving apps admin (root) level access, which in term allows installation of other apps, tweaks and themes not on the App Store. Think Cydia – the unofficial official jailbreak software manager.</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">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-130'
	>
	Jailbreak detection</h2></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'
	>
	So, now that we’re familiar with what jailbreaking isn’t and what it is, it’s time to discuss how developers detect a jailbreak. While there’s no official way to detect a jailbreak, and false positives are possible, most methods rely on attempts to access resources that are usually inaccesible on a sandboxed app.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-137"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-135">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-136'
	>
	For example we will try to:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-140"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-138">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-139'
	>
	<li>Try to find the presence of Cydia</li><li>Attempt to find existence of CydiaSubstrate, the framework that allows installation of third-party patches</li><li>Attempt to access directories that should not be available to an app without escalated privileges (such as /bin/bash, /etc/apt)</li><li>Try to find symbolic links to usually unavailable directories</li><li>Or, attempt to write to a directory where that usually wouldn’t be possible</li></ul></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'
	>
	The reason for having so many different methods is due to many different types of jailbreaks and iOS versions. Usually, if any of the methods above succeeds, we assume we’re dealing with a jailbroken phone.</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-heading" data-id="es-144">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-145'
	>
	Breaking the jailbreak</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-149"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-147">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-148'
	>
	In order to demonstrate that detecting a jailbreak doesn’t pose a significant obstacle to a determined hacker, we’ll need a few things:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-152"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-150">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-151'
	>
	<li>An app with jailbreak detection</li><li>A jailbroken device</li><li>A bit of reverse-engineering</li><li>A tweak that disables the jailbreak detection for the same app</li></ul></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'
	>
	Let’s roll up our sleeves.</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-heading" data-id="es-156">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-157'
	>
	1. App with jailbreak detection</h3></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'
	>
	For the sake of this article, I’ve developed a simple app with an elaborate name <strong>Jailbreaking Bad</strong>. Its only purpose is to detect if a device is jailbroken.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-164"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-162">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-163'
	>
	If you’re interested in the source code, you can find that here:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-167"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-165">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-166'
	>
	<a href="https://github.com/Adis/jailbreaking-bad">GitHub – Adis/jailbreaking-bad</a></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-170"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-168">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-169'
	>
	The jailbreak detection is contained inside a class named <code>JBChecker</code>, which is just a wrapper for a more complicated class that does all the heavy lifting, for clarity.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-173"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-171">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-172'
	>
	This class only has one method that checks if the device is jailbroken or not, and returns the result. This is also our entry point when jailbreaking the app a few steps later.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-175"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-objective-c github-light" data-language="objective-c" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">+ (</span><span class="token" style="color: #d73a49;">BOOL</span><span class="token">)isJailbroken
</span></span><span class="line"><span class="token">{
</span></span><span class="line"><span class="token">    // Lib used can be found at https://github.com/thii/DTTJailbreakDetection
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">return</span><span class="token"> </span><span class="token">[</span><span class="token">DTTJailbreakDetection </span><span class="token" style="color: #005cc5;">isJailbroken</span><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></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-178"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-176">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-177'
	>
	After opening the app, you will be presented with a single button; tap it, and the app will tell you if it has detected a jailbreak or not.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-181"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-179">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-180'
	>
	2. A jailbroken device</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-184"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-182">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-183'
	>
	Obviously, a major part of testing this yourself is getting your hands on a jailbroken device. I won’t be covering how to perform a jailbreak in this article as this info is widely available online.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-187"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-185">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-186'
	>
	In case you were wondering how the app looks like on a jailbroken iPhone, here’s a handy gif:</p></div>	</div>
</div>
</div>		</div>
	</div>

<div
	class="wrapper"
	data-id="es-192"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-190"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-191">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2019/01/jailbreaking-bad-why-jailbreak-detection-in-ios-apps-is-pointless-2.gif"
					class="image__img block-media__image-img"
					alt=""
										height="640"
															width="360"
										loading="lazy"
					 />
					</picture>

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

<div
	class="wrapper"
	data-id="es-252"
	 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-193">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-196"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-194">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-195'
	>
	3. A bit of reverse-engineering</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-199"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-197">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-198'
	>
	In order to develop a tweak for an app, you will have to figure out the behaviour you want to change.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-202"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-200">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-201'
	>
	Depending on your level of curiosity, there are plenty of tools out there which allow you to deconstruct and observe the ins and outs of a certain app.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-205"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-203">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-204'
	>
	In order to get familiar with with our own app, first, we’ll want to inspect the IPA (not the beer, the extension) file from the device on a unix machine. The tool of our choice will be <a href="http://stevenygard.com/projects/class-dump/">class-dump</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-208"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-206">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-207'
	>
	IPA file is just an archive, so unarchive it, and take a look at its content. You’ll find icons, folders, .plist files – but we’re looking for a <em>mach-o</em> file that represents our app in a binary format. This file will usually have the app’s name. To dump the headers from the file, use the class dump:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-210"
	 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;">./class-dump</span><span class="token"> </span><span class="token" style="color: #032f62;">Jailbreaking</span><span class="token" style="color: #005cc5;">\ </span><span class="token" style="color: #032f62;">Bad</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-213"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-211">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-212'
	>
	and you will be presented with a lot of output, but the part we’re interested in is this one:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-215"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-objective-c github-light" data-language="objective-c" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">@</span><span class="token" style="color: #d73a49;">interface</span><span class="token"> </span><span class="token" style="color: #6f42c1;">JBChecker</span><span class="token"> </span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #6f42c1;">NSObject</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><span class="line"><span class="token">+ </span><span class="token">(</span><span class="token">_Bool</span><span class="token">)</span><span class="token" style="color: #6f42c1;">isJailbroken</span><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;">@</span><span class="token" style="color: #d73a49;">end</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-218"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-216">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-217'
	>
	What we can see here is the header of our checker class (the wrapper we added as described before), with the method name from which we can easily infer the usage and the return value we want to override. Gotcha.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-221"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-219">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-220'
	>
	4. A tweak that disables jailbreak detection</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-224"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-222">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-223'
	>
	In a jailbreak world, <em>a tweak</em> is an improvement that allows you to hook into existing classes and methods of installed third-party and system apps. Tweaks are hosted on repositories or repos usually handled by Cydia. Default Cydia repos are community maintained and imply a certain level of trust and safety.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-227"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-225">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-226'
	>
	For the sake of this blog post, I’ve made a repo of my own:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-230"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-228">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-229'
	>
	<a href="https://github.com/Adis">GitHub – Adis</a></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-233"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-231">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-232'
	>
	I won’t go into details on how to develop a tweak or host it on a repo since there’s a lot of work involved there, but my tool of choice for tweak development was <a href="https://github.com/theos/theos">Theos</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-236"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-234">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-235'
	>
	Back to work. Now that you know which method is responsible for making jailbreak checks, you’ll want to write a tweak that will override the behavior of that method. This is just a bit more of programming. Here’s the entire content of my own tweak:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-238"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-objective-c github-light" data-language="objective-c" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">// </span><span class="token" style="color: #d73a49;">Class</span><span class="token"> used to check </span><span class="token" style="color: #d73a49;">for</span><span class="token"> jailbreaks
</span></span><span class="line"><span class="token">%hook JBChecker
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">// Redefine the behavior of the function that checks
</span></span><span class="line"><span class="token">// </span><span class="token" style="color: #d73a49;">for</span><span class="token"> jailbreaks
</span></span><span class="line"><span class="token">+ (</span><span class="token" style="color: #d73a49;">BOOL</span><span class="token">)isJailbroken
</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"> </span><span class="token" style="color: #005cc5;">NO</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">%end
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-241"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-239">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-240'
	>
	The syntax is simple – <code>%hook %end</code> block injects itself into a class that checks for the jailbreak, and I rewrote the method that checks for jailbreaks to simply return false in all cases and skip any other checks.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-244"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-242">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-243'
	>
	In order to get this tweak on your own device, you’ll need to add a new source in Cydia. The app will warn you that this is not a trusted repo, and that’s fine. As mentioned above, only a selected few are trusted.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-247"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-245">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-246'
	>
	When the repo is there, you’ll find a single tweak called <code>JBBad</code>. After you install the tweak, go back and open the Jailbreaking Bad app. The app will – regardless of device status – report that the device is not jailbroken until you uninstall the tweak.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-250"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-248">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-249'
	>
	And a handy .gif with the boring parts sped up:</p></div>	</div>
</div>
</div>		</div>
	</div>

<div
	class="wrapper"
	data-id="es-255"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-253"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-254">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2019/01/jailbreaking-bad-why-jailbreak-detection-in-ios-apps-is-pointless-3.gif"
					class="image__img block-media__image-img"
					alt=""
										height="640"
															width="360"
										loading="lazy"
					 />
					</picture>

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

<div
	class="wrapper"
	data-id="es-267"
	 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-256">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-259"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-257">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-258'
	>
	Not a lack of security in iOS apps</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-262"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-260">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-261'
	>
	While the process described above might seem simple, it by no means implies that iOS apps lack security. Building truly secure apps includes far more than implementing a simple jailbreak check, and a threat that would justify the effort of blocking app usage based on jailbreak detection would have to be substantial and take copious amounts of work to devise.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-265"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-263">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-264'
	>
	The purpose of the article is to demonstrate that, at best, jailbreak detections are a tiny security upgrade. Such detections might only deter a part of your user base which is most likely well aware of the security issues a jailbreak presents.</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/jailbreaking-bad-why-jailbreak-detection-in-ios-apps-is-pointless/">Why Jailbreak Detection in iOS Apps Is Pointless</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
					<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-385"
	 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-268">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-271"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-269">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-270'
	>
	<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-274"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-272">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-273'
	>
	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-277"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-275">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-276'
	>
	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-280"
	 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-278"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-279">
	<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-283"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-281">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-282'
	>
	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-286"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-284">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-285'
	>
	The two pinning methods</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-289"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-287">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-288'
	>
	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-292"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-290">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-291'
	>
	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-295"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-293">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-294'
	>
	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-298"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-296">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-297'
	>
	SSL pinning cookbook</h2></div>	</div>

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

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-300">
	<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-304"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-302">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-303'
	>
	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-307"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-305">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-306'
	>
	Getting the certificate</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-310"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-308">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-309'
	>
	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-312"
	 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-315"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-313">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-314'
	>
	Pinning with Swift and Alamofire</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-318"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-316">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-317'
	>
	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-320"
	 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-323"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-321">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-322'
	>
	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-326"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-324">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-325'
	>
	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-328"
	 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-331"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-329">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-330'
	>
	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-334"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-332">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-333'
	>
	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-337"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-335">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-336'
	>
	You can either pin a <strong>certificate</strong>:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-339"
	 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-342"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-340">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-341'
	>
	Or a <strong>public key</strong>:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-344"
	 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-347"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-345">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-346'
	>
	Find the full code example in the repo here:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-350"
	 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-348"
	 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-349'
	>
	https://github.com/Adis/swift-ssl-pin-examples</div>		
			</div>
	</a>	</div>

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

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

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-359"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-357">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-358'
	>
	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-362"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-360">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-361'
	>
	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-365"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-363">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-364'
	>
	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-368"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-366">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-367'
	>
	Handling the certificate change/update</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-371"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-369">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-370'
	>
	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-374"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-372">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-373'
	>
	<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-377"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-375">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-376'
	>
	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-380"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-378">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-379'
	>
	Parting words</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-383"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-381">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-382'
	>
	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>
					<item>
				<image>
					<url>8031https://infinum.com/uploads/2014/02/how-two-men-delivered-a-baby-in-4-5-months-0.webp</url>
				</image>
				<title>How Two Men Delivered a Baby in 4.5 Months</title>
				<link>https://infinum.com/blog/how-two-men-delivered-a-baby-in-4-5-months/</link>
				<pubDate>Thu, 06 Mar 2014 09:00:00 +0000</pubDate>
				<dc:creator>Adis Mustedanagic</dc:creator>
				<guid isPermaLink="false">https://infinum.com/the-capsized-eight/how-two-men-delivered-a-baby-in-4-5-months/</guid>
				<description>
					<![CDATA[<p>Every once in a while, we get a request out of the ordinary, and just sometimes we take the challenge. </p>
<p>The post <a href="https://infinum.com/blog/how-two-men-delivered-a-baby-in-4-5-months/">How Two Men Delivered a Baby in 4.5 Months</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-450"
	 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-386">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-389"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-387">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-388'
	>
	Every once in a while, we get a request out of the ordinary, and just sometimes we take the challenge. This is a story about one of those times when two men delivered a baby in 4.5 months. <em>Figuratively</em>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-392"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-390">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-391'
	>
	Almost everyone working in software development eventually gets familiar with <a href="http://en.wikipedia.org/wiki/Brooks’s_law">Brooks’s law</a>. Another way of putting it is</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-397"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="blockquote block-blockquote__blockquote" data-id="es-393">
	
	<div class="blockquote__content">
		<i
	class="icon blockquote__icon icon--size-16 icon--scale-100"
	 aria-hidden='true' data-name='blockquote-24' data-id='es-394'>
	<svg fill='none' height='24' viewBox='0 0 24 24' width='24' xmlns='http://www.w3.org/2000/svg'><path clip-rule='evenodd' d='m12 24c6.6274 0 12-5.3726 12-12 0-2.79685-.9568-5.37021-2.561-7.41062-.581.22951-1.0832.60583-1.5069 1.12898-.5132.60844-.7698 1.41969-.7698 2.43375v.07605h2.5789v5.59004h-5.6197v-5.01962c0-1.11547.154-2.06616.4619-2.85205.3336-.81125.757-1.48307 1.2702-2.01545.528-.52161 1.1175-.92155 1.7687-1.1998-2.0728-1.70651-4.7279-2.73128-7.6223-2.73128-6.62742 0-12 5.37258-12 12 0 6.6274 5.37258 12 12 12zm-3.53811-18.05347c-.30793.78589-.46189 1.73658-.46189 2.85205v5.01962h5.6197v-5.59004h-2.5789v-.07605c0-1.01406.2566-1.82531.7698-2.43375.5389-.63379 1.1804-1.05209 1.9245-1.2549v-2.28164c-.7441.07605-1.4626.25351-2.1555.53238-.6928.27887-1.3086.68449-1.84752 1.21688-.51321.53238-.9366 1.2042-1.27019 2.01545z' fill='currentColor' fill-rule='evenodd'/></svg></i><p	class='typography typography--size-36-text js-typography blockquote__quote'
	data-id='es-395'
	>
	Nine women can’t deliver a baby in one month.</p>
		<div class="blockquote__caption-wrap">
					</div>
	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-400"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-398">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-399'
	>
	Hence the figure of speech above. There are exceptions, of course, and this is one of them.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-403"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-401">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-402'
	>
	The quest</h2></div>	</div>

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

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-405">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2014/02/how-two-men-delivered-a-baby-in-4-5-months-1.webp"
					class="image__img block-media__image-img"
					alt=""
										height="200"
															width="700"
										loading="lazy"
					 />
					</picture>

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

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-409"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-407">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-408'
	>
	To conquer the unknown, of course. Long story short, we were given an opportunity to help out on a project that was late before we even started. The details were scarce, the job was on-site with the client at the other end of Europe, and the deadlines were just around the corner. After a quick round of negotiations, the deal was set: two men for <strong>four days</strong>, working on a big app that was yet to be released to the public.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-412"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-410">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-411'
	>
	The resolution</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-415"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-413">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-414'
	>
	Skipping ahead to the end – <em>well, it worked</em>. We gave the project a much needed push in the right direction and set the grounds for working on it from back home. Looking back, I don’t think I ever doubted we would pull it off, despite the odds looking grim on paper.</p></div>	</div>

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

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-417">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2014/02/how-two-men-delivered-a-baby-in-4-5-months-2.webp"
					class="image__img block-media__image-img"
					alt=""
										height="330"
															width="700"
										loading="lazy"
					 />
					</picture>

			<figcaption class="image__figcaption block-media__image-figcaption">
			Programmers in action		</figcaption>
	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-421"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-419">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-420'
	>
	So, why the lack of concern, and even more important, why did things work out well?</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-424"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-422">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-423'
	>
	For starters, a lot of <strong>mobile apps</strong> are in the scope of <strong>1-2 developers</strong> to handle. Usually a single developer should be competent enough to handle an average app by himself, not including the API or other components outside of the application. This was the case here as well, with most of the work being done by a single developer, so initial project assessment took a negligible amount of time.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-427"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-425">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-426'
	>
	There was also <strong>the pressure</strong> to do what we were hired to do. Some people don’t respond well to increased pressure and lack of time, but in our case this probably added the much needed sense of urgency.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-430"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-428">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-429'
	>
	<strong>Isolation and focus</strong> can boost productivity drastically. Working on-site, with very little to worry about other than the project at hand, we could afford to concentrate completely on a single task that needed to be done at that moment.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-433"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-431">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-432'
	>
	<strong>Experience</strong> was also a key factor. This wasn’t our first rodeo, so we knew exactly how to handle certain situations. It was just a matter of coding the right solution and not wasting time on figuring it out.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-436"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-434">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-435'
	>
	The challenges and lessons</h2></div>	</div>

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

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-438">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2014/02/how-two-men-delivered-a-baby-in-4-5-months-3.webp"
					class="image__img block-media__image-img"
					alt=""
										height="200"
															width="700"
										loading="lazy"
					 />
					</picture>

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

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-442"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-440">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-441'
	>
	After working on the project on-site with the client, I brought it back home to work on it full time. There were quite a few hurdles to overcome with the combination of working on-site and working remotely, but it essentially boiled down to these:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-445"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-443">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-444'
	>
	<li>Working with other people can be challenging if they’re not a regular member of your team. Get to know them and find common ground and a good way to work together.</li><li>Every company has its own development processes and prefers different tools. It takes a bit of time to fit into a different workflow (<em>or even help someone ditch their workflow in favor of a better one</em>). Switching to a newer or more suitable technology is often a short-term pain that proves to be worthwhile in the long run.</li><li>Sometimes, perseverance is the key. More than once, the issues kept piling up, but working through them was just a matter of persistence and systematic problem solving.</li><li>Developing a location based app while not being at the location turned out to be a lesser challenge than expected. A bike is a really versatile transportation method for simulating different conditions.</li><li>Skype meetings are mostly fine, but in-person meetings every now and then can give you a positive boost.</li><li>In certain scenarios, <a href="http://en.wikipedia.org/wiki/Pair_programming">pair programming</a> is a very effective technique. For example when a new programmer needs to be quickly introduced into an existing project at a later stage of development.</li><li>Always check the weather before traveling and dress accordingly.</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-448"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-446">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-447'
	>
	The last one is probably the least significant for this article, <a href="https://www.youtube.com/watch?v=sTJ7AzBIJoI">but sometimes the simplest advice is the best advice</a>.</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/how-two-men-delivered-a-baby-in-4-5-months/">How Two Men Delivered a Baby in 4.5 Months</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
					<item>
				<image>
					<url>8008https://infinum.com/uploads/2014/01/ios7-sdk-is-mandatory-upgrade-your-apps-now-0.webp</url>
				</image>
				<title>iOS 7 SDK Is Mandatory. Upgrade Your Apps Now!</title>
				<link>https://infinum.com/blog/ios7-sdk-is-mandatory-upgrade-your-apps-now/</link>
				<pubDate>Fri, 03 Jan 2014 11:00:00 +0000</pubDate>
				<dc:creator>Adis Mustedanagic</dc:creator>
				<guid isPermaLink="false">https://infinum.com/the-capsized-eight/ios7-sdk-is-mandatory-upgrade-your-apps-now/</guid>
				<description>
					<![CDATA[<p>Apple has recently announced that, starting from February 1st, all iOS apps and updates need to work seamlessly with iOS 7.</p>
<p>The post <a href="https://infinum.com/blog/ios7-sdk-is-mandatory-upgrade-your-apps-now/">iOS 7 SDK Is Mandatory. Upgrade Your Apps Now!</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-524"
	 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-451">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-454"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-452">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-453'
	>
	Apple has recently announced that, starting from February 1st, all iOS apps and updates need to work seamlessly with iOS 7.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-457"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-455">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-456'
	>
	<a href="https://developer.apple.com/news/?id=12172013a">Link to the relevant announcement.</a></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-462"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="blockquote block-blockquote__blockquote" data-id="es-458">
	
	<div class="blockquote__content">
		<i
	class="icon blockquote__icon icon--size-16 icon--scale-100"
	 aria-hidden='true' data-name='blockquote-24' data-id='es-459'>
	<svg fill='none' height='24' viewBox='0 0 24 24' width='24' xmlns='http://www.w3.org/2000/svg'><path clip-rule='evenodd' d='m12 24c6.6274 0 12-5.3726 12-12 0-2.79685-.9568-5.37021-2.561-7.41062-.581.22951-1.0832.60583-1.5069 1.12898-.5132.60844-.7698 1.41969-.7698 2.43375v.07605h2.5789v5.59004h-5.6197v-5.01962c0-1.11547.154-2.06616.4619-2.85205.3336-.81125.757-1.48307 1.2702-2.01545.528-.52161 1.1175-.92155 1.7687-1.1998-2.0728-1.70651-4.7279-2.73128-7.6223-2.73128-6.62742 0-12 5.37258-12 12 0 6.6274 5.37258 12 12 12zm-3.53811-18.05347c-.30793.78589-.46189 1.73658-.46189 2.85205v5.01962h5.6197v-5.59004h-2.5789v-.07605c0-1.01406.2566-1.82531.7698-2.43375.5389-.63379 1.1804-1.05209 1.9245-1.2549v-2.28164c-.7441.07605-1.4626.25351-2.1555.53238-.6928.27887-1.3086.68449-1.84752 1.21688-.51321.53238-.9366 1.2042-1.27019 2.01545z' fill='currentColor' fill-rule='evenodd'/></svg></i><p	class='typography typography--size-36-text js-typography blockquote__quote'
	data-id='es-460'
	>
	Starting February 1, new apps and app updates submitted to the App Store must be built with the latest version of Xcode 5 and must be optimized for iOS 7.</p>
		<div class="blockquote__caption-wrap">
					</div>
	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-465"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-463">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-464'
	>
	In technical terms, starting February 1st, all apps submitted to the App Store need to be built with <strong>iOS 7 SDK</strong> and <strong>XCode 5</strong>. Anything that does not conform to these terms will be rejected.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-468"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-466">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-467'
	>
	In less technical terms, this means that your apps need to make use of the new iOS 7 design and interface.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-471"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-469">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-470'
	>
	What is the difference between iOS 7 SDK and the other ones?</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-474"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-472">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-473'
	>
	The difference is mostly visual. For example, compare the two screenshots below; the left one is the Elements example app back in iOS 6 and before, and the right one is the same app in iOS 7.</p></div>	</div>

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

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-476">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2014/01/ios7-sdk-is-mandatory-upgrade-your-apps-now-1.webp"
					class="image__img block-media__image-img"
					alt=""
										height="552"
															width="580"
										loading="lazy"
					 />
					</picture>

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

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-480"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-478">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-479'
	>
	This is also the fastest way to determine visually whether an app needs an update. If your app looks like the left one on iOS 7, you will most likely have to update your app to the new SDK.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-483"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-481">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-482'
	>
	Do I need to update my app?</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-486"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-484">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-485'
	>
	There are quite a few ways to answer this question, and they all depend on what the future plans for your app are. The nifty flowchart below should answer most of your questions.</p></div>	</div>

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

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-488">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2014/01/ios7-sdk-is-mandatory-upgrade-your-apps-now-2.webp"
					class="image__img block-media__image-img"
					alt=""
										height="413"
															width="550"
										loading="lazy"
					 />
					</picture>

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

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-492"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-490">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-491'
	>
	In a nutshell, if you are still not using the new SDK and have an actively developed app, updating is imminent, but you have a small time frame to push critical updates if you have to.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-495"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-493">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-494'
	>
	Does this mean that my app won’t work on older versions of iOS?</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-498"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-496">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-497'
	>
	No. The SDK and the minimal supported versions of iOS are not the same thing, and your app will still work on old versions of iOS you want to support.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-501"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-499">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-500'
	>
	Is changing the SDK a lot of work?</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-504"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-502">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-503'
	>
	It depends. Just switching the SDK is done in a jiffy. However, you still need to make sure there are no wayward visual elements. The design of every app is at least a bit customized and will probably need some tweaking. Adjusting visual elements might also be needed to complement the new flat design if your app looks odd in the new environment.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-507"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-505">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-506'
	>
	iOS 7 also brings new gestures, notably, the swipe-to-go-back, so if your app takes advantage of different gestures, another part of upgrading is making sure there is no unwanted interaction between the two.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-510"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-508">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-509'
	>
	To put it shortly – it depends on the size of your app and the amount of work you want done.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-513"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-511">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-512'
	>
	What will be the consequences of this announcement?</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-516"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-514">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-515'
	>
	At the time of writing this article, the <a href="https://developer.apple.com/support/appstore/">iOS 7 market share is at 78% percent</a> and rising. Presumably, this is one of the decisions made to push the percentages up and make the development for previous versions of iOS obsolete. Apple is pushing hard to keep the users up to date with their release cycle, but there will always be a minor percentage of users who do not update, whatever reason there might be for not doing so.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-519"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-517">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-518'
	>
	For <strong>developers</strong>, this is a welcome change. Having to support more than the latest SDK is a rather complicated development process, and this will make things much simpler.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-522"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-520">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-521'
	>
	On the other hand, this decision also means more work for apps that have not yet been converted to iOS 7 SDK, and are planning an update soon, possibly pushing the date of the update a bit further. It also means that if you are targeting a significant number of users still using iOS 6, there will be some extra work to make sure everything looks as intended.</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/ios7-sdk-is-mandatory-upgrade-your-apps-now/">iOS 7 SDK Is Mandatory. Upgrade Your Apps Now!</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
		
	</channel>
</rss>