--- a/Overview.html Mon Jul 08 15:18:28 2013 -0400
+++ b/Overview.html Fri Jul 12 15:13:11 2013 -0400
@@ -54,7 +54,7 @@
wg: "Web Cryptography Working Group",
// URI of the public WG page
- wgURI: "http://example.org/really-cool-wg",
+ wgURI: "http://www.w3.org/2012/webcrypto/",
// name (without the @w3c.org) of the public mailing to which comments are due
wgPublicList: "public-webcrypto",
@@ -70,14 +70,14 @@
</head>
<body>
<section id='abstract'>
- This document is NOT a recommendation track document, and should be read as an informative overview of the target use cases for a cryptographic API for the web. These use cases, described as scenarios, represent some of the set of expected functionality that may be achieved by the Web Cryptography API [[!WEBCRYPTO]] which provides an API for cryptographic operations such as encryption and decryption, and the Key Discovery API [[!KEY-DISCOVERY]], which specifically covers the ability to access cryptographic keys that have been pre-provisioned. As both APIs are under construction, the reader should consult each specification for changes, and should treat sample code provided here as illustrative only. Presented here are primary use cases, showing what the working group hopes to achieve first.
+ This document is NOT a recommendation track document, and should be read as an informative overview of the target use cases for a cryptographic API for the web. These use cases, described as scenarios, represent some of the set of expected functionality that may be achieved by the Web Cryptography API [[WebCryptoAPI]] which provides an API for cryptographic operations such as encryption and decryption, and the Key Discovery API [[webcrypto-key-discovery]], which specifically covers the ability to access cryptographic keys that have been pre-provisioned. As both APIs are under construction, the reader should consult each specification for changes, and should treat sample code provided here as illustrative only. Presented here are primary use cases, showing what the working group hopes to achieve first.
</section>
<section id='nonGoals'>
<h2>Some Non-Goals</h2>
- <p>Certain popular use cases for cryptography on the web do not correspond to the combined capabilities of the Key Discovery API [[!KEY-DISCOVERY]] or the Web Cryptography API [[!WEBCRYPTO]], and these use cases are not addressed here. These include:
+ <p>Certain popular use cases for cryptography on the web do not correspond to the combined capabilities of the Key Discovery API [[webcrypto-key-discovery]] or the Web Cryptography API [[WebCryptoAPI]], and these use cases are not addressed here. These include:
</p>
<ol>
- <li><p>Any use case requiring a relaxation or violation of the same-origin policy in JavaScript, implemented by all the major web browsers. This includes use cases that require direct access to cryptographic material that is not domain-specific from a key store that is not domain specific. Currently, certain banking transactions require citizens to obtain certificates that are centrally issued, and that are user specific yet not domain specific, and that are used by multiple institutions, each having separate domains, each of which can call upon a hardware-based cryptographic material store. Such use cases aren't directly addressed by the combination of the Web Cryptography API [[!WEBCRYPTO]] or the Key Discovery API [[!KEY-DISCOVERY]]. Instead, use cases that require cryptographic material to be shared between domains can leverage cross-origin messaging and the structured clonability of keys, or the importing and exporting of cryptographic keys across domains; such use cases are covered in this document. Another use case not addressed here for the same reason is the case of a centrally issued electronic identity (eID) that exposes a certificate chain to web applications for use with digital signatures.</p> </li>
+ <li><p>Any use case requiring a relaxation or violation of the same-origin policy in JavaScript, implemented by all the major web browsers. This includes use cases that require direct access to cryptographic material that is not domain-specific from a key store that is not domain specific. Currently, certain banking transactions require citizens to obtain certificates that are centrally issued, and that are user specific yet not domain specific, and that are used by multiple institutions, each having separate domains, each of which can call upon a hardware-based cryptographic material store. Such use cases aren't directly addressed by the combination of the Web Cryptography API [[WebCryptoAPI]] or the Key Discovery API [[webcrypto-key-discovery]]. Instead, use cases that require cryptographic material to be shared between domains can leverage cross-origin messaging and the structured clonability of keys, or the importing and exporting of cryptographic keys across domains; such use cases are covered in this document. Another use case not addressed here for the same reason is the case of a centrally issued electronic identity (eID) that exposes a certificate chain to web applications for use with digital signatures.</p> </li>
<li><p>Any use case that expressly requires the use of auxiliary cryptographic hardware, including smart cards or USB dongles. Other standardization activities may provide mechanisms for these technologies to interact with web applications, but such use cases fall beyond the scope of this document. Examples of this type of use case include "advanced electronic signatures" which rely on certificates issued on secure hardware by certifying authorities, typically acting under the aegis of state governments.</p></li>
</ol>
</section>
@@ -93,8 +93,8 @@
<li><p><dfn title="decrypt" id="decrypt">DECRYPT</dfn>, the ability to decrypt a digitally signed document. <dfn id="decrypt-sym">DECRYPT-SYM</dfn> is a specific type of decryption using symmetric keys, and <dfn id="decrypt-assym">DECRYPT-ASSYM</dfn> is a specific type of decryption using assymetric keys, typically a public and private key pair.</p></li>
<li><p><dfn title="derive" id="derive">DERIVE</dfn>, the ability to derive a key or key pair used in cryptographic operations, starting with a base key, and factors such as algorithms appropriate for key derivation; <dfn id="derive-assym">DERIVE-ASSYM</dfn> is the ability to derive assymetric keys, typically a public and private key pair, for use with assymetric cryptographic operations, and <dfn id="derive-sym">DERIVE-SYM</dfn> is the ability to derive a symmetric key for use with symmetric cryptographic operations.</p></li>
<li><p><dfn title="keygen" id="keygen">KEYGEN</dfn>, the ability to generate a key or key pair used in cryptographic operations, without an initial base key, and using factors such as the entropy of the computing system and algorithms appropriate for key or key pair generation; <dfn id="keygen-assym">KEYGEN-ASSYM</dfn> is the ability to generate assymetric keys, typically a public and private key pair, for use with assymetric cryptographic operations, and <dfn id="keygen-sym">KEYGEN-SYM</dfn> is the ability to derive a symmetric key for use with symmetric cryptographic operations.</p></li>
- <li><p><dfn title="import" id="import">IMPORT</dfn>, the ability to import a key or key pair that have already been created elsewhere, for use within the web application that is invoking the import function, for use within the importing web application's origin. This necessiates an interoperable key format, such as JSON Web Key [[!JWK]] which may be represented as octets.</p></li>
- <li><p><dfn title="export" id="export">EXPORT</dfn>, the ability to export a key or key pair that can be accessed from within the application that is invoking the export function. This necessiates an interoperable key format, such as JSON Web Key [[!JWK]] which may be represented as octets, that other web applications can then import.</p></li>
+ <li><p><dfn title="import" id="import">IMPORT</dfn>, the ability to import a key or key pair that have already been created elsewhere, for use within the web application that is invoking the import function, for use within the importing web application's origin. This necessiates an interoperable key format, such as JSON Web Key [[JWK]] which may be represented as octets.</p></li>
+ <li><p><dfn title="export" id="export">EXPORT</dfn>, the ability to export a key or key pair that can be accessed from within the application that is invoking the export function. This necessiates an interoperable key format, such as JSON Web Key [[JWK]] which may be represented as octets, that other web applications can then import.</p></li>
<li><p><dfn title="keyex" id="keyex">KEYEX</dfn>, the ability for two entities to exchange key(s) without interception by a third party, with <dfn id="keyex-dh">KEYEX-DH</dfn> representing Diffie-Hellman key exchange, a common application of safe key exchange. </p>
<div class="note">This feature doesn't imply that every aspect of key exchange is covered, since much of key exchange often includes a network component, which isn't covered by the API. The <a title="derive">DERIVE</a> feature, coupled with an a network exchange of key data outside the scope of this API, may be all that is required.</div>
</li>
@@ -102,25 +102,25 @@
<li><p><dfn title="sym" id="sym">-SYM</dfn>, an abbreviation for <em>symmetric key cryptographic operations</em>, used in this document as a suffix to other features to specifically clarify the feature being invoked by the web application.</p></li>
<li><p><dfn title="assym" id="assym">-ASSYM</dfn>, an abbreviation for <em>assymetric key cryptographic operations</em>, typically involving a public and private key pair, used in this document as a suffix to other features to specifically clarify the feature being invoked by the web application.</p></li>
<li><p><dfn title="random" id="random">RANDOM</dfn>, the ability to generate cryptographically secure random numbers.</p></li>
- <li><p><dfn title="JSONWebKey" id="JSONWebKey">JWK</dfn>, the ability to represent public keys in the JSON Web Key format [[!JWK]]. JWK keys can be imported [<a title="import">IMPORT</a>] and exported [<a title="export">EXPORT</a>].</p></li>
+ <li><p><dfn title="JSONWebKey" id="JSONWebKey">JWK</dfn>, the ability to represent public keys in the JSON Web Key format [[JWK]]. JWK keys can be imported [<a title="import">IMPORT</a>] and exported [<a title="export">EXPORT</a>].</p></li>
<li><p><dfn title="wrap" id="wrap">WRAP</dfn> which allows a web application to use a key to <em>wrap another key</em>, so that the wrapped key can be unwrapped by a party with the corresponding wrapping key. While it is possible to create a key-wrapping and unwrapping mechanism with the other features listed, this feature provides a way to do so without exposing the key to be wrapped to JavaScript. <dfn title="wrap-sym" id="wrap-sym">WRAP-SYM</dfn> refers to symmetric key wrapping, and <dfn title="wrap-assym">WRAP-ASSYM</dfn> refers to assymetric key wrapping.</p>
<li><p><dfn id="unwrap">UNWRAP</dfn> which allows a web application to use a key to unwrap another encrypted key or key pair, which can then be used in standard cryptographic operations. While it is possible to create a key-wrapping and unwrapping mechanism with the other features listed, this feature provides a way to do so without exposing the key to be wrapped to JavaScript. <dfn id="unwrap-sym" title="unwrap-sym">UNWRAP-SYM</dfn> refers to symmetric unwrapping, and <dfn id="unwrap-assym" title="unwrap-assym">UNWRAP-ASSYM</dfn> refers to assymetric unwrapping.</p>
<div class="issue"><p>This feature is subject to discussion. See <a href="https://www.w3.org/2012/webcrypto/track/issues/35">ISSUE-35</a> logged by the WebCrypto WG.</p></div>
</li>
<li><p><dfn id="namedkey">NAMEDKEY</dfn> which allows an application in JavaScript to discover a <dfn id="pre-prov">pre-provisioned</dfn> key within the scope of the application's origin, which exists at the time of the application's first invocation, and has not been derived, generated or imported by the application using any of the features listed above; such keys may have been provisioned by a device manufacturer, for example, and the JavaSript application can access them for initial authorization and authentication at time of first invocation. </p>
- <div class="note"><p>This feature is developed in the Key Discovery API [[!KEY-DISCOVERY]].</p></div>
+ <div class="note"><p>This feature is developed in the Key Discovery API [[webcrypto-key-discovery]].</p></div>
</li>
</ul>
</section>
<section>
<h2>Use Case Scenarios</h2>
- <p>This section collates use case scenarios that leverages the WebCrypto API [[!WEBCRYPTO]] or the Key Discovery API [[!KEY-DISCOVERY]]; in particular, these use cases leverage all the features listed above as <a href="#reqs">requirements</a>. Where possible, sample code is provided, and should be considered illustrative only, since the underlying API specifications are changing.</p>
+ <p>This section collates use case scenarios that leverages the WebCrypto API [[WebCryptoAPI]] or the Key Discovery API [[webcrypto-key-discovery]]; in particular, these use cases leverage all the features listed above as <a href="#reqs">requirements</a>. Where possible, sample code is provided, and should be considered illustrative only, since the underlying API specifications are changing.</p>
<section>
<h3>Banking Transactions</h3>
<p>Park Jae-sang opens up a bank account with Gangnam Bank, and wishes to log-in and engage in online transactions, including account balance checking, online payments (with some automated scheduled payments), and account transfers between domestic and investment accounts. The first time Park logs in to the Gangnam Bank website (abbreviated "GB") with a temporary verification code sent to his cell phone, the bank asks him to ascertain if the browser he is using is not at a kiosk; moreover, he is asked if it is a web browser and machine configuration he will use often.</p>
- <p>He confirms that it is. The GB web site then asks him to generate a public key/private key pair. Park consents, and the web page creates the key pair, storing his private key in the browser's designated key store, along with a one-time key escrow by the bank. Additionally, Jae-sang is presented with the bank's public key, such that documents issued by the bank can be verified and decrypted; Jae-sang presents the derived public key to GB. Jae-sang is also presented with a user guide that explains the validity period of the key pair, and for how long they will persist. [<a title="keygen">KEYGEN-ASSYM</a> .</p>
- <p>GB may first generate some key pair for Jae-sang. These include the public key/private key which will be used for digital signatures. </p>
+ <p>He confirms that it is. The GB web site then generates a public key/private key pair and stores the key pair in client-side storage, along with a one-time key escrow by the bank. Additionally, Jae-sang is presented with the bank's public key, such that documents issued by the bank can be verified and decrypted. Jae-sang is also presented with a user guide that explains the validity period of the key pair, and for how long they will persist. [<a title="keygen">KEYGEN-ASSYM</a>].</p>
+ <p>GB may generate assymetric keys as in the example below. </p>
<pre class="example hightlight prettyprint">
@@ -136,19 +136,18 @@
window.crypto.subtle.generateKey(algorithmKeyGen, false, ["sign"]).then(
- function(key)
+ function(keyPair)
{
// Store the key pair in IndexedDB
},
- console.error.bind(console, "Unable to generate key -- call your Banker or retry later."));
+ console.error.bind(console, "Unable to generate keys -- call your Banker or retry later."));
</pre>
-<p>GB may then use a key exchange mechanism to exchange keys with the server over TLS. This includes making sure that the client (Jae-sang) obtains a copy of GB's public key, and that GB obtains a copy of Jae-sang's public key, which were generated in the preceding step. </p>
-<p>Subsequent access to the GB website -- always over TLS -- is triggered via use of the key that Jae-sang generated when he first accessed the website. JavaScript initially loaded by GB contains a message that only Jae-sang can decipher, since it is encrypted with his public key; moreover, that message is signed by GB, which gives the client confidence that the message originates from GB. The message is deciphered, and the deciphered message is then digitally signed and sent back to the GB server. </p>
+<p>Subsequent access to the GB website -- always over TLS -- may use keypairs for Jae-sang generated by GB. For instance, JavaScript initially loaded by GB may contain a message that only Jae-sang can decipher, since it is encrypted with his public key; moreover, that message is signed by GB, which gives Jae-sang confidence that the message originates from GB, whose public key is used to verify signed messages by GB. The message is deciphered, and the deciphered message is then digitally signed and sent back to the GB server. </p>
<p> [<a title="keycall">KEYCALL</a> | <a title="verify">VERIFY</a> | <a title="decrypt-assym">DECRYPT-ASSYM</a> | <a title="sign">SIGN</a>]</p>
-<p>In the example below, an encrypted message is signed by GB. The signature is verified, and upon successful verfication, is decrypted. The decrypted message is then processed. This example should be seen as a simplification for illustrative purposes only. </p>
-<div class="issue"><p>Semantics of the verify operation are still TBD in the group. TODO: create another example using WRAP/UNWRAP.</p></div>
+<p>In the example below, an encrypted message is signed by GB. The signature is verified, and upon successful verification of the digital signature, the encrypted message is decrypted. The decrypted message is then processed. This example should be seen as a simplification for illustrative purposes only. </p>
+<div class="issue"><p>Semantics of the verify operation are still TBD in the group. Moreover, some of this is best demonstrated using WRAP/UNWRAP, which still has unstable semantics. TODO: create another example using WRAP/UNWRAP.</p></div>
<pre class="example highlight prettyprint">
// Encrypted and Signed Message generated by GB... the ellipsis are added.
@@ -202,7 +201,7 @@
);
</pre>
<p>
-His browser presents this key every time he accesses the website and enters his password, which effectively binds his username and password to the generated private key. Additionally, Jae-sang can digitally sign online checks, authorize payments, and sign tax forms that he submits to the bank site using this generated key [<a href="sign">SIGN</a>]. He can also perform the following tasks, following an authentication cycle such as the one described above:</p>
+As long as Jae-sang uses the same browser, within the validity period of the keys that he generated, he can use them as credentials by signing, verifying, encrypting and decrypting bits of data sent by GB. Additionally, Jae-sang can digitally sign online checks, authorize payments, and sign tax forms that he submits to the bank site using similarly generated assymetric keys. He can also perform the following tasks:</p>
<ol>
<li>Submit documents to GB that only GB can read, with the assurance that these have come from Jae-sang. Such documents include confidential financial information, and may be encrypted at submission. This can follow the well-understood pattern of wrapping keys using assymetric encryption, but encrypting and decrypting larger documents using symmetric encryption. [<a title="sign">SIGN</a> | <a title="derive-sym">DERIVE-SYM</a> | <a title="encrypt-sym">ENCRYPT-SYM</a> | <a title="wrap">WRAP-ASSYM</a>]</li>
<li>Receive encrypted documents from GB that only he can read, with the assurance that they have come from GB and only GB. These include his private bank statements and tax documents, which are signed with his public key, already generated and obtained by GB in a previous step. [<a title="verify">VERIFY</a> | <a title="unwrap">UNWRAP-ASSYM</a> | <a title="decrypt-sym">DECRYPT-SYM</a>]</li>
@@ -216,8 +215,8 @@
Ryan has just bought a new TV and wishes to watch video content from the service provider. He connects the TV to the Internet, and navigates to the video provider's website. The video provider's site establishes a secure communication channel between the video provider's page on the TV and the video provider's servers, proving to the servers that Ryan's TV is indeed one of those that meets the security requirements by use of the cryptographic key and identifier pre-provisioned on the TV. The video provider's page on the TV likewise verifies that it is talking to a genuine server, preventing the hijacking of Ryan's video watching by a malicious third party. To ensure the highest security, the pre-provisoned key is used minimally in this process to deliver session keys.
</p>
-<p>[<a title="namedkey">NAMEDKEY</a> | <a title="verify">VERIFY</a> | <a title="unwrap">UNWRAP</a> | <a title="mac">MAC</a> | <a title="encrypt-sym">ENCRYPT-SYM</a> | <a title="decrypt-sym">DECRYPT-SYM></a> | <a title="sign">SIGN</a>]</p>
-<p>The Key Discovery API describes the provides a mechanism for an application in JavaScript to detect the presence of a pre-provisioned key using the name of a disclosed identifier. </p>
+<p>[<a title="namedkey">NAMEDKEY</a> | <a title="verify">VERIFY</a> | <a title="unwrap">UNWRAP</a> | <a title="mac">MAC</a> | <a title="encrypt-sym">ENCRYPT-SYM</a> | <a title="decrypt-sym">DECRYPT-SYM</a> | <a title="sign">SIGN</a>]</p>
+<p>The Key Discovery API [[webcrypto-key-discovery]] describes the provides a mechanism for an application in JavaScript to detect the presence of a pre-provisioned key using the name of a disclosed identifier. </p>
<pre class="example highlight prettyprint">
var keys = window.getKeysByName("VetFlxL33t_Device.p1a.b11");
keys.onerror = function(e){
@@ -288,7 +287,7 @@
<h2>Encrypted Communications via Webmail</h2>
<p>Tantek wishes to communicate with Ryan securely. Moreover, Tantek wishes to use an email web application (EWA) provided by a third party, which is a web site that allows users who have accounts to set up email accounts of their own choosing -- that is, users can enter in existing POP/IMAP/SMTP username and password credentials, or simply use an email address provided by the EWA at its own address. The EWA serves to send messages, as well as provide a message store available from anywhere. It allows for the possibility of sending encrypted messages.</p>
<p>Ryan provides a PGP key on his website, encoded in the relevant conventions. For instance, he follows the common practice of including a Base64 text string that represents his public key.</p>
- <p>Ryan uses the [hCard] format to encapsulate contact information with some semantic annotation within the markup of his webpage. Within the [hCard], he does something like this:</p>
+ <p>Ryan uses the hCard format [[hCard]] to encapsulate contact information with some semantic annotation within the markup of his webpage. Within the hCard ([[hCard]]), he does something like this:</p>
<pre class="example highlight prettyprint">
<span class="key">
@@ -302,8 +301,8 @@
</span>
</pre>
-<p>Logging on to EWA, Tantek is prompted to import Ryan's contact information from his web page, and is notified that Ryan's public key will also be imported. EWA then begins the process of importing Ryan's PGP key, since it understands how to parse public keys within hCard content (see also key examples). In order to import the key for storage under EWA's origin, it must first "scrub" the key format to be in one of the accepted import formats of the WebCrypto API.</p>
-<p>Here, a standardized Contacts API could be used to procure Ryan's contact information, and can be one way of importing the key for use by an application such as EWA. Due the same origin policy [[!HTML]], EWA must import the key, so that operations conducted with it fall under the domain of EWA. The key is converted to JSON Web Key format [[!JWK]], which the WebCrypto API accepts and then import it for use within the web application.</p>
+<p>Logging on to EWA, Tantek is prompted to import Ryan's contact information from his web page, and is notified that Ryan's public key will also be imported. EWA then begins the process of importing Ryan's PGP key, since it understands how to parse public keys within hCard content in markup. In order to import the key for storage under EWA's origin, it must first "scrub" the key format to be in one of the accepted import formats of the WebCrypto API.</p>
+<p>Here, a standardized Contacts API could be used to procure Ryan's contact information, and can be one way of importing the key for use by an application such as EWA. Due the same origin policy [[HTML]], EWA must import the key, so that operations conducted with it fall under the domain of EWA. The key is converted to JSON Web Key format [[JWK]], which the WebCrypto API accepts and then imports it for use within the web application.</p>
<pre class="example highlight prettyprint">
/**
1. First convert the PGP key format into an "importable" format by the WebCrypto API; assume "keyString" is the PGP format
@@ -369,19 +368,19 @@
<section>
<h2>BrowserID: Use of Cryptography for Identity Protocols</h2>
<p>
-Karen, an avid photographer, has been looking for a site to store all the photos that she posts on various websites. Instead of creating yet another online identity for another photo storage website, Karen is pleased to find a photo-storage service that uses the BrowserID protocol [[!BrowserID]], allowing her to use any email address as an identity. The photo-storage service (PSS) is a <em>Relying Party</em> of the protocol, and Karen elects to use Persona.org as an <em>Identity Provider</em>, since she sees a "log-in with Persona" button on the PSS website. She notes that her preferred email provider is not yet an Identity Provider for use with BrowserID [[!BrowserID]], and thus uses Persona.org as a fallback option.
+Karen, an avid photographer, has been looking for a site to store all the photos that she posts on various websites. Instead of creating yet another online identity for another photo storage website, Karen is pleased to find a photo-storage service that uses the BrowserID protocol [[BrowserID]], allowing her to use any email address as an identity. The photo-storage service (PSS) is a <em>Relying Party</em> of the protocol, and Karen elects to use Persona.org as an <em>Identity Provider</em>, since she sees a "log-in with Persona" button on the PSS website. She notes that her preferred email provider is not yet an Identity Provider for use with BrowserID [[BrowserID]], and thus uses Persona.org as a fallback option.
</p>
<p>
Karen first creates a "verified email" identity with Persona.org. Persona.org sends out an email with a hyperlink in it to an email address that she chooses to use as one of her identities (she chooses "karen@webcrypto.com"), especially for use with PSS. She then logs in to this email account and clicks on the verification link sent by Persona.org. Persona.org is thus able to determine that Karen owns this email address. The following now happens:</p>
<ol>
<li><p>Persona.org creates assymetric keys, public and private, on behalf of the user. [<a title="keygen-assym">KEYGEN-ASSYM</a>]</p></li>
-<li><p>Persona.org's web page then sends the public key just created over TLS for storage on Persona.org's servers, and stores the keypair in the browser's client-side storage. This could include [[!INDEXEDDB]] and <code>localStorage</code>, although in browsers with a native implementation of BrowserID [[!BrowserID]], this might include another key store.</p></li>
-<li><p>Persona.org then generates a certificate, which involves signing the public key just created, the email address, and a validity interval; the signature here is performed by Persona.org. This certificate takes the form of a [[!JWT]] object. The [[!JWT]] object -- the certificate created above -- is itself stored in the browser's client storage, which can be [[!INDEXEDDB]] or <code>localStore</code>; if the browser implementation has a native implementation of [[!BrowserID]], another key and certificate store could exist. [<a title="keycall">KEYCALL</a> | <a title="sign">SIGN</a>]</p></li>
+<li><p>Persona.org's web page then sends the public key just created over TLS for storage on Persona.org's servers, and stores the keypair in the browser's client-side storage. This could include [[INDEXEDDB]] and <code>localStorage</code>, although in browsers with a native implementation of BrowserID [[BrowserID]], this might include another key store.</p></li>
+<li><p>Persona.org then generates a certificate, which involves signing the public key just created, the email address, and a validity interval; the signature here is performed by Persona.org. This certificate takes the form of a [[JWT]] object. The [[JWT]] object -- the certificate created above -- is itself stored in the browser's client storage, which can be [[INDEXEDDB]] or <code>localStore</code>; if the browser implementation has a native implementation of [[BrowserID]], another key and certificate store could exist. [<a title="keycall">KEYCALL</a> | <a title="sign">SIGN</a>]</p></li>
</ol>
<p>Karen now has at least one identity, namely her email of choice, verified on Persona.org, along with a certificate issued by Persona.org. She then decides to log in to the PSS website using that identity. The following sequence then takes place:</p>
<ol>
-<li><p>Karen accesses the website of the PSS, and then clicks on the "Log in with Persona" link. The log-in link loads script from Persona.org in an <code>iframe</code>, which creates an assertion structure as a JWT [[!JWT]]. The assertion consists of the name of the Relying Party, also referred to as an <em>audience</em>, and a validity period. This assertion is signed using the private key that was created previously. [<a title="keycall">KEYCALL</a> | <a title="sign">SIGN</a>]</p></li>
-<li>The signed assertion is then combined with the certificate created previously into a new [[!JWT]] structure, which might look like this:
+<li><p>Karen accesses the website of the PSS, and then clicks on the "Log in with Persona" link. The log-in link loads script from Persona.org in an <code>iframe</code>, which creates an assertion structure as a JWT [[JWT]]. The assertion consists of the name of the Relying Party, also referred to as an <em>audience</em>, and a validity period. This assertion is signed using the private key that was created previously. [<a title="keycall">KEYCALL</a> | <a title="sign">SIGN</a>]</p></li>
+<li>The signed assertion is then combined with the certificate created previously into a new [[JWT]] structure, which might look like this:
<pre class="example highlight prettyprint">
// This is for illustrative purposes only
// Proper use of JWT uses Base64