Home | History | Annotate | Download | only in articles
      1 page.title=Network Security Configuration
      2 page.keywords=security,network,config
      3 page.metaDescription=Feature that allows app developers to customize network security settings in a safe configuration file.
      4 page.image=images/cards/card-nyc_2x.jpg
      5 
      6 @jd:body
      7 
      8 <div id="tb-wrapper">
      9 <div id="tb">
     10 
     11 <h2>In this document</h2>
     12 <ol>
     13   <li><a href="#manifest">Adding a Security Configuration File</a></li>
     14   <li><a href="#CustomTrust">Customizing Trusted CAs</a>
     15       <ol>
     16       <li><a href="#ConfigCustom">Configuring a Trusted Custom CA</a></li>
     17       <li><a href="#LimitingCas">Limiting the Set of Trusted CAs</a></li>
     18       <li><a href="#TrustingAdditionalCas">Trusting Additional CAs</a></li>
     19       </ol>
     20   </li>
     21   <li><a href="#TrustingDebugCa">Debugging-only CAs</a></li>
     22   <li><a href="#CleartextTrafficPermitted">Opting Out of Cleartext Traffic</a></li>
     23   <li><a href="#CertificatePinning">Pinning Certificates</a></li>
     24   <li><a href="#ConfigInheritance">Configuration Inheritance Behavior</a></li>
     25   <li><a href="#FileFormat">Configuration File Format</a></li>
     26 </ol>
     27 </div>
     28 </div>
     29 
     30 
     31 <p>
     32   The Network Security Configuration feature lets apps customize their network
     33   security settings in a safe, declarative configuration file without modifying
     34   app code. These settings can be configured for specific domains and for a
     35   specific app. The key capabilities of this feature are as follows:
     36 </p>
     37 
     38 <ul>
     39   <li>
     40     <b>Custom trust anchors:</b> Customize which Certificate Authorities (CA)
     41     are trusted for an app's secure connections. For
     42     example, trusting particular self-signed certificates or restricting the
     43     set of public CAs that the app trusts.
     44   </li>
     45 
     46   <li>
     47     <b>Debug-only overrides:</b> Safely debug secure connections in an app
     48     without added risk to the installed base.
     49   </li>
     50 
     51   <li>
     52     <b>Cleartext traffic opt-out:</b> Protect apps from
     53     accidental usage of cleartext traffic.
     54   </li>
     55 
     56   <li>
     57     <b>Certificate pinning:</b> Restrict an app's secure connection to
     58     particular certificates.
     59   </li>
     60 </ul>
     61 
     62 
     63 <h2 id="manifest">Adding a Security Configuration File</h2>
     64 
     65 <p>
     66   The Network Security Configuration feature uses an XML file where you specify
     67   the settings for your app. You must include an entry in the manifest of your
     68   app to point to this file. The following code excerpt from a manifest
     69   demonstrates how to create this entry:
     70 </p>
     71 
     72 <pre>
     73 &lt;?xml version="1.0" encoding="utf-8"?&gt;
     74 &lt;manifest ... &gt;
     75     &lt;application android:networkSecurityConfig="@xml/network_security_config"
     76                     ... &gt;
     77         ...
     78     &lt;/application&gt;
     79 &lt;/manifest&gt;
     80 </pre>
     81 
     82 <h2 id="CustomTrust">Customizing Trusted CAs</h2>
     83 
     84 <p>
     85   An app may want to trust a custom set of CAs instead of the platform
     86   default. The most common reasons of this are:
     87 </p>
     88 
     89 <ul>
     90   <li>Connecting to a host with a custom certificate authority, such as a
     91   CA that is self-signed or is issued internally within a company.
     92   </li>
     93 
     94   <li>Limiting the set of CAs to only the CAs you trust instead of every
     95   pre-installed CA.
     96   </li>
     97 
     98   <li>Trusting additional CAs not included in the system.
     99   </li>
    100 </ul>
    101 
    102 <p>
    103   By default, secure connections (using protocols like TLS and HTTPS) from all
    104   apps trust the pre-installed system CAs, and apps targeting Android 6.0 (API
    105   level 23) and lower also trust the user-added CA store by default. An app can
    106   customize its own connections using {@code base-config} (for app-wide
    107   customization) or {@code domain-config} (for per-domain customization).
    108 </p>
    109 
    110 
    111 <h3 id="ConfigCustom">Configuring a Custom CA</h3>
    112 
    113 <p>
    114   Assume you want to connect to your host which uses a self-signed SSL
    115   certificate or to a host whose SSL certificate is issued by a non-public CA
    116   which you trust, such as your company's internal CA.
    117 </p>
    118 
    119 <p>
    120   <code>res/xml/network_security_config.xml</code>:
    121 <pre>
    122 &lt;?xml version="1.0" encoding="utf-8"?&gt;
    123 &lt;network-security-config&gt;
    124     &lt;domain-config&gt;
    125         &lt;domain includeSubdomains="true"&gt;example.com&lt;/domain&gt;
    126         &lt;trust-anchors&gt;
    127             &lt;certificates src="@raw/my_ca"/&gt;
    128         &lt;/trust-anchors&gt;
    129     &lt;/domain-config&gt;
    130 &lt;/network-security-config&gt;
    131 </pre>
    132 </p>
    133 
    134 <p>
    135   Add the self-signed or non-public CA certificate, in PEM or DER format, to
    136   {@code res/raw/my_ca}.
    137 </p>
    138 
    139 
    140 <h3 id="LimitingCas">Limiting the Set of Trusted CAs</h3>
    141 
    142 <p>
    143   An app that does not want to trust all CAs trusted by system can
    144   instead specify its own reduced set of CAs to trust. This protects the
    145   app from fradulent certificates issued by any of the other CAs.
    146 </p>
    147 
    148 <p>
    149   The configuration to limit the set of trusted CAs is similar to <a href=
    150   "#ConfigCustom">trusting a custom CA</a> for a specific domain except
    151   that multiple CAs are provided in the resource.
    152 </p>
    153 
    154 <p>
    155 <code>res/xml/network_security_config.xml</code>:
    156 <pre>
    157 &lt;?xml version="1.0" encoding="utf-8"?&gt;
    158 &lt;network-security-config&gt;
    159     &lt;domain-config&gt;
    160         &lt;domain includeSubdomains="true"&gt;secure.example.com&lt;/domain&gt;
    161         &lt;domain includeSubdomains="true"&gt;cdn.example.com&lt;/domain&gt;
    162         &lt;trust-anchors&gt;
    163             &lt;certificates src="@raw/trusted_roots"/&gt;
    164         &lt;/trust-anchors&gt;
    165     &lt;/domain-config&gt;
    166 &lt;/network-security-config&gt;
    167 </pre>
    168 </p>
    169 
    170 <p>
    171   Add the trusted CAs, in PEM or DER format, to {@code res/raw/trusted_roots}.
    172   Note that if using PEM format the file must contain <em>only</em> PEM data
    173   and no extra text. You can also provide multiple
    174   <a href="#certificates"><code>&lt;certificates&gt;</code></a>
    175 elements instead of one.
    176 </p>
    177 
    178 
    179 <h3 id="TrustingAdditionalCas">
    180   Trusting Additional CAs
    181 </h3>
    182 
    183 <p>
    184   An app may want to trust additional CAs not trusted by the system,
    185   this could be due to the system not yet including the CA or a CA that does
    186   not meet the requirements for inclusion into the Android system. An
    187   app can do this by specifying multiple certificate sources for a
    188   configuration.
    189 </p>
    190 <p>
    191 <code>res/xml/network_security_config.xml</code>:
    192 <pre>
    193 &lt;?xml version="1.0" encoding="utf-8"?&gt;
    194 &lt;network-security-config&gt;
    195     &lt;base-config&gt;
    196         &lt;trust-anchors&gt;
    197             &lt;certificates src="@raw/extracas"/&gt;
    198             &lt;certificates src="system"/&gt;
    199         &lt;/trust-anchors&gt;
    200     &lt;/base-config&gt;
    201 &lt;/network-security-config&gt;
    202 </pre>
    203 </p>
    204 
    205 
    206 <h2 id="TrustingDebugCa">Configuring CAs for Debugging</h2>
    207 
    208 <p>
    209   When debugging an app that connects over HTTPS, you may want to
    210   connect to a local development server, which does not have the SSL
    211   certificate for your production server. In order to support this without any
    212   modification to your app's code, you can specify debug-only CAs, which
    213   are trusted <i>only</i> when <a href=
    214   "{@docRoot}guide/topics/manifest/application-element.html#debug">
    215 android:debuggable</a>
    216   is {@code true}, by using {@code debug-overrides}. Normally, IDEs and build
    217   tools set this flag automatically for non-release builds.
    218 </p>
    219 
    220 <p>
    221   This is safer than the usual conditional code because, as a security
    222   precaution, app stores do not accept apps which are marked
    223   debuggable.
    224 </p>
    225 
    226 <p>
    227 <code>res/xml/network_security_config.xml</code>:
    228 <pre>
    229 &lt;?xml version="1.0" encoding="utf-8"?&gt;
    230 &lt;network-security-config&gt;
    231     &lt;debug-overrides&gt;
    232         &lt;trust-anchors&gt;
    233             &lt;certificates src="@raw/debug_cas"/&gt;
    234         &lt;/trust-anchors&gt;
    235     &lt;/debug-overrides&gt;
    236 &lt;/network-security-config&gt;
    237 </pre>
    238 </p>
    239 
    240 
    241 <h2 id="CleartextTrafficPermitted">Opting Out of Cleartext Traffic</h2>
    242 
    243 <p>
    244   Applications intending to connect to destinations using only secure
    245   connections can opt-out of supporting cleartext (using the unencrypted HTTP
    246   protocol instead of HTTPS) to those destinations. This option helps prevent
    247   accidental regressions in apps due to changes in URLs provided by external
    248   sources such as backend servers.
    249   See {@link android.security.NetworkSecurityPolicy#isCleartextTrafficPermitted
    250   NetworkSecurityPolicy.isCleartextTrafficPermitted()} for more details.
    251 </p>
    252 
    253 <p>
    254   For example, an app may want to ensure that all connections to {@code
    255   secure.example.com} are always done over HTTPS to protect sensitive traffic
    256   from hostile networks.
    257 </p>
    258 
    259 <p>
    260 <code>res/xml/network_security_config.xml</code>:
    261 <pre>
    262 &lt;?xml version="1.0" encoding="utf-8"?&gt;
    263 &lt;network-security-config&gt;
    264     &lt;domain-config cleartextTrafficPermitted="false"&gt;
    265         &lt;domain includeSubdomains="true"&gt;secure.example.com&lt;/domain&gt;
    266     &lt;/domain-config&gt;
    267 &lt;/network-security-config&gt;
    268 </pre>
    269 </p>
    270 
    271 
    272 <h2 id="CertificatePinning">Pinning Certificates</h2>
    273 
    274 <p>
    275   Normally, an app trusts all pre-installed CAs. If any of these CAs were to
    276   issue a fradulent certificate, the app would be at risk from a
    277   man-in-the-middle attack. Some apps choose to limit the set of certificates
    278   they accept by either limiting the set of CAs they trust or by certificate
    279   pinning.
    280 </p>
    281 
    282 <p>
    283   Certificate pinning is done by providing a set of certificates by hash of the
    284   public key (<code>SubjectPublicKeyInfo</code> of the X.509 certificate). A
    285   certificate chain is then valid only if the certificate chain contains at
    286   least one of the pinned public keys.
    287 </p>
    288 
    289 <p>
    290   Note that, when using certificate pinning, you should always include a backup
    291   key so that if you are forced to switch to new keys or change CAs (when
    292   pinning to a CA certificate or an intermediate of that CA), your
    293   app's connectivity is unaffected. Otherwise, you must push out
    294   an update to the app to restore connectivity.
    295 </p>
    296 
    297 <p>
    298   Additionally, it is possible to set an expiration time for pins after which
    299   pinning is not performed. This helps prevent connectivity issues in
    300   apps which have not been updated. However, setting an expiration time
    301   on pins may enable pinning bypass.
    302 </p>
    303 
    304 <p>
    305 <code>res/xml/network_security_config.xml</code>:
    306 <pre>
    307 &lt;?xml version="1.0" encoding="utf-8"?&gt;
    308 &lt;network-security-config&gt;
    309     &lt;domain-config&gt;
    310         &lt;domain includeSubdomains="true"&gt;example.com&lt;/domain&gt;
    311         &lt;pin-set expiration="2018-01-01"&gt;
    312             &lt;pin digest="SHA-256"&gt;7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=&lt;/pin&gt;
    313             &lt;!-- backup pin --&gt
    314             &lt;pin digest="SHA-256"&gt;fwza0LRMXouZHRC8Ei+4PyuldPDcf3UKgO/04cDM1oE=&lt;/pin&gt;
    315         &lt;/pin-set&gt;
    316     &lt;/domain-config&gt;
    317 &lt;/network-security-config&gt;
    318 </pre>
    319 </p>
    320 
    321 
    322 <h2 id="ConfigInheritance">Configuration Inheritance Behavior</h2>
    323 
    324 <p>
    325   Values not set in a specific configuration are inherited. This behavior allows
    326   more complex configurations while keeping the configuration file readable.
    327 </p>
    328 
    329 <p>
    330   If a value is not set in a specific entry, then the value from the more
    331   general entry is used. For example, values not set in a {@code domain-config}
    332   are taken from the parent {@code domain-config}, if nested, or from the {@code
    333   base-config} if not. Values not set in the {@code base-config} use the
    334   platform default values.
    335 </p>
    336 
    337 <p>
    338   For example, consider where all connections to subdomains of {@code
    339   example.com} must use a custom set of CAs. Additonally, cleartext traffic to
    340   these domains is permitted <em>except</em> when connecting to {@code
    341   secure.example.com}. By nesting the configuration for {@code
    342   secure.example.com} inside the configuration for {@code example.com}, the
    343   {@code trust-anchors} does not need to be duplicated.
    344 </p>
    345 
    346 <p>
    347 <code>res/xml/network_security_config.xml</code>:
    348 <pre>
    349 &lt;?xml version="1.0" encoding="utf-8"?&gt;
    350 &lt;network-security-config&gt;
    351     &lt;domain-config&gt;
    352         &lt;domain includeSubdomains="true"&gt;example.com&lt;/domain&gt;
    353         &lt;trust-anchors&gt;
    354             &lt;certificates src="@raw/my_ca"/&gt;
    355         &lt;/trust-anchors&gt;
    356         &lt;domain-config cleartextTrafficPermitted="false"&gt;
    357             &lt;domain includeSubdomains="true"&gt;secure.example.com&lt;/domain&gt;
    358         &lt;/domain-config&gt;
    359     &lt;/domain-config&gt;
    360 &lt;/network-security-config&gt;
    361 </pre>
    362 </p>
    363 
    364 
    365 <h2 id="FileFormat">Configuration File Format</h2>
    366 
    367 <p>
    368   The Network Security Configuration feature uses an XML file format.
    369   The overall structure of the file is shown in the following code sample:
    370 </p>
    371 
    372 <pre>
    373 &lt;?xml version="1.0" encoding="utf-8"?&gt;
    374 &lt;network-security-config&gt;
    375     &lt;base-config&gt;
    376         &lt;trust-anchors&gt;
    377             &lt;certificates src="..."/&gt;
    378             ...
    379         &lt;/trust-anchors&gt;
    380     &lt;/base-config&gt;
    381 
    382     &lt;domain-config&gt;
    383         &lt;domain&gt;android.com&lt;/domain&gt;
    384         ...
    385         &lt;trust-anchors&gt;
    386             &lt;certificates src="..."/&gt;
    387             ...
    388         &lt;/trust-anchors&gt;
    389         &lt;pin-set&gt;
    390             &lt;pin digest="..."&gt;...&lt;/pin&gt;
    391             ...
    392         &lt;/pin-set&gt;
    393     &lt;/domain-config&gt;
    394     ...
    395     &lt;debug-overrides&gt;
    396         &lt;trust-anchors&gt;
    397             &lt;certificates src="..."/&gt;
    398             ...
    399         &lt;/trust-anchors&gt;
    400     &lt;/debug-overrides&gt;
    401 &lt;/network-security-config&gt;
    402 </pre>
    403 
    404 <p>
    405   The following sections describe the syntax and other details of the file
    406   format.
    407 </p>
    408 
    409 <h3 id="network-security-config">
    410   &lt;network-security-config&gt;
    411 </h3>
    412 
    413 <dl class="xml">
    414   <dt>
    415     can contain:
    416   </dt>
    417 
    418   <dd>
    419     0 or 1 of <code><a href="#base-config">&lt;base-config&gt;</a></code><br>
    420     Any number of <code><a href=
    421     "#domain-config">&lt;domain-config&gt;</a></code><br>
    422     0 or 1 of <code><a href="#debug-overrides">&lt;debug-overrides&gt;</a></code>
    423   </dd>
    424 </dl>
    425 
    426 <h3 id="base-config">
    427   &lt;base-config&gt;
    428 </h3>
    429 
    430 <dl class="xml">
    431   <dt>
    432     syntax:
    433   </dt>
    434 </dl>
    435 
    436 <pre class="stx">
    437 &lt;base-config <a href=
    438 "#CleartextTrafficPermitted">cleartextTrafficPermitted</a>=["true" | "false"]&gt;
    439     ...
    440 &lt;/base-config&gt;
    441 </pre>
    442 <dl class="xml">
    443   <dt>
    444     can contain:
    445   </dt>
    446 
    447   <dd>
    448     <code><a href="#trust-anchors">&lt;trust-anchors&gt;</a></code>
    449   </dd>
    450 
    451   <dt>
    452     description:
    453   </dt>
    454 
    455   <dd>
    456     The default configuration used by all connections whose destination is not
    457     covered by a <a href="#domain-config"><code>domain-config</code></a>.
    458 
    459 <p>
    460   Any values that are not set use the platform default values. The default
    461   configuration for apps targeting Android 7.0 (API level 24) and higher is as
    462   follows:
    463 </p>
    464 
    465 <pre>
    466 &lt;base-config cleartextTrafficPermitted="true"&gt;
    467     &lt;trust-anchors&gt;
    468         &lt;certificates src="system" /&gt;
    469     &lt;/trust-anchors&gt;
    470 &lt;/base-config&gt;
    471 </pre>
    472 The default configuration for apps targeting Android 6.0 (API level 23) and
    473 lower is as follows:
    474 <pre>
    475 &lt;base-config cleartextTrafficPermitted="true"&gt;
    476     &lt;trust-anchors&gt;
    477         &lt;certificates src="system" /&gt;
    478         &lt;certificates src="user" /&gt;
    479     &lt;/trust-anchors&gt;
    480 &lt;/base-config&gt;
    481 </pre>
    482 
    483   </dd>
    484 </dl>
    485 
    486 <h3 id="domain-config">&lt;domain-config&gt;</h3>
    487 <dl class="xml">
    488 <dt>syntax:</dt>
    489 <dd>
    490 <pre class="stx">&lt;domain-config <a href="#CleartextTrafficPermitted">cleartextTrafficPermitted</a>=["true" | "false"]&gt;
    491     ...
    492 &lt;/domain-config&gt;</pre>
    493 </dd>
    494 
    495 <dt>Can Contain:</dt>
    496 
    497 <dd>
    498 1 or more <code><a href="#domain">&lt;domain&gt;</a></code>
    499 <br/>0 or 1 <code><a href="#trust-anchors">&lt;trust-anchors&gt;</a></code>
    500 <br/>0 or 1 <code><a href="#pin-set">&lt;pin-set&gt;</code></a>
    501 <br/>Any number of nested <code>&lt;domain-config&gt;</code></dd>
    502 
    503 <dt>Description</dt>
    504 <dd>Configuration used for connections to specific destinations, as defined by
    505 the {@code domain} elements.
    506 
    507 <p>Note that if multiple {@code domain-config} elements cover a destination, the
    508 configuration with the most specific (longest) matching domain rule is
    509 used.</p></dd>
    510 </dl>
    511 
    512 <h3 id="domain">&lt;domain&gt;</h3>
    513 
    514 <dl class="xml">
    515   <dt>
    516     syntax:
    517   </dt>
    518 
    519   <dd>
    520     <pre class="stx">
    521 &lt;domain includeSubdomains=["true" | "false"]&gt;example.com&lt;/domain&gt;
    522 </pre>
    523   </dd>
    524 
    525   <dt>
    526     Attributes:
    527   </dt>
    528 
    529   <dd>
    530     <dl class="attr">
    531       <dt>
    532         {@code includeSubdomains}
    533       </dt>
    534 
    535       <dd>
    536         If {@code "true"}, then this domain rule matches the domain and all
    537         subdomains, including subdomains of subdomains. Otherwise, the rule only
    538         applies to exact matches.
    539       </dd>
    540     </dl>
    541   </dd>
    542 
    543   <dt>
    544     Description:
    545   </dt>
    546 </dl>
    547 
    548 <h3 id="debug-overrides">&lt;debug-overrides&gt;</h3>
    549 
    550 <dl class="xml">
    551   <dt>
    552     syntax:
    553   </dt>
    554 
    555   <dd>
    556     <pre class="stx">
    557 &lt;debug-overrides&gt;
    558     ...
    559 &lt;/debug-overrides&gt;
    560 </pre>
    561   </dd>
    562 
    563   <dt>
    564     Can Contain:
    565   </dt>
    566 
    567   <dd>
    568     0 or 1 <code><a href="#trust-anchors">&lt;trust-anchors&gt;</a></code>
    569   </dd>
    570 
    571   <dt>
    572     Description:
    573   </dt>
    574 
    575   <dd>
    576     Overrides to be applied when <a href=
    577     "{@docRoot}guide/topics/manifest/application-element.html#debug">android:debuggable</a>
    578     is {@code "true"}, which is normally the case for non-release builds
    579     generated by IDEs and build tools. Trust anchors specified in {@code
    580     debug-overrides} are added to all other configurations, and certificate
    581     pinning is not performed when the server's certificate chain uses one of
    582     these debug-only trust anchors. If <a href=
    583     "{@docRoot}guide/topics/manifest/application-element.html#debug">android:debuggable</a>
    584     is {@code "false"}, then this section is completely ignored.
    585   </dd>
    586 </dl>
    587 
    588 <h3 id="trust-anchors">&lt;trust-anchors&gt;</h3>
    589 <dl class="xml">
    590   <dt>
    591     syntax:
    592   </dt>
    593 
    594   <dd>
    595     <pre class="stx">
    596 &lt;trust-anchors&gt;
    597 ...
    598 &lt;/trust-anchors&gt;
    599 </pre>
    600   </dd>
    601 
    602   <dt>
    603     Can Contain:
    604   </dt>
    605 
    606   <dd>
    607     Any number of <code><a href="#certificates">&lt;certificates&gt;</a></code>
    608   </dd>
    609 
    610   <dt>
    611     Description:
    612   </dt>
    613 
    614   <dd>
    615     Set of trust anchors for secure connections.
    616   </dd>
    617 </dl>
    618 
    619 
    620 <h3 id="certificates">&lt;certificates&gt;</h3>
    621 <dl class="xml">
    622 <dt>syntax:</dt>
    623 <dd><pre class="stx">&lt;certificates src=["system" | "user" | "<i>raw resource</i>"]
    624               overridePins=["true" | "false"] /&gt;
    625 </pre></dd>
    626 <dt>description:</dt>
    627 <dd>Set of X.509 certificates for {@code trust-anchors} elements.</dd>
    628 
    629 <dt>attributes:</dt>
    630 <dd><dl class="attr">
    631 <dt>{@code src}</dt>
    632 <dd>
    633 The source of CA certificates. Each certificate can be one of the following:
    634 <ul>
    635   <li>a raw resource ID pointing to a file containing X.509 certificates.
    636   Certificates must be encoded in DER or PEM format. In the case of PEM
    637   certificates, the file <em>must not</em> contain extra non-PEM data such as
    638   comments.
    639   </li>
    640 
    641   <li>{@code "system"} for the pre-installed system CA certificates
    642   </li>
    643 
    644   <li>{@code "user"} for user-added CA certificates
    645   </li>
    646 </ul>
    647 </dd>
    648 
    649 <dt>{@code overridePins}</dt>
    650 <dd>
    651   <p>
    652     Specifies if the CAs from this source bypass certificate pinning. If {@code
    653     "true"}, then pinning is not performed on certificate chains which are
    654     signed by one of the CAs from this source. This can be useful for debugging
    655     CAs or for testing man-in-the-middle attacks on your app's secure traffic.
    656   </p>
    657 
    658   <p>
    659     Default is {@code "false"} unless specified in a {@code debug-overrides}
    660     element, in which case the default is {@code "true"}.
    661   </p>
    662 </dd>
    663 </dl>
    664 </dd>
    665 
    666 
    667 <h3 id="pin-set">&lt;pin-set&gt;</h3>
    668 
    669 <dl class="xml">
    670   <dt>
    671     syntax:
    672   </dt>
    673 
    674   <dd>
    675 <pre class="stx">
    676 &lt;pin-set expiration="date"&gt;
    677 ...
    678 &lt;/pin-set&gt;
    679 </pre>
    680   </dd>
    681 
    682   <dt>
    683     Can Contain:
    684   </dt>
    685 
    686   <dd>
    687     Any number of <code><a href="#pin">&lt;pin&gt;</a></code>
    688   </dd>
    689 
    690   <dt>
    691     Description:
    692   </dt>
    693 
    694   <dd>
    695     A set of public key pins. For a secure connection to be trusted, one of the
    696     public keys in the chain of trust must be in the set of pins. See
    697     <code><a href="#pin">&lt;pin&gt;</a></code> for the format of pins.
    698   </dd>
    699 
    700   <dt>
    701     Attributes:
    702   </dt>
    703 
    704   <dd>
    705     <dl class="attr">
    706       <dt>
    707         {@code expiration}
    708       </dt>
    709 
    710       <dd>
    711         The date, in {@code yyyy-MM-dd} format, on which the pins expire, thus
    712         disabling pinning. If the attribute is not set, then the pins do not
    713         expire.
    714         <p>
    715           Expiration helps prevent connectivity issues in apps which do not get
    716           updates to their pin set, such as when the user disables app updates.
    717         </p>
    718       </dd>
    719     </dl>
    720   </dd>
    721 </dl>
    722 
    723 <h3 id="pin">&lt;pin&gt;</h3>
    724 <dl class="xml">
    725   <dt>
    726     syntax:
    727   </dt>
    728 
    729   <dd>
    730 <pre class="stx">
    731 &lt;pin digest=["SHA-256"]&gt;base64 encoded digest of X.509
    732     SubjectPublicKeyInfo (SPKI)&lt;/pin&gt;
    733 </pre>
    734   </dd>
    735 
    736   <dt>
    737     Attributes:
    738   </dt>
    739 
    740   <dd>
    741     <dl class="attr">
    742       <dt>
    743         {@code digest}
    744       </dt>
    745 
    746       <dd>
    747         The digest algorithm used to generate the pin. Currently, only
    748         {@code "SHA-256"} is supported.
    749       </dd>
    750     </dl>
    751   </dd>
    752 </dl>
    753