Mercurial > hg > rc1
comparison temp/js_cache/publickey-0e011cb.js @ 0:1e000243b222
vanilla 1.3.3 distro, I hope
author | Charlie Root |
---|---|
date | Thu, 04 Jan 2018 15:50:29 -0500 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e000243b222 |
---|---|
1 "use strict"; | |
2 | |
3 (function(context){ | |
4 /* | |
5 Default keyservers (HTTPS and CORS enabled) | |
6 */ | |
7 var DEFAULT_KEYSERVERS = [ | |
8 "https://keys.fedoraproject.org/", | |
9 "https://keybase.io/", | |
10 ]; | |
11 | |
12 /* | |
13 Initialization to create an PublicKey object. | |
14 | |
15 Arguments: | |
16 | |
17 * keyservers - Array of keyserver domains, default is: | |
18 ["https://keys.fedoraproject.org/", "https://keybase.io/"] | |
19 | |
20 Examples: | |
21 | |
22 //Initialize with the default keyservers | |
23 var hkp = new PublicKey(); | |
24 | |
25 //Initialize only with a specific keyserver | |
26 var hkp = new PublicKey(["https://key.ip6.li/"]); | |
27 */ | |
28 var PublicKey = function(keyservers){ | |
29 this.keyservers = keyservers || DEFAULT_KEYSERVERS; | |
30 }; | |
31 | |
32 /* | |
33 Get a public key from any keyserver based on keyId. | |
34 | |
35 Arguments: | |
36 | |
37 * keyId - String key id of the public key (this is usually a fingerprint) | |
38 | |
39 * callback - Function that is called when finished. Two arguments are | |
40 passed to the callback: publicKey and errorCode. publicKey is | |
41 an ASCII armored OpenPGP public key. errorCode is the error code | |
42 (either HTTP status code or keybase error code) returned by the | |
43 last keyserver that was tried. If a publicKey was found, | |
44 errorCode is null. If no publicKey was found, publicKey is null | |
45 and errorCode is not null. | |
46 | |
47 Examples: | |
48 | |
49 //Get a valid public key | |
50 var hkp = new PublicKey(); | |
51 hkp.get("F75BE4E6EF6E9DD203679E94E7F6FAD172EFEE3D", function(publicKey, errorCode){ | |
52 errorCode !== null ? console.log(errorCode) : console.log(publicKey); | |
53 }); | |
54 | |
55 //Try to get an invalid public key | |
56 var hkp = new PublicKey(); | |
57 hkp.get("bogus_id", function(publicKey, errorCode){ | |
58 errorCode !== null ? console.log(errorCode) : console.log(publicKey); | |
59 }); | |
60 */ | |
61 PublicKey.prototype.get = function(keyId, callback, keyserverIndex, err){ | |
62 //default starting point is at the first keyserver | |
63 if(keyserverIndex === undefined){ | |
64 keyserverIndex = 0; | |
65 } | |
66 | |
67 //no more keyservers to check, so no key found | |
68 if(keyserverIndex >= this.keyservers.length){ | |
69 return callback(null, err || 404); | |
70 } | |
71 | |
72 //set the keyserver to try next | |
73 var ks = this.keyservers[keyserverIndex]; | |
74 var _this = this; | |
75 | |
76 //special case for keybase | |
77 if(ks.indexOf("https://keybase.io/") === 0){ | |
78 | |
79 //don't need 0x prefix for keybase searches | |
80 if(keyId.indexOf("0x") === 0){ | |
81 keyId = keyId.substr(2); | |
82 } | |
83 | |
84 //request the public key from keybase | |
85 var xhr = new XMLHttpRequest(); | |
86 xhr.open("get", "https://keybase.io/_/api/1.0/user/lookup.json" + | |
87 "?fields=public_keys&key_fingerprint=" + keyId); | |
88 xhr.onload = function(){ | |
89 if(xhr.status === 200){ | |
90 var result = JSON.parse(xhr.responseText); | |
91 | |
92 //keybase error returns HTTP 200 status, which is silly | |
93 if(result['status']['code'] !== 0){ | |
94 return _this.get(keyId, callback, keyserverIndex + 1, result['status']['code']); | |
95 } | |
96 | |
97 //no public key found | |
98 if(result['them'].length === 0){ | |
99 return _this.get(keyId, callback, keyserverIndex + 1, 404); | |
100 } | |
101 | |
102 //found the public key | |
103 var publicKey = result['them'][0]['public_keys']['primary']['bundle']; | |
104 return callback(publicKey, null); | |
105 } | |
106 else{ | |
107 return _this.get(keyId, callback, keyserverIndex + 1, xhr.status); | |
108 } | |
109 }; | |
110 xhr.send(); | |
111 } | |
112 | |
113 //normal HKP keyserver | |
114 else{ | |
115 //add the 0x prefix if absent | |
116 if(keyId.indexOf("0x") !== 0){ | |
117 keyId = "0x" + keyId; | |
118 } | |
119 | |
120 //request the public key from the hkp server | |
121 var xhr = new XMLHttpRequest(); | |
122 xhr.open("get", ks + "pks/lookup?op=get&options=mr&search=" + keyId); | |
123 xhr.onload = function(){ | |
124 if(xhr.status === 200){ | |
125 return callback(xhr.responseText, null); | |
126 } | |
127 else{ | |
128 return _this.get(keyId, callback, keyserverIndex + 1, xhr.status); | |
129 } | |
130 }; | |
131 xhr.send(); | |
132 } | |
133 }; | |
134 | |
135 /* | |
136 Search for a public key in the keyservers. | |
137 | |
138 Arguments: | |
139 | |
140 * query - String to search for (usually an email, name, or username). | |
141 | |
142 * callback - Function that is called when finished. Two arguments are | |
143 passed to the callback: results and errorCode. results is an | |
144 Array of users that were returned by the search. errorCode is | |
145 the error code (either HTTP status code or keybase error code) | |
146 returned by the last keyserver that was tried. If any results | |
147 were found, errorCode is null. If no results are found, results | |
148 is null and errorCode is not null. | |
149 | |
150 Examples: | |
151 | |
152 //Search for diafygi's key id | |
153 var hkp = new PublicKey(); | |
154 hkp.search("diafygi", function(results, errorCode){ | |
155 errorCode !== null ? console.log(errorCode) : console.log(results); | |
156 }); | |
157 | |
158 //Search for a nonexistent key id | |
159 var hkp = new PublicKey(); | |
160 hkp.search("doesntexist123", function(results, errorCode){ | |
161 errorCode !== null ? console.log(errorCode) : console.log(results); | |
162 }); | |
163 */ | |
164 PublicKey.prototype.search = function(query, callback, keyserverIndex, results, err){ | |
165 //default starting point is at the first keyserver | |
166 if(keyserverIndex === undefined){ | |
167 keyserverIndex = 0; | |
168 } | |
169 | |
170 //initialize the results array | |
171 if(results === undefined){ | |
172 results = []; | |
173 } | |
174 | |
175 //no more keyservers to check | |
176 if(keyserverIndex >= this.keyservers.length){ | |
177 | |
178 //return error if no results | |
179 if(results.length === 0){ | |
180 return callback(null, err || 404); | |
181 } | |
182 | |
183 //return results | |
184 else{ | |
185 | |
186 //merge duplicates | |
187 var merged = {}; | |
188 for(var i = 0; i < results.length; i++){ | |
189 var k = results[i]; | |
190 | |
191 //see if there's duplicate key ids to merge | |
192 if(merged[k['keyid']] !== undefined){ | |
193 | |
194 for(var u = 0; u < k['uids'].length; u++){ | |
195 var has_this_uid = false; | |
196 | |
197 for(var m = 0; m < merged[k['keyid']]['uids'].length; m++){ | |
198 if(merged[k['keyid']]['uids'][m]['uid'] === k['uids'][u]){ | |
199 has_this_uid = true; | |
200 break; | |
201 } | |
202 } | |
203 | |
204 if(!has_this_uid){ | |
205 merged[k['keyid']]['uids'].push(k['uids'][u]) | |
206 } | |
207 } | |
208 } | |
209 | |
210 //no duplicate found, so add it to the dict | |
211 else{ | |
212 merged[k['keyid']] = k; | |
213 } | |
214 } | |
215 | |
216 //return a list of the merged results in the same order | |
217 var merged_list = []; | |
218 for(var i = 0; i < results.length; i++){ | |
219 var k = results[i]; | |
220 if(merged[k['keyid']] !== undefined){ | |
221 merged_list.push(merged[k['keyid']]); | |
222 delete(merged[k['keyid']]); | |
223 } | |
224 } | |
225 return callback(merged_list, null); | |
226 } | |
227 } | |
228 | |
229 //set the keyserver to try next | |
230 var ks = this.keyservers[keyserverIndex]; | |
231 var _this = this; | |
232 | |
233 //special case for keybase | |
234 if(ks.indexOf("https://keybase.io/") === 0){ | |
235 | |
236 //request a list of users from keybase | |
237 var xhr = new XMLHttpRequest(); | |
238 xhr.open("get", "https://keybase.io/_/api/1.0/user/autocomplete.json?q=" + encodeURIComponent(query)); | |
239 xhr.onload = function(){ | |
240 if(xhr.status === 200){ | |
241 var kb_json = JSON.parse(xhr.responseText); | |
242 | |
243 //keybase error returns HTTP 200 status, which is silly | |
244 if(kb_json['status']['code'] !== 0){ | |
245 return _this.search(query, callback, keyserverIndex + 1, results, kb_json['status']['code']); | |
246 } | |
247 | |
248 //no public key found | |
249 if(kb_json['completions'].length === 0){ | |
250 return _this.search(query, callback, keyserverIndex + 1, results, 404); | |
251 } | |
252 | |
253 //compose keybase user results | |
254 var kb_results = []; | |
255 for(var i = 0; i < kb_json['completions'].length; i++){ | |
256 var user = kb_json['completions'][i]['components']; | |
257 | |
258 //skip if no public key fingerprint | |
259 if(user['key_fingerprint'] === undefined){ | |
260 continue; | |
261 } | |
262 | |
263 //build keybase user result | |
264 var kb_result = { | |
265 "keyid": user['key_fingerprint']['val'].toUpperCase(), | |
266 "href": "https://keybase.io/" + user['username']['val'] + "/key.asc", | |
267 "info": "https://keybase.io/" + user['username']['val'], | |
268 "algo": user['key_fingerprint']['algo'], | |
269 "keylen": user['key_fingerprint']['nbits'], | |
270 "creationdate": null, | |
271 "expirationdate": null, | |
272 "revoked": false, | |
273 "disabled": false, | |
274 "expired": false, | |
275 "uids": [{ | |
276 "uid": user['username']['val'] + | |
277 " on Keybase <https://keybase.io/" + | |
278 user['username']['val'] + ">", | |
279 "creationdate": null, | |
280 "expirationdate": null, | |
281 "revoked": false, | |
282 "disabled": false, | |
283 "expired": false, | |
284 }] | |
285 }; | |
286 | |
287 //add full name | |
288 if(user['full_name'] !== undefined){ | |
289 kb_result['uids'].push({ | |
290 "uid": "Full Name: " + user['full_name']['val'], | |
291 "creationdate": null, | |
292 "expirationdate": null, | |
293 "revoked": false, | |
294 "disabled": false, | |
295 "expired": false, | |
296 }); | |
297 } | |
298 | |
299 //add twitter | |
300 if(user['twitter'] !== undefined){ | |
301 kb_result['uids'].push({ | |
302 "uid": user['twitter']['val'] + | |
303 " on Twitter <https://twitter.com/" + | |
304 user['twitter']['val'] + ">", | |
305 "creationdate": null, | |
306 "expirationdate": null, | |
307 "revoked": false, | |
308 "disabled": false, | |
309 "expired": false, | |
310 }); | |
311 } | |
312 | |
313 //add github | |
314 if(user['github'] !== undefined){ | |
315 kb_result['uids'].push({ | |
316 "uid": user['github']['val'] + | |
317 " on Github <https://github.com/" + | |
318 user['github']['val'] + ">", | |
319 "creationdate": null, | |
320 "expirationdate": null, | |
321 "revoked": false, | |
322 "disabled": false, | |
323 "expired": false, | |
324 }); | |
325 } | |
326 | |
327 //add reddit | |
328 if(user['reddit'] !== undefined){ | |
329 kb_result['uids'].push({ | |
330 "uid": user['reddit']['val'] + | |
331 " on Github <https://reddit.com/u/" + | |
332 user['reddit']['val'] + ">", | |
333 "creationdate": null, | |
334 "expirationdate": null, | |
335 "revoked": false, | |
336 "disabled": false, | |
337 "expired": false, | |
338 }); | |
339 } | |
340 | |
341 //add hackernews | |
342 if(user['hackernews'] !== undefined){ | |
343 kb_result['uids'].push({ | |
344 "uid": user['hackernews']['val'] + | |
345 " on Hacker News <https://news.ycombinator.com/user?id=" + | |
346 user['hackernews']['val'] + ">", | |
347 "creationdate": null, | |
348 "expirationdate": null, | |
349 "revoked": false, | |
350 "disabled": false, | |
351 "expired": false, | |
352 }); | |
353 } | |
354 | |
355 //add coinbase | |
356 if(user['coinbase'] !== undefined){ | |
357 kb_result['uids'].push({ | |
358 "uid": user['coinbase']['val'] + | |
359 " on Coinbase <https://www.coinbase.com/" + | |
360 user['coinbase']['val'] + ">", | |
361 "creationdate": null, | |
362 "expirationdate": null, | |
363 "revoked": false, | |
364 "disabled": false, | |
365 "expired": false, | |
366 }); | |
367 } | |
368 | |
369 //add websites | |
370 if(user['websites'] !== undefined){ | |
371 for(var w = 0; w < user['websites'].length; w++){ | |
372 kb_result['uids'].push({ | |
373 "uid": "Owns " + user['websites'][w]['val'], | |
374 "creationdate": null, | |
375 "expirationdate": null, | |
376 "revoked": false, | |
377 "disabled": false, | |
378 "expired": false, | |
379 }); | |
380 } | |
381 } | |
382 | |
383 kb_results.push(kb_result); | |
384 } | |
385 | |
386 results = results.concat(kb_results); | |
387 return _this.search(query, callback, keyserverIndex + 1, results, null); | |
388 } | |
389 else{ | |
390 return _this.search(query, callback, keyserverIndex + 1, results, xhr.status); | |
391 } | |
392 }; | |
393 xhr.send(); | |
394 } | |
395 | |
396 //normal HKP keyserver | |
397 else{ | |
398 var xhr = new XMLHttpRequest(); | |
399 xhr.open("get", ks + "pks/lookup?op=index&options=mr&fingerprint=on&search=" + encodeURIComponent(query)); | |
400 xhr.onload = function(){ | |
401 if(xhr.status === 200){ | |
402 var ks_results = []; | |
403 var raw = xhr.responseText.split("\n"); | |
404 var curKey = undefined; | |
405 for(var i = 0; i < raw.length; i++){ | |
406 var line = raw[i].trim(); | |
407 | |
408 //pub:<keyid>:<algo>:<keylen>:<creationdate>:<expirationdate>:<flags> | |
409 if(line.indexOf("pub:") == 0){ | |
410 if(curKey !== undefined){ | |
411 ks_results.push(curKey); | |
412 } | |
413 var vals = line.split(":"); | |
414 curKey = { | |
415 "keyid": vals[1], | |
416 "href": ks + "pks/lookup?op=get&options=mr&search=0x" + vals[1], | |
417 "info": ks + "pks/lookup?op=vindex&search=0x" + vals[1], | |
418 "algo": vals[2] === "" ? null : parseInt(vals[2]), | |
419 "keylen": vals[3] === "" ? null : parseInt(vals[3]), | |
420 "creationdate": vals[4] === "" ? null : parseInt(vals[4]), | |
421 "expirationdate": vals[5] === "" ? null : parseInt(vals[5]), | |
422 "revoked": vals[6].indexOf("r") !== -1, | |
423 "disabled": vals[6].indexOf("d") !== -1, | |
424 "expired": vals[6].indexOf("e") !== -1, | |
425 "uids": [], | |
426 } | |
427 } | |
428 | |
429 //uid:<escaped uid string>:<creationdate>:<expirationdate>:<flags> | |
430 if(line.indexOf("uid:") == 0){ | |
431 var vals = line.split(":"); | |
432 curKey['uids'].push({ | |
433 "uid": decodeURIComponent(vals[1]), | |
434 "creationdate": vals[2] === "" ? null : parseInt(vals[2]), | |
435 "expirationdate": vals[3] === "" ? null : parseInt(vals[3]), | |
436 "revoked": vals[4].indexOf("r") !== -1, | |
437 "disabled": vals[4].indexOf("d") !== -1, | |
438 "expired": vals[4].indexOf("e") !== -1, | |
439 }); | |
440 } | |
441 } | |
442 ks_results.push(curKey); | |
443 | |
444 results = results.concat(ks_results); | |
445 return _this.search(query, callback, keyserverIndex + 1, results, null); | |
446 } | |
447 else{ | |
448 return _this.search(query, callback, keyserverIndex + 1, results, xhr.status); | |
449 } | |
450 }; | |
451 xhr.send(); | |
452 } | |
453 }; | |
454 | |
455 context.PublicKey = PublicKey; | |
456 })(typeof exports === "undefined" ? this : exports); |