{"id":130669,"date":"2021-01-15T00:29:31","date_gmt":"2021-01-15T00:29:31","guid":{"rendered":"https:\/\/developer.apple.com\/news\/?id=g9ejcf8y"},"modified":"2021-01-15T00:29:31","modified_gmt":"2021-01-15T00:29:31","slug":"identity-pinning-how-to-configure-server-certificates-for-your-app","status":"publish","type":"post","link":"https:\/\/sickgaming.net\/blog\/2021\/01\/15\/identity-pinning-how-to-configure-server-certificates-for-your-app\/","title":{"rendered":"Identity Pinning: How to configure server certificates for your app"},"content":{"rendered":"<div class=\"inline-article-image\"><img decoding=\"async\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2022\/12\/identity-pinning-how-to-configure-server-certificates-for-your-app.jpg\" data-hires=\"false\" alt><\/div>\n<p>If your app sends or receives data over the network, it\u2019s critical to preserve the privacy and integrity of a person\u2019s information and protect it from data breaches and attacks. You should use the Transport Layer Security (TLS) protocol to protect content in transit and authenticate the server receiving the data.<\/p>\n<p>When you connect through TLS, the server provides a certificate or certificate chain to establish its identity. You can further limit the set of server certificates your app trusts by pinning their public-key identities in your app. Here\u2019s how to get started.<\/p>\n<h3>When to use pinning<\/h3>\n<p>By default, when your app connects to a secure TLS network, the system evaluates server trustworthiness by default. Most apps can meet their security requirements by relying on this behavior; however, certain apps may need to further limit the set of trusted certificates.<\/p>\n<p>For example, your app may need to meet regulatory requirements that determine which specific Certificate Authorities (CAs) can be trusted. While Apple platforms ensure by default that only trustworthy CAs are involved, your app can use identity pinning to further limit the set of CAs to those associated with a particular government or organization.<\/p>\n<p>Pinning cannot loosen the trust requirements of your app \u2014&nbsp;it can only tighten them. You still always need to meet the system\u2019s default trust requirements when using public-key certificates involved in a TLS network connection.<\/p>\n<hr>\n<p><em>Note: When you\u2019ve configured your app to expect a specific set of public keys for a given server, it will refuse to connect to that server unless those public keys are involved. As a result, if the server deploys new certificates that alter the public keys, your app will refuse to connect. At that point, you\u2019ll need to update your app with a pinning configuration that reflects the new set of public keys.<\/em><\/p>\n<hr>\n<h3>Think long term<\/h3>\n<p>If you want to use identity pinning in your app, consider creating a long-term strategy that accounts for both planned and unplanned events so that you can prevent pinning failures.<\/p>\n<p>Your app can proactively provide a great experience by pinning the public keys of CAs, instead of servers. This way, you can deploy server certificates that contain new public keys signed by the same CA without the need for pinning configuration updates.<\/p>\n<p>You can also consider pinning more than one public key, especially when pinning server identities. This way, your app will still be able to connect to configured servers even if they revoke or rotate certificates.<\/p>\n<p>Additionally, plan to provide a fallback experience in your app if it\u2019s unable to connect to a server in the event of a pinning failure. First, think of ways your app experience may be impacted, and come up with mitigating solutions for any negative side effects. Can the app still function without making that connection, and can you provide someone with a temporary recovery path?<\/p>\n<p>You\u2019ll also want to plan for an eventual recovery path. One way you can address pinning failures is through a new pinning configuration, delivered via app update. Consider whether that\u2019s an option given the use cases of your app.<\/p>\n<p>We highly recommend simulating various events and potential failure points when testing your app by acquiring additional public-key certificates for this purpose and varying the configuration of your server accordingly.<\/p>\n<h3>How to pin CA public keys<\/h3>\n<p>A pinned CA public key must appear in a certificate chain either in an intermediate or root certificate. Pinned keys are always associated with a domain name, and the app will refuse to connect to that domain unless the pinning requirement is met.<\/p>\n<p>As an example, to require the presence of a specific CA public key when connecting to the <code>example.org<\/code> domain name, you can add the following entries to the <code>Info.plist<\/code> file of your app.<\/p>\n<div class=\"inline-article-image\"><img decoding=\"async\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2022\/12\/identity-pinning-how-to-configure-server-certificates-for-your-app-1.jpg\" data-hires=\"false\" alt=\"NSAppTransportSecurity NSPinnedDomains example.org NSIncludesSubdomains NSPinnedCAIdentities SPKI-SHA256-BASE64 r\/mIkG3eEpVdm+u\/ko\/cwxzOMo1bk4TyHIlByibiA5E= \"><\/p>\n<div class=\"typography-caption\">NSAppTransportSecurity<br \/>\n NSPinnedDomains  example.org  NSIncludesSubdomains  NSPinnedCAIdentities   SPKI-SHA256-BASE64 r\/mIkG3eEpVdm+u\/ko\/cwxzOMo1bk4TyHIlByibiA5E=\n<\/div>\n<\/div>\n<pre class=\"code-source\"><code><span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">key<\/span>&gt;<\/span>NSAppTransportSecurity<span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">key<\/span>&gt;<\/span>\n<span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">dict<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">key<\/span>&gt;<\/span>NSPinnedDomains<span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">key<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">dict<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">key<\/span>&gt;<\/span>example.org<span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">key<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">dict<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">key<\/span>&gt;<\/span>NSIncludesSubdomains<span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">key<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">true<\/span>\/&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">key<\/span>&gt;<\/span>NSPinnedCAIdentities<span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">key<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">array<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">dict<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">key<\/span>&gt;<\/span>SPKI-SHA256-BASE64<span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">key<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">string<\/span>&gt;<\/span>r\/mIkG3eEpVdm+u\/ko\/cwxzOMo1bk4TyHIlByibiA5E=<span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">string<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">dict<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">array<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">dict<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">dict<\/span>&gt;<\/span>\n<span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">dict<\/span>&gt;<\/span><\/code><\/pre>\n<p>In this example, the pinned public key is associated with <code>example.org<\/code> and also subdomains such as <code>math.example.org<\/code> and <code>history.example.org<\/code>, but it won\u2019t be associated with <code>advanced.math.example.org<\/code>, or <code>ancient.history.example.org<\/code>.<\/p>\n<p>The public key is expressed as the Base64-encoded SHA-256 digest of an X.509 certificate\u2019s DER-encoded ASN.1 Subject Public Key Info structure. Assuming the following PEM-encoded public-key certificate, stored in file <code>ca.pem<\/code>, you can calculate its SPKI-SHA256-BASE64 value with the <code>openssl<\/code> command.<\/p>\n<pre class=\"code-source\"><code>-----BEGIN CERTIFICATE-----\nMIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh\nMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\nd3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\nQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT\nMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\nb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG\n9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB\nCSDMAZOnTjC3U\/dDxGkAV53ijSLdhwZAAIEJzs4bg7\/fzTtxRuLWZscFs3YnFo97\nnh6Vfe63SKMI2tavegw5BmV\/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt\n43C\/dxC\/\/AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P\nT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr\/y7vrTC0LUq7dBMtoM1O\/4\ngdW7jVg\/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO\nBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH\/BAUwAwEB\/zAdBgNVHQ4EFgQUA95QNVbR\nTLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw\nDQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY\/Esr\nhMAtudXH\/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp\/2PV5Adg\n06O\/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF\nPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls\nYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk\nCAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=\n-----END CERTIFICATE----- $ cat ca.pem | openssl x509 -inform pem -noout -outform pem -pubkey | openssl pkey -pubin -inform pem -outform der | openssl dgst -sha256 -binary | openssl enc -base64<\/code><\/pre>\n<p>To introduce redundancy into your pinning configuration, you can associate multiple public keys with a domain name. <\/p>\n<div class=\"inline-article-image\"><img decoding=\"async\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2022\/12\/identity-pinning-how-to-configure-server-certificates-for-your-app-2.jpg\" data-hires=\"false\" alt=\"Screenshot of NSPinnedLeafIdentities: App Transport Security Settings \u2014 Dictionary \u2014 1 item\nNSPinned Domains \u2014&nbsp;Dictionary \u2014&nbsp;2 items\nexample.org \u2014&nbsp;Dictionary \u2014&nbsp;2 items\nexample.net \u2014&nbsp;Dictionary \u2014&nbsp;1 item\nNSPinnedLeafIdentities&nbsp;\u2014 Array \u2014&nbsp;2 items\nItem 0 \u2014&nbsp;Dictionary \u2014&nbsp;1 item\nSPKI-SHA256-BASE64&nbsp;\u2014&nbsp;String \u2014&nbsp;i9HalScvf6T\/skE3\/A7QOq5n5cTYs8UHNOEFCnkguSI=\nItem 1 \u2014&nbsp;Dictionary \u2014&nbsp;1 item\nSPKI-SHA256-BASE64&nbsp;\u2014&nbsp;String \u2014&nbsp;i9HalScvf6T\/skE3\/A7QOq5n5cTYs8UHNOEFCnkguSI=\"><\/div>\n<pre class=\"code-source\"><code><span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">key<\/span>&gt;<\/span>NSAppTransportSecurity<span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">key<\/span>&gt;<\/span>\n<span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">dict<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">key<\/span>&gt;<\/span>NSPinnedDomains<span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">key<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">dict<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">key<\/span>&gt;<\/span>example.org<span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">key<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">dict<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">key<\/span>&gt;<\/span>NSIncludesSubdomains<span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">key<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">true<\/span>\/&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">key<\/span>&gt;<\/span>NSPinnedCAIdentities<span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">key<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">array<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">dict<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">key<\/span>&gt;<\/span>SPKI-SHA256-BASE64<span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">key<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">string<\/span>&gt;<\/span>r\/mIkG3eEpVdm+u\/ko\/cwxzOMo1bk4TyHIlByibiA5E=<span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">string<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">dict<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">array<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">dict<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">key<\/span>&gt;<\/span>example.net<span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">key<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">dict<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">key<\/span>&gt;<\/span>NSPinnedLeafIdentities<span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">key<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">array<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">dict<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">key<\/span>&gt;<\/span>SPKI-SHA256-BASE64<span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">key<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">string<\/span>&gt;<\/span>i9HaIScvf6T\/skE3\/A7QOq5n5cTYs8UHNOEFCnkguSI=<span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">string<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">dict<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">dict<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">key<\/span>&gt;<\/span>SPKI-SHA256-BASE64<span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">key<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;<span class=\"syntax-name\">string<\/span>&gt;<\/span>i9HaIScvf6T\/skE3\/A7QOq5n5cTYs8UHNOEFCnkguSI=<span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">string<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">dict<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">array<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">dict<\/span>&gt;<\/span> <span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">dict<\/span>&gt;<\/span>\n<span class=\"syntax-tag\">&lt;\/<span class=\"syntax-name\">dict<\/span>&gt;<\/span><\/code><\/pre>\n<p>For example, to pin multiple public keys for the <code>example.net<\/code> server certificate, you would add individual entries as items in an array to the <code>Info.plist<\/code> file of your app. To satisfy the pinning requirement for a connection to <code>example.net<\/code>, the server certificate must include one of those keys.<\/p>\n<h3>Resources<\/h3>\n<p><a href=\"https:\/\/developer.apple.com\/documentation\/bundleresources\/information_property_list\/nsapptransportsecurity\" class=\"icon icon-after icon-chevronright\">NSAppTransportSecurity<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>If your app sends or receives data over the network, it\u2019s critical to preserve the privacy and integrity of a person\u2019s information and protect it from data breaches and attacks. You should use the Transport Layer Security (TLS) protocol to protect content in transit and authenticate the server receiving the data. When you connect through [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":130670,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[55],"tags":[],"class_list":["post-130669","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-apple-developer-news"],"_links":{"self":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/130669","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/comments?post=130669"}],"version-history":[{"count":0,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/130669\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/media\/130670"}],"wp:attachment":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/media?parent=130669"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/categories?post=130669"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/tags?post=130669"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}