@@ -5,31 +5,366 @@ secrecy protocol that works in synchronous and asynchronous messaging environmen
5
5
[ here] ( https://github.com/trevp/axolotl/wiki ) , and the details of the wire format are available
6
6
[ here] ( https://github.com/WhisperSystems/TextSecure/wiki/ProtocolV2 ) .
7
7
8
- ## Getting started
8
+ Currently this implementation only supports version 3 of the protocol.
9
+
10
+ ## Installation
9
11
10
12
### Node.js
11
13
14
+ Install using npm:
12
15
```
13
16
$ npm install axolotl
14
17
```
15
18
19
+ and import using ` "axolotl" ` :
16
20
``` javascript
17
21
var axolotl = require (" axolotl" );
18
22
```
19
23
20
24
### Browser
21
25
26
+ Install using bower:
22
27
```
23
28
$ bower install axolotl
24
29
```
25
30
26
- With AMD:
31
+ and import using AMD:
27
32
``` javascript
28
33
require ([" axolotl" ], function (axolotl ) {
29
34
30
35
});
31
36
```
37
+
32
38
or without:
33
39
``` javascript
34
40
window .axolotl (... )
35
- ```
41
+ ```
42
+
43
+ ## Getting started
44
+
45
+ ### Dependencies
46
+
47
+ libaxolotl-javascript depends on [ traceur-runtime] ( https://github.com/google/traceur-compiler ) and
48
+ [ protobuf.js] ( https://github.com/dcodeIO/ProtoBuf.js ) . These dependencies are not included in the distributed package.
49
+ If you installed libaxolotl-javascript using npm then there is nothing more you need to do - npm will download these
50
+ dependencies for you.
51
+
52
+ If you are using libaxolotl-javascript in the browser, you will have to provide the library's dependencies yourself. If
53
+ you're using AMD, then simply provide the location of these dependencies in your AMD configuration. Otherwise, include
54
+ the dependencies on the page before including ` axolotl.js ` .
55
+
56
+ ### The Store interface
57
+
58
+ You need to provide an implementation of the ` Store ` interface when instantiating Axolotl. This is an object that
59
+ has the following methods.
60
+
61
+ * Note that all methods may return a Promise if the operation is asynchronous.*
62
+
63
+ #### getLocalIdentityKeyPair
64
+
65
+ ```
66
+ getLocalIdentityKeyPair() → {KeyPair}
67
+ ```
68
+
69
+ Get the local identity key pair created at install time. A key pair is a JavaScript object containing the keys ` public `
70
+ and ` private ` which correspond to the public and private keys, respectively. These keys are of type ArrayBuffer.
71
+
72
+ #### getLocalRegistrationId
73
+
74
+ ```
75
+ getLocalRegistrationId() → {Number}
76
+ ```
77
+
78
+ Get the local registration identifier created at install time.
79
+
80
+ #### getLocalSignedPreKeyPair
81
+
82
+ ```
83
+ getLocalSignedPreKeyPair(signedPreKeyId) → {KeyPair}
84
+ ```
85
+
86
+ Get the local signed pre-key pair associated with the ` signedPreKeyId ` .
87
+
88
+ ##### Parameters
89
+
90
+ Name|Type|Description
91
+ :---|:---|:----------
92
+ ` signedPreKeyId ` |Number|The identifier of the signed pre-key.
93
+
94
+ #### getLocalPreKeyPair
95
+
96
+ ```
97
+ getLocalPreKeyPair(preKeyId) → {KeyPair}
98
+ ```
99
+
100
+ Get the local pre-key pair associated with the ` preKeyId ` .
101
+
102
+ ##### Parameters
103
+
104
+ Name|Type|Description
105
+ :---|:---|:----------
106
+ ` preKeyId ` |Number|The identifier of the pre-key.
107
+
108
+ #### getRemotePreKeyBundle
109
+
110
+ ```
111
+ getRemotePreKeyBundle(remoteIdentity) → {PreKeyBundle}
112
+ ```
113
+
114
+ Retrieve a pre-key bundle for a remote identity. This will likely be retrieved from a remote server. A ` PreKeyBundle ` is
115
+ a JavaScript object with the following properties:
116
+
117
+ Name|Type|Description
118
+ :---|:---|:----------
119
+ ` identityKey ` |ArrayBuffer|The remote identity's public key.
120
+ ` preKeyId ` |Number|The identifier of the pre-key included in this bundle.
121
+ ` preKey ` |ArrayBuffer|The public half of the pre-key.
122
+ ` signedPreKeyId ` |Number|The identifier of the signed pre-key included in this bundle.
123
+ ` signedPreKey ` |ArrayBuffer|The public half of the signed pre-key.
124
+ ` signedPreKeySignature ` |ArrayBuffer|The signature associated with the ` signedPreKey ` .
125
+
126
+ ##### Parameters
127
+
128
+ Name|Type|Description
129
+ :---|:---|:----------
130
+ ` remoteIdentity ` |Identity|The identity of the remote entity. The type is the same as the type you pass to into
131
+ the methods on Axolotl.
132
+
133
+ #### isRemoteIdentityTrusted
134
+
135
+ ```
136
+ isRemoteIdentityTrusted(remoteIdentity, identityPublicKey) → {Boolean}
137
+ ```
138
+
139
+ Determine if the public key associated with the remote identity is trusted. It is up to the application to determine
140
+ an appropriate algorithm for this.
141
+
142
+ ##### Parameters
143
+
144
+ Name|Type|Description
145
+ :---|:---|:----------
146
+ ` remoteIdentity ` |Identity|The identity of the remote entity.
147
+ ` identityPublicKey ` |ArrayBuffer|The purported remote identity's public key.
148
+
149
+ #### putRemoteIdentity
150
+
151
+ ```
152
+ putRemoteIdentity(remoteIdentity, identityPublicKey) → {Void}
153
+ ```
154
+
155
+ Store a public key to be associated with the remote identity. This is called when a session is successfully established
156
+ and gives the application an opportunity to register trust in the identity.
157
+
158
+ ##### Parameters
159
+
160
+ Name|Type|Description
161
+ :---|:---|:----------
162
+ ` remoteIdentity ` |Identity|The identity of the remote entity.
163
+ ` identityPublicKey ` |ArrayBuffer|The remote identity's public key.
164
+
165
+ #### hasSession
166
+
167
+ ```
168
+ hasSession(identity) → {Boolean}
169
+ ```
170
+
171
+ Determine if there is a stored session for the identity.
172
+
173
+ ##### Parameters
174
+
175
+ Name|Type|Description
176
+ :---|:---|:----------
177
+ ` identity ` |Identity|The identity.
178
+
179
+ #### getSession
180
+
181
+ ```
182
+ getSession(identity) → {String}
183
+ ```
184
+
185
+ Retrieve the session state associated with the identity.
186
+
187
+ ##### Parameters
188
+
189
+ Name|Type|Description
190
+ :---|:---|:----------
191
+ ` identity ` |Identity|The identity.
192
+
193
+ #### putSession
194
+
195
+ ```
196
+ putSession(identity, sessionState) → {Void}
197
+ ```
198
+
199
+ Store the session state along with the identity.
200
+
201
+ ##### Parameters
202
+
203
+ Name|Type|Description
204
+ :---|:---|:----------
205
+ ` identity ` |Identity|The identity.
206
+ ` sessionState ` |String|The serialised session state.
207
+
208
+ ### The Crypto interface
209
+
210
+ You need to provide an implementation of the ` Crypto ` interface when instantiating Axolotl. This is an object that
211
+ has the following methods.
212
+
213
+ * Note that all methods may return a Promise if the operation is asynchronous.*
214
+
215
+ #### generateKeyPair
216
+
217
+ ```
218
+ generateKeyPair() → {KeyPair}
219
+ ```
220
+
221
+ Generate a fresh, random [ Curve25519] ( http://en.wikipedia.org/wiki/Curve25519 ) public/private key pair suitable for use
222
+ with Diffie-Hellman key agreements. The returned private key should be an ArrayBuffer consisting of 32 bytes. The
223
+ returned public key should be an ArrayBuffer consisting of 33 bytes, where the first byte is equal to ` 0x05 ` .
224
+
225
+ #### calculateAgreement
226
+
227
+ ```
228
+ calculateAgreement(theirPublicKey, ourPrivateKey) → {ArrayBuffer}
229
+ ```
230
+
231
+ Compute a [ Curve25519] ( http://en.wikipedia.org/wiki/Curve25519 ) Diffie-Hellman key agreement.
232
+
233
+ ##### Parameters
234
+
235
+ Name|Type|Description
236
+ :---|:---|:----------
237
+ ` theirPublicKey ` |ArrayBuffer|Their 33 byte public key.
238
+ ` ourPrivateKey ` |ArrayBuffer|Our 32 byte private key.
239
+
240
+ #### randomBytes
241
+
242
+ ```
243
+ randomBytes(byteCount) → {ArrayBuffer}
244
+ ```
245
+
246
+ Generate ` byteCount ` bytes of cryptographically secure random data and return as an ArrayBuffer.
247
+
248
+ ##### Parameters
249
+
250
+ Name|Type|Description
251
+ :---|:---|:----------
252
+ ` byteCount ` |Number|The number of bytes to generate.
253
+
254
+ #### sign
255
+
256
+ ```
257
+ sign(privateKey, dataToSign) → {ArrayBuffer}
258
+ ```
259
+
260
+ Produce an [ Ed25519] ( http://en.wikipedia.org/wiki/EdDSA ) signature. The returned signature should be an ArrayBuffer
261
+ consisting of 64 bytes.
262
+
263
+ ##### Parameters
264
+
265
+ Name|Type|Description
266
+ :---|:---|:----------
267
+ ` privateKey ` |ArrayBuffer|The 32 byte private key to use to generate the signature.
268
+ ` dataToSign ` |ArrayBuffer|The data to be signed. May be any length.
269
+
270
+ #### verifySignature
271
+
272
+ ```
273
+ verifySignature(publicKey, dataToSign, purportedSignature) → {Boolean}
274
+ ```
275
+
276
+ Verify an [ Ed25519] ( http://en.wikipedia.org/wiki/EdDSA ) signature.
277
+
278
+ ##### Parameters
279
+
280
+ Name|Type|Description
281
+ :---|:---|:----------
282
+ ` privateKey ` |ArrayBuffer|The 33 byte public half of the key used to produce the signature.
283
+ ` dataToSign ` |ArrayBuffer|The data that was signed. May be any length.
284
+ ` purportedSignature ` |ArrayBuffer|The purported signature to check.
285
+
286
+ #### hmac
287
+
288
+ ```
289
+ hmac(key, data) → {ArrayBuffer}
290
+ ```
291
+
292
+ Produce a HMAC-HASH using SHA-256. The returned ArrayBuffer should consist of 32 bytes.
293
+
294
+ ##### Parameters
295
+
296
+ Name|Type|Description
297
+ :---|:---|:----------
298
+ ` key ` |ArrayBuffer|The mac key. May be any length.
299
+ ` data ` |ArrayBuffer|The data to be hashed. May be any length.
300
+
301
+ #### encrypt
302
+
303
+ ```
304
+ encrypt(key, plaintext, iv) → {ArrayBuffer}
305
+ ```
306
+
307
+ Encrypt the ` plaintext ` using AES-256-CBC.
308
+
309
+ ##### Parameters
310
+
311
+ Name|Type|Description
312
+ :---|:---|:----------
313
+ ` key ` |ArrayBuffer|The 32 byte cipher key.
314
+ ` plaintext ` |ArrayBuffer|The data to be encrypted. May be any length.
315
+ ` iv ` |ArrayBuffer|A 16 byte random initialisation vector.
316
+
317
+ #### decrypt
318
+
319
+ ```
320
+ decrypt(key, ciphertext, iv) → {ArrayBuffer}
321
+ ```
322
+
323
+ Decrypt the ` ciphertext ` using AES-256-CBC.
324
+
325
+ ##### Parameters
326
+
327
+ Name|Type|Description
328
+ :---|:---|:----------
329
+ ` key ` |ArrayBuffer|The 32 byte cipher key used to encrypt the data.
330
+ ` ciphertext ` |ArrayBuffer|The data to be decrypted. Should have a length that is a multiple of 16 bytes.
331
+ ` iv ` |ArrayBuffer|The 16 byte initialisation vector used to encrypt the data.
332
+
333
+ ### Using Axolotl
334
+
335
+ Start by instantiating Axolotl:
336
+
337
+ ``` javascript
338
+ var axol = axolotl (crypto, store);
339
+ ```
340
+
341
+ When your application is first installed, the client will likely need to register with the server. To do this, a number
342
+ of data needs to be generated:
343
+
344
+ ``` javascript
345
+ axol .generateIdentityKeyPair ().then (... ); // Generate our identity key
346
+ axol .generateRegistrationId ().then (... ); // Generate our registration id
347
+ axol .generatePreKeys (0 , 100 ).then (... ); // Generate the first set of our pre-keys to send to the server
348
+ axol .generateLastResortPreKey ().then (... ); // Generate our last restore pre-key to send to the server
349
+ axol .generateSignedPreKey (identityKeyPair, 1 ).then (... ); // Generate our first signed pre-key to send to the server
350
+ ```
351
+
352
+ Once registered, sending messages is very simple:
353
+
354
+ ``` javascript
355
+ var message = convertStringToBytes (" Hello bob" );
356
+ axol .encryptMessage (" bob" , message).then (function (ciphertext ) {
357
+ // Send ciphertext to alice
358
+ });
359
+ ```
360
+
361
+ and on the receiving side:
362
+
363
+ ``` javascript
364
+ // When receiving a ciphertext, decide what type it is from the container and then decrypt
365
+ axol .decryptPreKeyWhisperMessage (" alice" , ciphertext).then (function (plaintext ) {
366
+ console .log (plaintext); // "Hello bob"
367
+ });
368
+ ```
369
+
370
+ and that's it!
0 commit comments