-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
173 lines (163 loc) · 6.99 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
<!DOCTYPE html>
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
</head>
<body>
<a
id="forkme_banner"
href="https://github.com/unobvious-technology/experiment-webcrypto-keypairs"
>View on GitHub</a
>
<div id="app">
<h1>Public/Private Keypair with Password Encryption</h1>
<p>
<em>
Allowing users to have a public/private keypair without storing the
private key material on their device.</em
>
</p>
<h2>Overview</h2>
<p>
The goal of this page is to demostrate public/private key cryptography
and the ability to export and import a private key using a user-supplied
password.
</p>
<ul>
<li>
The <strong>keypair</strong> is using the RSA-OAEP algorithm, with a
SHA-512 hash. It uses a 4096-bit key, and the
<a
href="https://developer.mozilla.org/en-US/docs/Web/API/RsaHashedKeyGenParams#properties"
>standard exponent</a
>
of <code>[ 0x01, 0x00, 0x01 ]</code> (65537).
</li>
<li>
The <strong>encryption key</strong> (user key) for the
<strong>private key</strong> of the <strong>keypair</strong> is a
<strong>256 bit AES-GCM key</strong> (Unfortunately AES-KW didn't
work?) generated by PBKDF2 using:
<ul>
<li>10000 iterations</li>
<li>
16 byte salt
<em>(See note)</em>
</li>
<li>SHA-512 hashing</li>
</ul>
</li>
<li>The <strong>exported public key</strong> is in SPKI format.</li>
<li>
The <strong>exported private key</strong> is binary data representing:
<ul>
<li>First 16 bytes: the unique IV (per encryption)</li>
<li>
Remaning bytes: the encrypted private key in PCKS8 format, using
the <strong>encryption key</strong> and unique IV from above.
</li>
</ul>
</li>
</ul>
<p>
All cryptography happens in the browser, using the Subtle Crypto APIs.
The generated key is extractable, but is not intended to be user facing
(for now this is just a rough prototype).
</p>
<p>
<strong>Note on the salt:</strong> it is currently generated on page
load / reset, however, for a user to login across page loads, the salt
would need to come from a reproducible source. This could be an API
<code>(identity -> salt, exported keypair)</code>, but ideally we'd not
be transmitting the salt in cleartext to the server.<br /><br />
Instead, we should probably perform some sort of blinding on it, or
generate it from some mechanism (e.g., a hash derived from the users'
password). <br />
<em><strong>Incorrect salt == incorrect user key</strong></em>
</p>
<h2 id="usecase-and-security">Use Case & Security Considerations</h2>
<p>
This library has been designed to have a very simple interface &
implementation. The use-case is for making it easier for users to use
end-to-end encryption on the web, particularly without requiring the
user to save private key files or always use the same device.
<br /><br />
For the average user, they don't know about keypairs or public/private
key cryptography, they're used to using either social networks or
passwords for logging in to applications. The goal is to keep the user
experience fairly similar whilst also allowing for end-to-end
encryption.
<br /><br />
The intended use is to allow a user to supply the email/username and
password, and then gain access to strong cryptographic keys which are
stored by an API. The API should also have access secured, ideally using
email verification and a PAKE-based authentication mechanism (SRP6a,
BS-SPEKE, OPAQUE), and the encrypted keys should only be retrievable
after authentication.
<strong>
It is imperative that the password is not transmitted to the server.
</strong>
<br /><br />
<strong>Threat modelling:</strong> The biggest weakness in this system
is that the private key is only secured as strongly as the users'
password. though we take steps to make bruteforcing passwords difficult,
by using high iterations with PBKDF2 and a unique salt per user, this
only slows down an attacker, so strong passwords should be encouraged.
<br /><br />
We also rely on the browser's implementation of WebCrypto to be reliable
and secure, and that the page has been served with appropriate security
to ensure no malicious scripts are interacting with the javascript
running on the page. If your browser is compromised, then all bets are
off. Whilst it is widely acknowledged that installable applications can
have better security,
<abbr
title="See how Apple and Google ban Adult oriented applications from their App Stores"
>sometimes the web is the best platform available</abbr
>.
<br /><br />
We generate a symmetric key derived from the user-supplied password,
which can only be accessed via the WebCrypto APIs for wrapping and
unwrapping keys, and cannot be exported. We use that symmetric
encryption key to encrypt a public/private keypair, such that the
private key can be stored by an API Server without compromising user
security too much, as for the average user, managing security keys is
difficult. <br /><br />
</p>
<h2>Example Usage <button id="reset">Reset</button></h2>
<div class="keypair">
<p id="message-output">Initializing...</p>
<p>
<label for="password">
<span>Password: </span>
<span>
<input type="password" id="password" value="password"
/></span>
</label>
</p>
<p>
<label for="salt">
<span>Salt: </span>
<span>
<input type="text" id="salt" />
<em class="small">
TODO: Replace with salt derived from identity + password
</em>
</span>
</label>
</p>
<p>
<button id="generate-userkey">Generate User Key</button>
<button id="generate-keypair" disabled>Generate Keypair</button>
<button id="export-keypair" disabled>Export Keypair</button>
<button id="import-keypair" disabled>Import Keypair</button>
</p>
<h4>Public Key (Hex Encoded)</h4>
<textarea id="public-key" cols="64" rows="16"></textarea>
<h4>Private Key (Hex Encoded)</h4>
<textarea id="private-key" cols="64" rows="16"></textarea>
</div>
</div>
<script src="/src/index.ts" type="text/javascript"></script>
</body>
</html>