shogun-core 6.7.2 → 6.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,13 +1,13 @@
1
1
  (function webpackUniversalModuleDefinition(root, factory) {
2
2
  if(typeof exports === 'object' && typeof module === 'object')
3
- module.exports = factory(require("Gun"));
3
+ module.exports = factory(require("Gun"), require("Gun.SEA"));
4
4
  else if(typeof define === 'function' && define.amd)
5
- define(["Gun"], factory);
5
+ define(["Gun", "Gun.SEA"], factory);
6
6
  else if(typeof exports === 'object')
7
- exports["ShogunCore"] = factory(require("Gun"));
7
+ exports["ShogunCore"] = factory(require("Gun"), require("Gun.SEA"));
8
8
  else
9
- root["ShogunCore"] = factory(root["Gun"]);
10
- })(this, (__WEBPACK_EXTERNAL_MODULE_gun__) => {
9
+ root["ShogunCore"] = factory(root["Gun"], root["Gun.SEA"]);
10
+ })(this, (__WEBPACK_EXTERNAL_MODULE_gun__, __WEBPACK_EXTERNAL_MODULE_gun_sea__) => {
11
11
  return /******/ (() => { // webpackBootstrap
12
12
  /******/ var __webpack_modules__ = ({
13
13
 
@@ -31398,1556 +31398,6 @@ if(typeof JSON != ''+u){
31398
31398
 
31399
31399
  }());
31400
31400
 
31401
- /***/ }),
31402
-
31403
- /***/ "./node_modules/gun/sea.js":
31404
- /*!*********************************!*\
31405
- !*** ./node_modules/gun/sea.js ***!
31406
- \*********************************/
31407
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
31408
-
31409
- /* module decorator */ module = __webpack_require__.nmd(module);
31410
- /* provided dependency */ var Buffer = __webpack_require__(/*! buffer */ "./node_modules/buffer/index.js")["Buffer"];
31411
- ;(function(){
31412
-
31413
- /* UNBUILD */
31414
- function USE(arg, req){
31415
- return req? __webpack_require__("./node_modules/gun sync recursive")(arg) : arg.slice? USE[R(arg)] : function(mod, path){
31416
- arg(mod = {exports: {}});
31417
- USE[R(path)] = mod.exports;
31418
- }
31419
- function R(p){
31420
- return p.split('/').slice(-1).toString().replace('.js','');
31421
- }
31422
- }
31423
- if(true){ var MODULE = module }
31424
- /* UNBUILD */
31425
-
31426
- ;USE(function(module){
31427
- // Security, Encryption, and Authorization: SEA.js
31428
- // MANDATORY READING: https://gun.eco/explainers/data/security.html
31429
- // IT IS IMPLEMENTED IN A POLYFILL/SHIM APPROACH.
31430
- // THIS IS AN EARLY ALPHA!
31431
-
31432
- if(typeof self !== "undefined"){ module.window = self } // should be safe for at least browser/worker/nodejs, need to check other envs like RN etc.
31433
- if(true){ module.window = window }
31434
-
31435
- var tmp = module.window || module, u;
31436
- var SEA = tmp.SEA || {};
31437
-
31438
- if(SEA.window = module.window){ SEA.window.SEA = SEA }
31439
-
31440
- try{ if(u+'' !== typeof MODULE){ MODULE.exports = SEA } }catch(e){}
31441
- module.exports = SEA;
31442
- })(USE, './root');
31443
-
31444
- ;USE(function(module){
31445
- var SEA = USE('./root');
31446
- try{ if(SEA.window){
31447
- if(location.protocol.indexOf('s') < 0
31448
- && location.host.indexOf('localhost') < 0
31449
- && ! /^127\.\d+\.\d+\.\d+$/.test(location.hostname)
31450
- && location.protocol.indexOf('file:') < 0){
31451
- console.warn('HTTPS needed for WebCrypto in SEA, redirecting...');
31452
- location.protocol = 'https:'; // WebCrypto does NOT work without HTTPS!
31453
- }
31454
- } }catch(e){}
31455
- })(USE, './https');
31456
-
31457
- ;USE(function(module){
31458
- var u;
31459
- if(u+''== typeof btoa){
31460
- if(u+'' == typeof Buffer){
31461
- try{ __webpack_require__.g.Buffer = USE("buffer", 1).Buffer }catch(e){ console.log("Please `npm install buffer` or add it to your package.json !") }
31462
- }
31463
- __webpack_require__.g.btoa = function(data){ return Buffer.from(data, "binary").toString("base64") };
31464
- __webpack_require__.g.atob = function(data){ return Buffer.from(data, "base64").toString("binary") };
31465
- }
31466
- })(USE, './base64');
31467
-
31468
- ;USE(function(module){
31469
- USE('./base64');
31470
- // This is Array extended to have .toString(['utf8'|'hex'|'base64'])
31471
- function SeaArray() {}
31472
- Object.assign(SeaArray, { from: Array.from })
31473
- SeaArray.prototype = Object.create(Array.prototype)
31474
- SeaArray.prototype.toString = function(enc, start, end) { enc = enc || 'utf8'; start = start || 0;
31475
- const length = this.length
31476
- if (enc === 'hex') {
31477
- const buf = new Uint8Array(this)
31478
- return [ ...Array(((end && (end + 1)) || length) - start).keys()]
31479
- .map((i) => buf[ i + start ].toString(16).padStart(2, '0')).join('')
31480
- }
31481
- if (enc === 'utf8') {
31482
- return Array.from(
31483
- { length: (end || length) - start },
31484
- (_, i) => String.fromCharCode(this[ i + start])
31485
- ).join('')
31486
- }
31487
- if (enc === 'base64') {
31488
- return btoa(this)
31489
- }
31490
- }
31491
- module.exports = SeaArray;
31492
- })(USE, './array');
31493
-
31494
- ;USE(function(module){
31495
- USE('./base64');
31496
- // This is Buffer implementation used in SEA. Functionality is mostly
31497
- // compatible with NodeJS 'safe-buffer' and is used for encoding conversions
31498
- // between binary and 'hex' | 'utf8' | 'base64'
31499
- // See documentation and validation for safe implementation in:
31500
- // https://github.com/feross/safe-buffer#update
31501
- var SeaArray = USE('./array');
31502
- function SafeBuffer(...props) {
31503
- console.warn('new SafeBuffer() is depreciated, please use SafeBuffer.from()')
31504
- return SafeBuffer.from(...props)
31505
- }
31506
- SafeBuffer.prototype = Object.create(Array.prototype)
31507
- Object.assign(SafeBuffer, {
31508
- // (data, enc) where typeof data === 'string' then enc === 'utf8'|'hex'|'base64'
31509
- from() {
31510
- if (!Object.keys(arguments).length || arguments[0]==null) {
31511
- throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.')
31512
- }
31513
- const input = arguments[0]
31514
- let buf
31515
- if (typeof input === 'string') {
31516
- const enc = arguments[1] || 'utf8'
31517
- if (enc === 'hex') {
31518
- const bytes = input.match(/([\da-fA-F]{2})/g)
31519
- .map((byte) => parseInt(byte, 16))
31520
- if (!bytes || !bytes.length) {
31521
- throw new TypeError('Invalid first argument for type \'hex\'.')
31522
- }
31523
- buf = SeaArray.from(bytes)
31524
- } else if (enc === 'utf8' || 'binary' === enc) { // EDIT BY MARK: I think this is safe, tested it against a couple "binary" strings. This lets SafeBuffer match NodeJS Buffer behavior more where it safely btoas regular strings.
31525
- const length = input.length
31526
- const words = new Uint16Array(length)
31527
- Array.from({ length: length }, (_, i) => words[i] = input.charCodeAt(i))
31528
- buf = SeaArray.from(words)
31529
- } else if (enc === 'base64') {
31530
- const dec = atob(input)
31531
- const length = dec.length
31532
- const bytes = new Uint8Array(length)
31533
- Array.from({ length: length }, (_, i) => bytes[i] = dec.charCodeAt(i))
31534
- buf = SeaArray.from(bytes)
31535
- } else if (enc === 'binary') { // deprecated by above comment
31536
- buf = SeaArray.from(input) // some btoas were mishandled.
31537
- } else {
31538
- console.info('SafeBuffer.from unknown encoding: '+enc)
31539
- }
31540
- return buf
31541
- }
31542
- const byteLength = input.byteLength // what is going on here? FOR MARTTI
31543
- const length = input.byteLength ? input.byteLength : input.length
31544
- if (length) {
31545
- let buf
31546
- if (input instanceof ArrayBuffer) {
31547
- buf = new Uint8Array(input)
31548
- }
31549
- return SeaArray.from(buf || input)
31550
- }
31551
- },
31552
- // This is 'safe-buffer.alloc' sans encoding support
31553
- alloc(length, fill = 0 /*, enc*/ ) {
31554
- return SeaArray.from(new Uint8Array(Array.from({ length: length }, () => fill)))
31555
- },
31556
- // This is normal UNSAFE 'buffer.alloc' or 'new Buffer(length)' - don't use!
31557
- allocUnsafe(length) {
31558
- return SeaArray.from(new Uint8Array(Array.from({ length : length })))
31559
- },
31560
- // This puts together array of array like members
31561
- concat(arr) { // octet array
31562
- if (!Array.isArray(arr)) {
31563
- throw new TypeError('First argument must be Array containing ArrayBuffer or Uint8Array instances.')
31564
- }
31565
- return SeaArray.from(arr.reduce((ret, item) => ret.concat(Array.from(item)), []))
31566
- }
31567
- })
31568
- SafeBuffer.prototype.from = SafeBuffer.from
31569
- SafeBuffer.prototype.toString = SeaArray.prototype.toString
31570
-
31571
- module.exports = SafeBuffer;
31572
- })(USE, './buffer');
31573
-
31574
- ;USE(function(module){
31575
- const SEA = USE('./root')
31576
- const api = {Buffer: USE('./buffer')}
31577
- var o = {}, u;
31578
-
31579
- // ideally we can move away from JSON entirely? unlikely due to compatibility issues... oh well.
31580
- JSON.parseAsync = JSON.parseAsync || function(t,cb,r){ var u; try{ cb(u, JSON.parse(t,r)) }catch(e){ cb(e) } }
31581
- JSON.stringifyAsync = JSON.stringifyAsync || function(v,cb,r,s){ var u; try{ cb(u, JSON.stringify(v,r,s)) }catch(e){ cb(e) } }
31582
-
31583
- api.parse = function(t,r){ return new Promise(function(res, rej){
31584
- JSON.parseAsync(t,function(err, raw){ err? rej(err) : res(raw) },r);
31585
- })}
31586
- api.stringify = function(v,r,s){ return new Promise(function(res, rej){
31587
- JSON.stringifyAsync(v,function(err, raw){ err? rej(err) : res(raw) },r,s);
31588
- })}
31589
-
31590
- if(SEA.window){
31591
- api.crypto = SEA.window.crypto || SEA.window.msCrypto
31592
- api.subtle = (api.crypto||o).subtle || (api.crypto||o).webkitSubtle;
31593
- api.TextEncoder = SEA.window.TextEncoder;
31594
- api.TextDecoder = SEA.window.TextDecoder;
31595
- api.random = (len) => api.Buffer.from(api.crypto.getRandomValues(new Uint8Array(api.Buffer.alloc(len))));
31596
- }
31597
- if(!api.TextDecoder)
31598
- {
31599
- const { TextEncoder, TextDecoder } = USE((u+'' == typeof MODULE?'.':'')+'./lib/text-encoding', 1);
31600
- api.TextDecoder = TextDecoder;
31601
- api.TextEncoder = TextEncoder;
31602
- }
31603
- if(!api.crypto)
31604
- {
31605
- try
31606
- {
31607
- var crypto = USE('crypto', 1);
31608
- Object.assign(api, {
31609
- crypto,
31610
- random: (len) => api.Buffer.from(crypto.randomBytes(len))
31611
- });
31612
- const { Crypto: WebCrypto } = USE('@peculiar/webcrypto', 1);
31613
- api.ossl = api.subtle = new WebCrypto({directory: 'ossl'}).subtle // ECDH
31614
- }
31615
- catch(e){
31616
- console.log("Please `npm install @peculiar/webcrypto` or add it to your package.json !");
31617
- }}
31618
-
31619
- module.exports = api
31620
- })(USE, './shim');
31621
-
31622
- ;USE(function(module){
31623
- var SEA = USE('./root');
31624
- var shim = USE('./shim');
31625
- var s = {};
31626
- s.pbkdf2 = {hash: {name : 'SHA-256'}, iter: 100000, ks: 64};
31627
- s.ecdsa = {
31628
- pair: {name: 'ECDSA', namedCurve: 'P-256'},
31629
- sign: {name: 'ECDSA', hash: {name: 'SHA-256'}}
31630
- };
31631
- s.ecdh = {name: 'ECDH', namedCurve: 'P-256'};
31632
-
31633
- // This creates Web Cryptography API compliant JWK for sign/verify purposes
31634
- s.jwk = function(pub, d){ // d === priv
31635
- pub = pub.split('.');
31636
- var x = pub[0], y = pub[1];
31637
- var jwk = {kty: "EC", crv: "P-256", x: x, y: y, ext: true};
31638
- jwk.key_ops = d ? ['sign'] : ['verify'];
31639
- if(d){ jwk.d = d }
31640
- return jwk;
31641
- };
31642
-
31643
- s.keyToJwk = function(keyBytes) {
31644
- const keyB64 = keyBytes.toString('base64');
31645
- const k = keyB64.replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, '');
31646
- return { kty: 'oct', k: k, ext: false, alg: 'A256GCM' };
31647
- }
31648
-
31649
- s.recall = {
31650
- validity: 12 * 60 * 60, // internally in seconds : 12 hours
31651
- hook: function(props){ return props } // { iat, exp, alias, remember } // or return new Promise((resolve, reject) => resolve(props)
31652
- };
31653
-
31654
- s.check = function(t){ return (typeof t == 'string') && ('SEA{' === t.slice(0,4)) }
31655
- s.parse = async function p(t){ try {
31656
- var yes = (typeof t == 'string');
31657
- if(yes && 'SEA{' === t.slice(0,4)){ t = t.slice(3) }
31658
- return yes ? await shim.parse(t) : t;
31659
- } catch (e) {}
31660
- return t;
31661
- }
31662
-
31663
- SEA.opt = s;
31664
- module.exports = s
31665
- })(USE, './settings');
31666
-
31667
- ;USE(function(module){
31668
- var shim = USE('./shim');
31669
- module.exports = async function(d, o){
31670
- var t = (typeof d == 'string')? d : await shim.stringify(d);
31671
- var hash = await shim.subtle.digest({name: o||'SHA-256'}, new shim.TextEncoder().encode(t));
31672
- return shim.Buffer.from(hash);
31673
- }
31674
- })(USE, './sha256');
31675
-
31676
- ;USE(function(module){
31677
- // This internal func returns SHA-1 hashed data for KeyID generation
31678
- const __shim = USE('./shim')
31679
- const subtle = __shim.subtle
31680
- const ossl = __shim.ossl ? __shim.ossl : subtle
31681
- const sha1hash = (b) => ossl.digest({name: 'SHA-1'}, new ArrayBuffer(b))
31682
- module.exports = sha1hash
31683
- })(USE, './sha1');
31684
-
31685
- ;USE(function(module){
31686
- var SEA = USE('./root');
31687
- var shim = USE('./shim');
31688
- var S = USE('./settings');
31689
- var sha = USE('./sha256');
31690
- var u;
31691
-
31692
- SEA.work = SEA.work || (async (data, pair, cb, opt) => { try { // used to be named `proof`
31693
- var salt = (pair||{}).epub || pair; // epub not recommended, salt should be random!
31694
- opt = opt || {};
31695
- if(salt instanceof Function){
31696
- cb = salt;
31697
- salt = u;
31698
- }
31699
- data = (typeof data == 'string')? data : await shim.stringify(data);
31700
- if('sha' === (opt.name||'').toLowerCase().slice(0,3)){
31701
- var rsha = shim.Buffer.from(await sha(data, opt.name), 'binary').toString(opt.encode || 'base64')
31702
- if(cb){ try{ cb(rsha) }catch(e){console.log(e)} }
31703
- return rsha;
31704
- }
31705
- salt = salt || shim.random(9);
31706
- var key = await (shim.ossl || shim.subtle).importKey('raw', new shim.TextEncoder().encode(data), {name: opt.name || 'PBKDF2'}, false, ['deriveBits']);
31707
- var work = await (shim.ossl || shim.subtle).deriveBits({
31708
- name: opt.name || 'PBKDF2',
31709
- iterations: opt.iterations || S.pbkdf2.iter,
31710
- salt: new shim.TextEncoder().encode(opt.salt || salt),
31711
- hash: opt.hash || S.pbkdf2.hash,
31712
- }, key, opt.length || (S.pbkdf2.ks * 8))
31713
- data = shim.random(data.length) // Erase data in case of passphrase
31714
- var r = shim.Buffer.from(work, 'binary').toString(opt.encode || 'base64')
31715
- if(cb){ try{ cb(r) }catch(e){console.log(e)} }
31716
- return r;
31717
- } catch(e) {
31718
- console.log(e);
31719
- SEA.err = e;
31720
- if(SEA.throw){ throw e }
31721
- if(cb){ cb() }
31722
- return;
31723
- }});
31724
-
31725
- module.exports = SEA.work;
31726
- })(USE, './work');
31727
-
31728
- ;USE(function(module){
31729
- var SEA = USE('./root');
31730
- var shim = USE('./shim');
31731
- var S = USE('./settings');
31732
-
31733
- SEA.name = SEA.name || (async (cb, opt) => { try {
31734
- if(cb){ try{ cb() }catch(e){console.log(e)} }
31735
- return;
31736
- } catch(e) {
31737
- console.log(e);
31738
- SEA.err = e;
31739
- if(SEA.throw){ throw e }
31740
- if(cb){ cb() }
31741
- return;
31742
- }});
31743
-
31744
- //SEA.pair = async (data, proof, cb) => { try {
31745
- SEA.pair = SEA.pair || (async (cb, opt) => { try {
31746
-
31747
- var ecdhSubtle = shim.ossl || shim.subtle;
31748
- // First: ECDSA keys for signing/verifying...
31749
- var sa = await shim.subtle.generateKey({name: 'ECDSA', namedCurve: 'P-256'}, true, [ 'sign', 'verify' ])
31750
- .then(async (keys) => {
31751
- // privateKey scope doesn't leak out from here!
31752
- //const { d: priv } = await shim.subtle.exportKey('jwk', keys.privateKey)
31753
- var key = {};
31754
- key.priv = (await shim.subtle.exportKey('jwk', keys.privateKey)).d;
31755
- var pub = await shim.subtle.exportKey('jwk', keys.publicKey);
31756
- //const pub = Buff.from([ x, y ].join(':')).toString('base64') // old
31757
- key.pub = pub.x+'.'+pub.y; // new
31758
- // x and y are already base64
31759
- // pub is UTF8 but filename/URL safe (https://www.ietf.org/rfc/rfc3986.txt)
31760
- // but split on a non-base64 letter.
31761
- return key;
31762
- })
31763
-
31764
- // To include PGPv4 kind of keyId:
31765
- // const pubId = await SEA.keyid(keys.pub)
31766
- // Next: ECDH keys for encryption/decryption...
31767
-
31768
- try{
31769
- var dh = await ecdhSubtle.generateKey({name: 'ECDH', namedCurve: 'P-256'}, true, ['deriveKey'])
31770
- .then(async (keys) => {
31771
- // privateKey scope doesn't leak out from here!
31772
- var key = {};
31773
- key.epriv = (await ecdhSubtle.exportKey('jwk', keys.privateKey)).d;
31774
- var pub = await ecdhSubtle.exportKey('jwk', keys.publicKey);
31775
- //const epub = Buff.from([ ex, ey ].join(':')).toString('base64') // old
31776
- key.epub = pub.x+'.'+pub.y; // new
31777
- // ex and ey are already base64
31778
- // epub is UTF8 but filename/URL safe (https://www.ietf.org/rfc/rfc3986.txt)
31779
- // but split on a non-base64 letter.
31780
- return key;
31781
- })
31782
- }catch(e){
31783
- if(SEA.window){ throw e }
31784
- if(e == 'Error: ECDH is not a supported algorithm'){ console.log('Ignoring ECDH...') }
31785
- else { throw e }
31786
- } dh = dh || {};
31787
-
31788
- var r = { pub: sa.pub, priv: sa.priv, /* pubId, */ epub: dh.epub, epriv: dh.epriv }
31789
- if(cb){ try{ cb(r) }catch(e){console.log(e)} }
31790
- return r;
31791
- } catch(e) {
31792
- console.log(e);
31793
- SEA.err = e;
31794
- if(SEA.throw){ throw e }
31795
- if(cb){ cb() }
31796
- return;
31797
- }});
31798
-
31799
- module.exports = SEA.pair;
31800
- })(USE, './pair');
31801
-
31802
- ;USE(function(module){
31803
- var SEA = USE('./root');
31804
- var shim = USE('./shim');
31805
- var S = USE('./settings');
31806
- var sha = USE('./sha256');
31807
- var u;
31808
-
31809
- SEA.sign = SEA.sign || (async (data, pair, cb, opt) => { try {
31810
- opt = opt || {};
31811
- if(!(pair||opt).priv){
31812
- if(!SEA.I){ throw 'No signing key.' }
31813
- pair = await SEA.I(null, {what: data, how: 'sign', why: opt.why});
31814
- }
31815
- if(u === data){ throw '`undefined` not allowed.' }
31816
- var json = await S.parse(data);
31817
- var check = opt.check = opt.check || json;
31818
- if(SEA.verify && (SEA.opt.check(check) || (check && check.s && check.m))
31819
- && u !== await SEA.verify(check, pair)){ // don't sign if we already signed it.
31820
- var r = await S.parse(check);
31821
- if(!opt.raw){ r = 'SEA' + await shim.stringify(r) }
31822
- if(cb){ try{ cb(r) }catch(e){console.log(e)} }
31823
- return r;
31824
- }
31825
- var pub = pair.pub;
31826
- var priv = pair.priv;
31827
- var jwk = S.jwk(pub, priv);
31828
- var hash = await sha(json);
31829
- var sig = await (shim.ossl || shim.subtle).importKey('jwk', jwk, {name: 'ECDSA', namedCurve: 'P-256'}, false, ['sign'])
31830
- .then((key) => (shim.ossl || shim.subtle).sign({name: 'ECDSA', hash: {name: 'SHA-256'}}, key, new Uint8Array(hash))) // privateKey scope doesn't leak out from here!
31831
- var r = {m: json, s: shim.Buffer.from(sig, 'binary').toString(opt.encode || 'base64')}
31832
- if(!opt.raw){ r = 'SEA' + await shim.stringify(r) }
31833
-
31834
- if(cb){ try{ cb(r) }catch(e){console.log(e)} }
31835
- return r;
31836
- } catch(e) {
31837
- console.log(e);
31838
- SEA.err = e;
31839
- if(SEA.throw){ throw e }
31840
- if(cb){ cb() }
31841
- return;
31842
- }});
31843
-
31844
- module.exports = SEA.sign;
31845
- })(USE, './sign');
31846
-
31847
- ;USE(function(module){
31848
- var SEA = USE('./root');
31849
- var shim = USE('./shim');
31850
- var S = USE('./settings');
31851
- var sha = USE('./sha256');
31852
- var u;
31853
-
31854
- SEA.verify = SEA.verify || (async (data, pair, cb, opt) => { try {
31855
- var json = await S.parse(data);
31856
- if(false === pair){ // don't verify!
31857
- var raw = await S.parse(json.m);
31858
- if(cb){ try{ cb(raw) }catch(e){console.log(e)} }
31859
- return raw;
31860
- }
31861
- opt = opt || {};
31862
- // SEA.I // verify is free! Requires no user permission.
31863
- var pub = pair.pub || pair;
31864
- var key = SEA.opt.slow_leak? await SEA.opt.slow_leak(pub) : await (shim.ossl || shim.subtle).importKey('jwk', S.jwk(pub), {name: 'ECDSA', namedCurve: 'P-256'}, false, ['verify']);
31865
- var hash = await sha(json.m);
31866
- var buf, sig, check, tmp; try{
31867
- buf = shim.Buffer.from(json.s, opt.encode || 'base64'); // NEW DEFAULT!
31868
- sig = new Uint8Array(buf);
31869
- check = await (shim.ossl || shim.subtle).verify({name: 'ECDSA', hash: {name: 'SHA-256'}}, key, sig, new Uint8Array(hash));
31870
- if(!check){ throw "Signature did not match." }
31871
- }catch(e){
31872
- if(SEA.opt.fallback){
31873
- return await SEA.opt.fall_verify(data, pair, cb, opt);
31874
- }
31875
- }
31876
- var r = check? await S.parse(json.m) : u;
31877
-
31878
- if(cb){ try{ cb(r) }catch(e){console.log(e)} }
31879
- return r;
31880
- } catch(e) {
31881
- console.log(e); // mismatched owner FOR MARTTI
31882
- SEA.err = e;
31883
- if(SEA.throw){ throw e }
31884
- if(cb){ cb() }
31885
- return;
31886
- }});
31887
-
31888
- module.exports = SEA.verify;
31889
- // legacy & ossl memory leak mitigation:
31890
-
31891
- var knownKeys = {};
31892
- var keyForPair = SEA.opt.slow_leak = pair => {
31893
- if (knownKeys[pair]) return knownKeys[pair];
31894
- var jwk = S.jwk(pair);
31895
- knownKeys[pair] = (shim.ossl || shim.subtle).importKey("jwk", jwk, {name: 'ECDSA', namedCurve: 'P-256'}, false, ["verify"]);
31896
- return knownKeys[pair];
31897
- };
31898
-
31899
- var O = SEA.opt;
31900
- SEA.opt.fall_verify = async function(data, pair, cb, opt, f){
31901
- if(f === SEA.opt.fallback){ throw "Signature did not match" } f = f || 1;
31902
- var tmp = data||'';
31903
- data = SEA.opt.unpack(data) || data;
31904
- var json = await S.parse(data), pub = pair.pub || pair, key = await SEA.opt.slow_leak(pub);
31905
- var hash = (f <= SEA.opt.fallback)? shim.Buffer.from(await shim.subtle.digest({name: 'SHA-256'}, new shim.TextEncoder().encode(await S.parse(json.m)))) : await sha(json.m); // this line is old bad buggy code but necessary for old compatibility.
31906
- var buf; var sig; var check; try{
31907
- buf = shim.Buffer.from(json.s, opt.encode || 'base64') // NEW DEFAULT!
31908
- sig = new Uint8Array(buf)
31909
- check = await (shim.ossl || shim.subtle).verify({name: 'ECDSA', hash: {name: 'SHA-256'}}, key, sig, new Uint8Array(hash))
31910
- if(!check){ throw "Signature did not match." }
31911
- }catch(e){ try{
31912
- buf = shim.Buffer.from(json.s, 'utf8') // AUTO BACKWARD OLD UTF8 DATA!
31913
- sig = new Uint8Array(buf)
31914
- check = await (shim.ossl || shim.subtle).verify({name: 'ECDSA', hash: {name: 'SHA-256'}}, key, sig, new Uint8Array(hash))
31915
- }catch(e){
31916
- if(!check){ throw "Signature did not match." }
31917
- }
31918
- }
31919
- var r = check? await S.parse(json.m) : u;
31920
- O.fall_soul = tmp['#']; O.fall_key = tmp['.']; O.fall_val = data; O.fall_state = tmp['>'];
31921
- if(cb){ try{ cb(r) }catch(e){console.log(e)} }
31922
- return r;
31923
- }
31924
- SEA.opt.fallback = 2;
31925
-
31926
- })(USE, './verify');
31927
-
31928
- ;USE(function(module){
31929
- var shim = USE('./shim');
31930
- var S = USE('./settings');
31931
- var sha256hash = USE('./sha256');
31932
-
31933
- const importGen = async (key, salt, opt) => {
31934
- //const combo = shim.Buffer.concat([shim.Buffer.from(key, 'utf8'), salt || shim.random(8)]).toString('utf8') // old
31935
- opt = opt || {};
31936
- const combo = key + (salt || shim.random(8)).toString('utf8'); // new
31937
- const hash = shim.Buffer.from(await sha256hash(combo), 'binary')
31938
-
31939
- const jwkKey = S.keyToJwk(hash)
31940
- return await shim.subtle.importKey('jwk', jwkKey, {name:'AES-GCM'}, false, ['encrypt', 'decrypt'])
31941
- }
31942
- module.exports = importGen;
31943
- })(USE, './aeskey');
31944
-
31945
- ;USE(function(module){
31946
- var SEA = USE('./root');
31947
- var shim = USE('./shim');
31948
- var S = USE('./settings');
31949
- var aeskey = USE('./aeskey');
31950
- var u;
31951
-
31952
- SEA.encrypt = SEA.encrypt || (async (data, pair, cb, opt) => { try {
31953
- opt = opt || {};
31954
- var key = (pair||opt).epriv || pair;
31955
- if(u === data){ throw '`undefined` not allowed.' }
31956
- if(!key){
31957
- if(!SEA.I){ throw 'No encryption key.' }
31958
- pair = await SEA.I(null, {what: data, how: 'encrypt', why: opt.why});
31959
- key = pair.epriv || pair;
31960
- }
31961
- var msg = (typeof data == 'string')? data : await shim.stringify(data);
31962
- var rand = {s: shim.random(9), iv: shim.random(15)}; // consider making this 9 and 15 or 18 or 12 to reduce == padding.
31963
- var ct = await aeskey(key, rand.s, opt).then((aes) => (/*shim.ossl ||*/ shim.subtle).encrypt({ // Keeping the AES key scope as private as possible...
31964
- name: opt.name || 'AES-GCM', iv: new Uint8Array(rand.iv)
31965
- }, aes, new shim.TextEncoder().encode(msg)));
31966
- var r = {
31967
- ct: shim.Buffer.from(ct, 'binary').toString(opt.encode || 'base64'),
31968
- iv: rand.iv.toString(opt.encode || 'base64'),
31969
- s: rand.s.toString(opt.encode || 'base64')
31970
- }
31971
- if(!opt.raw){ r = 'SEA' + await shim.stringify(r) }
31972
-
31973
- if(cb){ try{ cb(r) }catch(e){console.log(e)} }
31974
- return r;
31975
- } catch(e) {
31976
- console.log(e);
31977
- SEA.err = e;
31978
- if(SEA.throw){ throw e }
31979
- if(cb){ cb() }
31980
- return;
31981
- }});
31982
-
31983
- module.exports = SEA.encrypt;
31984
- })(USE, './encrypt');
31985
-
31986
- ;USE(function(module){
31987
- var SEA = USE('./root');
31988
- var shim = USE('./shim');
31989
- var S = USE('./settings');
31990
- var aeskey = USE('./aeskey');
31991
-
31992
- SEA.decrypt = SEA.decrypt || (async (data, pair, cb, opt) => { try {
31993
- opt = opt || {};
31994
- var key = (pair||opt).epriv || pair;
31995
- if(!key){
31996
- if(!SEA.I){ throw 'No decryption key.' }
31997
- pair = await SEA.I(null, {what: data, how: 'decrypt', why: opt.why});
31998
- key = pair.epriv || pair;
31999
- }
32000
- var json = await S.parse(data);
32001
- var buf, bufiv, bufct; try{
32002
- buf = shim.Buffer.from(json.s, opt.encode || 'base64');
32003
- bufiv = shim.Buffer.from(json.iv, opt.encode || 'base64');
32004
- bufct = shim.Buffer.from(json.ct, opt.encode || 'base64');
32005
- var ct = await aeskey(key, buf, opt).then((aes) => (/*shim.ossl ||*/ shim.subtle).decrypt({ // Keeping aesKey scope as private as possible...
32006
- name: opt.name || 'AES-GCM', iv: new Uint8Array(bufiv), tagLength: 128
32007
- }, aes, new Uint8Array(bufct)));
32008
- }catch(e){
32009
- if('utf8' === opt.encode){ throw "Could not decrypt" }
32010
- if(SEA.opt.fallback){
32011
- opt.encode = 'utf8';
32012
- return await SEA.decrypt(data, pair, cb, opt);
32013
- }
32014
- }
32015
- var r = await S.parse(new shim.TextDecoder('utf8').decode(ct));
32016
- if(cb){ try{ cb(r) }catch(e){console.log(e)} }
32017
- return r;
32018
- } catch(e) {
32019
- console.log(e);
32020
- SEA.err = e;
32021
- if(SEA.throw){ throw e }
32022
- if(cb){ cb() }
32023
- return;
32024
- }});
32025
-
32026
- module.exports = SEA.decrypt;
32027
- })(USE, './decrypt');
32028
-
32029
- ;USE(function(module){
32030
- var SEA = USE('./root');
32031
- var shim = USE('./shim');
32032
- var S = USE('./settings');
32033
- // Derive shared secret from other's pub and my epub/epriv
32034
- SEA.secret = SEA.secret || (async (key, pair, cb, opt) => { try {
32035
- opt = opt || {};
32036
- if(!pair || !pair.epriv || !pair.epub){
32037
- if(!SEA.I){ throw 'No secret mix.' }
32038
- pair = await SEA.I(null, {what: key, how: 'secret', why: opt.why});
32039
- }
32040
- var pub = key.epub || key;
32041
- var epub = pair.epub;
32042
- var epriv = pair.epriv;
32043
- var ecdhSubtle = shim.ossl || shim.subtle;
32044
- var pubKeyData = keysToEcdhJwk(pub);
32045
- var props = Object.assign({ public: await ecdhSubtle.importKey(...pubKeyData, true, []) },{name: 'ECDH', namedCurve: 'P-256'}); // Thanks to @sirpy !
32046
- var privKeyData = keysToEcdhJwk(epub, epriv);
32047
- var derived = await ecdhSubtle.importKey(...privKeyData, false, ['deriveBits']).then(async (privKey) => {
32048
- // privateKey scope doesn't leak out from here!
32049
- var derivedBits = await ecdhSubtle.deriveBits(props, privKey, 256);
32050
- var rawBits = new Uint8Array(derivedBits);
32051
- var derivedKey = await ecdhSubtle.importKey('raw', rawBits,{ name: 'AES-GCM', length: 256 }, true, [ 'encrypt', 'decrypt' ]);
32052
- return ecdhSubtle.exportKey('jwk', derivedKey).then(({ k }) => k);
32053
- })
32054
- var r = derived;
32055
- if(cb){ try{ cb(r) }catch(e){console.log(e)} }
32056
- return r;
32057
- } catch(e) {
32058
- console.log(e);
32059
- SEA.err = e;
32060
- if(SEA.throw){ throw e }
32061
- if(cb){ cb() }
32062
- return;
32063
- }});
32064
-
32065
- // can this be replaced with settings.jwk?
32066
- var keysToEcdhJwk = (pub, d) => { // d === priv
32067
- //var [ x, y ] = shim.Buffer.from(pub, 'base64').toString('utf8').split(':') // old
32068
- var [ x, y ] = pub.split('.') // new
32069
- var jwk = d ? { d: d } : {}
32070
- return [ // Use with spread returned value...
32071
- 'jwk',
32072
- Object.assign(
32073
- jwk,
32074
- { x: x, y: y, kty: 'EC', crv: 'P-256', ext: true }
32075
- ), // ??? refactor
32076
- {name: 'ECDH', namedCurve: 'P-256'}
32077
- ]
32078
- }
32079
-
32080
- module.exports = SEA.secret;
32081
- })(USE, './secret');
32082
-
32083
- ;USE(function(module){
32084
- var SEA = USE('./root');
32085
- // This is to certify that a group of "certificants" can "put" anything at a group of matched "paths" to the certificate authority's graph
32086
- SEA.certify = SEA.certify || (async (certificants, policy = {}, authority, cb, opt = {}) => { try {
32087
- /*
32088
- The Certify Protocol was made out of love by a Vietnamese code enthusiast. Vietnamese people around the world deserve respect!
32089
- IMPORTANT: A Certificate is like a Signature. No one knows who (authority) created/signed a cert until you put it into their graph.
32090
- "certificants": '*' or a String (Bob.pub) || an Object that contains "pub" as a key || an array of [object || string]. These people will have the rights.
32091
- "policy": A string ('inbox'), or a RAD/LEX object {'*': 'inbox'}, or an Array of RAD/LEX objects or strings. RAD/LEX object can contain key "?" with indexOf("*") > -1 to force key equals certificant pub. This rule is used to check against soul+'/'+key using Gun.text.match or String.match.
32092
- "authority": Key pair or priv of the certificate authority.
32093
- "cb": A callback function after all things are done.
32094
- "opt": If opt.expiry (a timestamp) is set, SEA won't sync data after opt.expiry. If opt.block is set, SEA will look for block before syncing.
32095
- */
32096
- console.log('SEA.certify() is an early experimental community supported method that may change API behavior without warning in any future version.')
32097
-
32098
- certificants = (() => {
32099
- var data = []
32100
- if (certificants) {
32101
- if ((typeof certificants === 'string' || Array.isArray(certificants)) && certificants.indexOf('*') > -1) return '*'
32102
- if (typeof certificants === 'string') return certificants
32103
- if (Array.isArray(certificants)) {
32104
- if (certificants.length === 1 && certificants[0]) return typeof certificants[0] === 'object' && certificants[0].pub ? certificants[0].pub : typeof certificants[0] === 'string' ? certificants[0] : null
32105
- certificants.map(certificant => {
32106
- if (typeof certificant ==='string') data.push(certificant)
32107
- else if (typeof certificant === 'object' && certificant.pub) data.push(certificant.pub)
32108
- })
32109
- }
32110
-
32111
- if (typeof certificants === 'object' && certificants.pub) return certificants.pub
32112
- return data.length > 0 ? data : null
32113
- }
32114
- return
32115
- })()
32116
-
32117
- if (!certificants) return console.log("No certificant found.")
32118
-
32119
- const expiry = opt.expiry && (typeof opt.expiry === 'number' || typeof opt.expiry === 'string') ? parseFloat(opt.expiry) : null
32120
- const readPolicy = (policy || {}).read ? policy.read : null
32121
- const writePolicy = (policy || {}).write ? policy.write : typeof policy === 'string' || Array.isArray(policy) || policy["+"] || policy["#"] || policy["."] || policy["="] || policy["*"] || policy[">"] || policy["<"] ? policy : null
32122
- // The "blacklist" feature is now renamed to "block". Why ? BECAUSE BLACK LIVES MATTER!
32123
- // We can now use 3 keys: block, blacklist, ban
32124
- const block = (opt || {}).block || (opt || {}).blacklist || (opt || {}).ban || {}
32125
- const readBlock = block.read && (typeof block.read === 'string' || (block.read || {})['#']) ? block.read : null
32126
- const writeBlock = typeof block === 'string' ? block : block.write && (typeof block.write === 'string' || block.write['#']) ? block.write : null
32127
-
32128
- if (!readPolicy && !writePolicy) return console.log("No policy found.")
32129
-
32130
- // reserved keys: c, e, r, w, rb, wb
32131
- const data = JSON.stringify({
32132
- c: certificants,
32133
- ...(expiry ? {e: expiry} : {}), // inject expiry if possible
32134
- ...(readPolicy ? {r: readPolicy } : {}), // "r" stands for read, which means read permission.
32135
- ...(writePolicy ? {w: writePolicy} : {}), // "w" stands for write, which means write permission.
32136
- ...(readBlock ? {rb: readBlock} : {}), // inject READ block if possible
32137
- ...(writeBlock ? {wb: writeBlock} : {}), // inject WRITE block if possible
32138
- })
32139
-
32140
- const certificate = await SEA.sign(data, authority, null, {raw:1})
32141
-
32142
- var r = certificate
32143
- if(!opt.raw){ r = 'SEA'+JSON.stringify(r) }
32144
- if(cb){ try{ cb(r) }catch(e){console.log(e)} }
32145
- return r;
32146
- } catch(e) {
32147
- SEA.err = e;
32148
- if(SEA.throw){ throw e }
32149
- if(cb){ cb() }
32150
- return;
32151
- }});
32152
-
32153
- module.exports = SEA.certify;
32154
- })(USE, './certify');
32155
-
32156
- ;USE(function(module){
32157
- var shim = USE('./shim');
32158
- // Practical examples about usage found in tests.
32159
- var SEA = USE('./root');
32160
- SEA.work = USE('./work');
32161
- SEA.sign = USE('./sign');
32162
- SEA.verify = USE('./verify');
32163
- SEA.encrypt = USE('./encrypt');
32164
- SEA.decrypt = USE('./decrypt');
32165
- SEA.certify = USE('./certify');
32166
- //SEA.opt.aeskey = USE('./aeskey'); // not official! // this causes problems in latest WebCrypto.
32167
-
32168
- SEA.random = SEA.random || shim.random;
32169
-
32170
- // This is Buffer used in SEA and usable from Gun/SEA application also.
32171
- // For documentation see https://nodejs.org/api/buffer.html
32172
- SEA.Buffer = SEA.Buffer || USE('./buffer');
32173
-
32174
- // These SEA functions support now ony Promises or
32175
- // async/await (compatible) code, use those like Promises.
32176
- //
32177
- // Creates a wrapper library around Web Crypto API
32178
- // for various AES, ECDSA, PBKDF2 functions we called above.
32179
- // Calculate public key KeyID aka PGPv4 (result: 8 bytes as hex string)
32180
- SEA.keyid = SEA.keyid || (async (pub) => {
32181
- try {
32182
- // base64('base64(x):base64(y)') => shim.Buffer(xy)
32183
- const pb = shim.Buffer.concat(
32184
- pub.replace(/-/g, '+').replace(/_/g, '/').split('.')
32185
- .map((t) => shim.Buffer.from(t, 'base64'))
32186
- )
32187
- // id is PGPv4 compliant raw key
32188
- const id = shim.Buffer.concat([
32189
- shim.Buffer.from([0x99, pb.length / 0x100, pb.length % 0x100]), pb
32190
- ])
32191
- const sha1 = await sha1hash(id)
32192
- const hash = shim.Buffer.from(sha1, 'binary')
32193
- return hash.toString('hex', hash.length - 8) // 16-bit ID as hex
32194
- } catch (e) {
32195
- console.log(e)
32196
- throw e
32197
- }
32198
- });
32199
- // all done!
32200
- // Obviously it is missing MANY necessary features. This is only an alpha release.
32201
- // Please experiment with it, audit what I've done so far, and complain about what needs to be added.
32202
- // SEA should be a full suite that is easy and seamless to use.
32203
- // Again, scroll naer the top, where I provide an EXAMPLE of how to create a user and sign in.
32204
- // Once logged in, the rest of the code you just read handled automatically signing/validating data.
32205
- // But all other behavior needs to be equally easy, like opinionated ways of
32206
- // Adding friends (trusted public keys), sending private messages, etc.
32207
- // Cheers! Tell me what you think.
32208
- ((SEA.window||{}).GUN||{}).SEA = SEA;
32209
-
32210
- module.exports = SEA
32211
- // -------------- END SEA MODULES --------------------
32212
- // -- BEGIN SEA+GUN MODULES: BUNDLED BY DEFAULT UNTIL OTHERS USE SEA ON OWN -------
32213
- })(USE, './sea');
32214
-
32215
- ;USE(function(module){
32216
- var SEA = USE('./sea'), Gun, u;
32217
- if(SEA.window){
32218
- Gun = SEA.window.GUN || {chain:{}};
32219
- } else {
32220
- Gun = USE((u+'' == typeof MODULE?'.':'')+'./gun', 1);
32221
- }
32222
- SEA.GUN = Gun;
32223
-
32224
- function User(root){
32225
- this._ = {$: this};
32226
- }
32227
- User.prototype = (function(){ function F(){}; F.prototype = Gun.chain; return new F() }()) // Object.create polyfill
32228
- User.prototype.constructor = User;
32229
-
32230
- // let's extend the gun chain with a `user` function.
32231
- // only one user can be logged in at a time, per gun instance.
32232
- Gun.chain.user = function(pub){
32233
- var gun = this, root = gun.back(-1), user;
32234
- if(pub){
32235
- pub = SEA.opt.pub((pub._||'')['#']) || pub;
32236
- return root.get('~'+pub);
32237
- }
32238
- if(user = root.back('user')){ return user }
32239
- var root = (root._), at = root, uuid = at.opt.uuid || lex;
32240
- (at = (user = at.user = gun.chain(new User))._).opt = {};
32241
- at.opt.uuid = function(cb){
32242
- var id = uuid(), pub = root.user;
32243
- if(!pub || !(pub = pub.is) || !(pub = pub.pub)){ return id }
32244
- id = '~' + pub + '/' + id;
32245
- if(cb && cb.call){ cb(null, id) }
32246
- return id;
32247
- }
32248
- return user;
32249
- }
32250
- function lex(){ return Gun.state().toString(36).replace('.','') }
32251
- Gun.User = User;
32252
- User.GUN = Gun;
32253
- User.SEA = Gun.SEA = SEA;
32254
- module.exports = User;
32255
- })(USE, './user');
32256
-
32257
- ;USE(function(module){
32258
- var u, Gun = (''+u != typeof GUN)? (GUN||{chain:{}}) : USE((''+u === typeof MODULE?'.':'')+'./gun', 1);
32259
- Gun.chain.then = function(cb, opt){
32260
- var gun = this, p = (new Promise(function(res, rej){
32261
- gun.once(res, opt);
32262
- }));
32263
- return cb? p.then(cb) : p;
32264
- }
32265
- })(USE, './then');
32266
-
32267
- ;USE(function(module){
32268
- var User = USE('./user'), SEA = User.SEA, Gun = User.GUN, noop = function(){};
32269
-
32270
- // Well first we have to actually create a user. That is what this function does.
32271
- User.prototype.create = function(...args){
32272
- var pair = typeof args[0] === 'object' && (args[0].pub || args[0].epub) ? args[0] : typeof args[1] === 'object' && (args[1].pub || args[1].epub) ? args[1] : null;
32273
- var alias = pair && (pair.pub || pair.epub) ? pair.pub : typeof args[0] === 'string' ? args[0] : null;
32274
- var pass = pair && (pair.pub || pair.epub) ? pair : alias && typeof args[1] === 'string' ? args[1] : null;
32275
- var cb = args.filter(arg => typeof arg === 'function')[0] || null; // cb now can stand anywhere, after alias/pass or pair
32276
- var opt = args && args.length > 1 && typeof args[args.length-1] === 'object' ? args[args.length-1] : {}; // opt is always the last parameter which typeof === 'object' and stands after cb
32277
-
32278
- var gun = this, cat = (gun._), root = gun.back(-1);
32279
- cb = cb || noop;
32280
- opt = opt || {};
32281
- if(false !== opt.check){
32282
- var err;
32283
- if(!alias){ err = "No user." }
32284
- if((pass||'').length < 8){ err = "Password too short!" }
32285
- if(err){
32286
- cb({err: Gun.log(err)});
32287
- return gun;
32288
- }
32289
- }
32290
- if(cat.ing){
32291
- (cb || noop)({err: Gun.log("User is already being created or authenticated!"), wait: true});
32292
- return gun;
32293
- }
32294
- cat.ing = true;
32295
- var act = {}, u;
32296
- act.a = function(pubs){
32297
- act.pubs = pubs;
32298
- if(pubs && !opt.already){
32299
- // If we can enforce that a user name is already taken, it might be nice to try, but this is not guaranteed.
32300
- var ack = {err: Gun.log('User already created!')};
32301
- cat.ing = false;
32302
- (cb || noop)(ack);
32303
- gun.leave();
32304
- return;
32305
- }
32306
- act.salt = String.random(64); // pseudo-randomly create a salt, then use PBKDF2 function to extend the password with it.
32307
- SEA.work(pass, act.salt, act.b); // this will take some short amount of time to produce a proof, which slows brute force attacks.
32308
- }
32309
- act.b = function(proof){
32310
- act.proof = proof;
32311
- pair ? act.c(pair) : SEA.pair(act.c) // generate a brand new key pair or use the existing.
32312
- }
32313
- act.c = function(pair){
32314
- var tmp
32315
- act.pair = pair || {};
32316
- if(tmp = cat.root.user){
32317
- tmp._.sea = pair;
32318
- tmp.is = {pub: pair.pub, epub: pair.epub, alias: alias};
32319
- }
32320
- // the user's public key doesn't need to be signed. But everything else needs to be signed with it! // we have now automated it! clean up these extra steps now!
32321
- act.data = {pub: pair.pub};
32322
- act.d();
32323
- }
32324
- act.d = function(){
32325
- act.data.alias = alias;
32326
- act.e();
32327
- }
32328
- act.e = function(){
32329
- act.data.epub = act.pair.epub;
32330
- SEA.encrypt({priv: act.pair.priv, epriv: act.pair.epriv}, act.proof, act.f, {raw:1}); // to keep the private key safe, we AES encrypt it with the proof of work!
32331
- }
32332
- act.f = function(auth){
32333
- act.data.auth = JSON.stringify({ek: auth, s: act.salt});
32334
- act.g(act.data.auth);
32335
- }
32336
- act.g = function(auth){ var tmp;
32337
- act.data.auth = act.data.auth || auth;
32338
- root.get(tmp = '~'+act.pair.pub).put(act.data).on(act.h); // awesome, now we can actually save the user with their public key as their ID.
32339
- var link = {}; link[tmp] = {'#': tmp}; root.get('~@'+alias).put(link).get(tmp).on(act.i); // next up, we want to associate the alias with the public key. So we add it to the alias list.
32340
- }
32341
- act.h = function(data, key, msg, eve){
32342
- eve.off(); act.h.ok = 1; act.i();
32343
- }
32344
- act.i = function(data, key, msg, eve){
32345
- if(eve){ act.i.ok = 1; eve.off() }
32346
- if(!act.h.ok || !act.i.ok){ return }
32347
- cat.ing = false;
32348
- cb({ok: 0, pub: act.pair.pub}); // callback that the user has been created. (Note: ok = 0 because we didn't wait for disk to ack)
32349
- if(noop === cb){ pair ? gun.auth(pair) : gun.auth(alias, pass) } // if no callback is passed, auto-login after signing up.
32350
- }
32351
- root.get('~@'+alias).once(act.a);
32352
- return gun;
32353
- }
32354
- User.prototype.leave = function(opt, cb){
32355
- var gun = this, user = (gun.back(-1)._).user;
32356
- if(user){
32357
- delete user.is;
32358
- delete user._.is;
32359
- delete user._.sea;
32360
- }
32361
- if(SEA.window){
32362
- try{var sS = {};
32363
- sS = SEA.window.sessionStorage;
32364
- delete sS.recall;
32365
- delete sS.pair;
32366
- }catch(e){};
32367
- }
32368
- return gun;
32369
- }
32370
- })(USE, './create');
32371
-
32372
- ;USE(function(module){
32373
- var User = USE('./user'), SEA = User.SEA, Gun = User.GUN, noop = function(){};
32374
- // now that we have created a user, we want to authenticate them!
32375
- User.prototype.auth = function(...args){ // TODO: this PR with arguments need to be cleaned up / refactored.
32376
- var pair = typeof args[0] === 'object' && (args[0].pub || args[0].epub) ? args[0] : typeof args[1] === 'object' && (args[1].pub || args[1].epub) ? args[1] : null;
32377
- var alias = !pair && typeof args[0] === 'string' ? args[0] : null;
32378
- var pass = (alias || (pair && !(pair.priv && pair.epriv))) && typeof args[1] === 'string' ? args[1] : null;
32379
- var cb = args.filter(arg => typeof arg === 'function')[0] || null; // cb now can stand anywhere, after alias/pass or pair
32380
- var opt = args && args.length > 1 && typeof args[args.length-1] === 'object' ? args[args.length-1] : {}; // opt is always the last parameter which typeof === 'object' and stands after cb
32381
-
32382
- var gun = this, cat = (gun._), root = gun.back(-1);
32383
-
32384
- if(cat.ing){
32385
- (cb || noop)({err: Gun.log("User is already being created or authenticated!"), wait: true});
32386
- return gun;
32387
- }
32388
- cat.ing = true;
32389
-
32390
- var act = {}, u, tries = 9;
32391
- act.a = function(data){
32392
- if(!data){ return act.b() }
32393
- if(!data.pub){
32394
- var tmp = []; Object.keys(data).forEach(function(k){ if('_'==k){ return } tmp.push(data[k]) })
32395
- return act.b(tmp);
32396
- }
32397
- if(act.name){ return act.f(data) }
32398
- act.c((act.data = data).auth);
32399
- }
32400
- act.b = function(list){
32401
- var get = (act.list = (act.list||[]).concat(list||[])).shift();
32402
- if(u === get){
32403
- if(act.name){ return act.err('Your user account is not published for dApps to access, please consider syncing it online, or allowing local access by adding your device as a peer.') }
32404
- if(alias && tries--){
32405
- root.get('~@'+alias).once(act.a);
32406
- return;
32407
- }
32408
- return act.err('Wrong user or password.')
32409
- }
32410
- root.get(get).once(act.a);
32411
- }
32412
- act.c = function(auth){
32413
- if(u === auth){ return act.b() }
32414
- if('string' == typeof auth){ return act.c(obj_ify(auth)) } // in case of legacy
32415
- SEA.work(pass, (act.auth = auth).s, act.d, act.enc); // the proof of work is evidence that we've spent some time/effort trying to log in, this slows brute force.
32416
- }
32417
- act.d = function(proof){
32418
- SEA.decrypt(act.auth.ek, proof, act.e, act.enc);
32419
- }
32420
- act.e = function(half){
32421
- if(u === half){
32422
- if(!act.enc){ // try old format
32423
- act.enc = {encode: 'utf8'};
32424
- return act.c(act.auth);
32425
- } act.enc = null; // end backwards
32426
- return act.b();
32427
- }
32428
- act.half = half;
32429
- act.f(act.data);
32430
- }
32431
- act.f = function(pair){
32432
- var half = act.half || {}, data = act.data || {};
32433
- act.g(act.lol = {pub: pair.pub || data.pub, epub: pair.epub || data.epub, priv: pair.priv || half.priv, epriv: pair.epriv || half.epriv});
32434
- }
32435
- act.g = function(pair){
32436
- if(!pair || !pair.pub || !pair.epub){ return act.b() }
32437
- act.pair = pair;
32438
- var user = (root._).user, at = (user._);
32439
- var tmp = at.tag;
32440
- var upt = at.opt;
32441
- at = user._ = root.get('~'+pair.pub)._;
32442
- at.opt = upt;
32443
- // add our credentials in-memory only to our root user instance
32444
- user.is = {pub: pair.pub, epub: pair.epub, alias: alias || pair.pub};
32445
- at.sea = act.pair;
32446
- cat.ing = false;
32447
- try{if(pass && u == (obj_ify(cat.root.graph['~'+pair.pub].auth)||'')[':']){ opt.shuffle = opt.change = pass; } }catch(e){} // migrate UTF8 & Shuffle!
32448
- opt.change? act.z() : (cb || noop)(at);
32449
- if(SEA.window && ((gun.back('user')._).opt||opt).remember){
32450
- // TODO: this needs to be modular.
32451
- try{var sS = {};
32452
- sS = SEA.window.sessionStorage; // TODO: FIX BUG putting on `.is`!
32453
- sS.recall = true;
32454
- sS.pair = JSON.stringify(pair); // auth using pair is more reliable than alias/pass
32455
- }catch(e){}
32456
- }
32457
- try{
32458
- if(root._.tag.auth){ // auth handle might not be registered yet
32459
- (root._).on('auth', at) // TODO: Deprecate this, emit on user instead! Update docs when you do.
32460
- } else { setTimeout(function(){ (root._).on('auth', at) },1) } // if not, hackily add a timeout.
32461
- //at.on('auth', at) // Arrgh, this doesn't work without event "merge" code, but "merge" code causes stack overflow and crashes after logging in & trying to write data.
32462
- }catch(e){
32463
- Gun.log("Your 'auth' callback crashed with:", e);
32464
- }
32465
- }
32466
- act.h = function(data){
32467
- if(!data){ return act.b() }
32468
- alias = data.alias
32469
- if(!alias)
32470
- alias = data.alias = "~" + pair.pub
32471
- if(!data.auth){
32472
- return act.g(pair);
32473
- }
32474
- pair = null;
32475
- act.c((act.data = data).auth);
32476
- }
32477
- act.z = function(){
32478
- // password update so encrypt private key using new pwd + salt
32479
- act.salt = String.random(64); // pseudo-random
32480
- SEA.work(opt.change, act.salt, act.y);
32481
- }
32482
- act.y = function(proof){
32483
- SEA.encrypt({priv: act.pair.priv, epriv: act.pair.epriv}, proof, act.x, {raw:1});
32484
- }
32485
- act.x = function(auth){
32486
- act.w(JSON.stringify({ek: auth, s: act.salt}));
32487
- }
32488
- act.w = function(auth){
32489
- if(opt.shuffle){ // delete in future!
32490
- console.log('migrate core account from UTF8 & shuffle');
32491
- var tmp = {}; Object.keys(act.data).forEach(function(k){ tmp[k] = act.data[k] });
32492
- delete tmp._;
32493
- tmp.auth = auth;
32494
- root.get('~'+act.pair.pub).put(tmp);
32495
- } // end delete
32496
- root.get('~'+act.pair.pub).get('auth').put(auth, cb || noop);
32497
- }
32498
- act.err = function(e){
32499
- var ack = {err: Gun.log(e || 'User cannot be found!')};
32500
- cat.ing = false;
32501
- (cb || noop)(ack);
32502
- }
32503
- act.plugin = function(name){
32504
- if(!(act.name = name)){ return act.err() }
32505
- var tmp = [name];
32506
- if('~' !== name[0]){
32507
- tmp[1] = '~'+name;
32508
- tmp[2] = '~@'+name;
32509
- }
32510
- act.b(tmp);
32511
- }
32512
- if(pair){
32513
- if(pair.priv && pair.epriv)
32514
- act.g(pair);
32515
- else
32516
- root.get('~'+pair.pub).once(act.h);
32517
- } else
32518
- if(alias){
32519
- root.get('~@'+alias).once(act.a);
32520
- } else
32521
- if(!alias && !pass){
32522
- SEA.name(act.plugin);
32523
- }
32524
- return gun;
32525
- }
32526
- function obj_ify(o){
32527
- if('string' != typeof o){ return o }
32528
- try{o = JSON.parse(o);
32529
- }catch(e){o={}};
32530
- return o;
32531
- }
32532
- })(USE, './auth');
32533
-
32534
- ;USE(function(module){
32535
- var User = USE('./user'), SEA = User.SEA, Gun = User.GUN;
32536
- User.prototype.recall = function(opt, cb){
32537
- var gun = this, root = gun.back(-1), tmp;
32538
- opt = opt || {};
32539
- if(opt && opt.sessionStorage){
32540
- if(SEA.window){
32541
- try{
32542
- var sS = {};
32543
- sS = SEA.window.sessionStorage; // TODO: FIX BUG putting on `.is`!
32544
- if(sS){
32545
- (root._).opt.remember = true;
32546
- ((gun.back('user')._).opt||opt).remember = true;
32547
- if(sS.recall || sS.pair) root.user().auth(JSON.parse(sS.pair), cb); // pair is more reliable than alias/pass
32548
- }
32549
- }catch(e){}
32550
- }
32551
- return gun;
32552
- }
32553
- /*
32554
- TODO: copy mhelander's expiry code back in.
32555
- Although, we should check with community,
32556
- should expiry be core or a plugin?
32557
- */
32558
- return gun;
32559
- }
32560
- })(USE, './recall');
32561
-
32562
- ;USE(function(module){
32563
- var User = USE('./user'), SEA = User.SEA, Gun = User.GUN, noop = function(){};
32564
- User.prototype.pair = function(){
32565
- var user = this, proxy; // undeprecated, hiding with proxies.
32566
- try{ proxy = new Proxy({DANGER:'\u2620'}, {get: function(t,p,r){
32567
- if(!user.is || !(user._||'').sea){ return }
32568
- return user._.sea[p];
32569
- }})}catch(e){}
32570
- return proxy;
32571
- }
32572
- // If authenticated user wants to delete his/her account, let's support it!
32573
- User.prototype.delete = async function(alias, pass, cb){
32574
- console.log("user.delete() IS DEPRECATED AND WILL BE MOVED TO A MODULE!!!");
32575
- var gun = this, root = gun.back(-1), user = gun.back('user');
32576
- try {
32577
- user.auth(alias, pass, function(ack){
32578
- var pub = (user.is||{}).pub;
32579
- // Delete user data
32580
- user.map().once(function(){ this.put(null) });
32581
- // Wipe user data from memory
32582
- user.leave();
32583
- (cb || noop)({ok: 0});
32584
- });
32585
- } catch (e) {
32586
- Gun.log('User.delete failed! Error:', e);
32587
- }
32588
- return gun;
32589
- }
32590
- User.prototype.alive = async function(){
32591
- console.log("user.alive() IS DEPRECATED!!!");
32592
- const gunRoot = this.back(-1)
32593
- try {
32594
- // All is good. Should we do something more with actual recalled data?
32595
- await authRecall(gunRoot)
32596
- return gunRoot._.user._
32597
- } catch (e) {
32598
- const err = 'No session!'
32599
- Gun.log(err)
32600
- throw { err }
32601
- }
32602
- }
32603
- User.prototype.trust = async function(user){
32604
- console.log("`.trust` API MAY BE DELETED OR CHANGED OR RENAMED, DO NOT USE!");
32605
- // TODO: BUG!!! SEA `node` read listener needs to be async, which means core needs to be async too.
32606
- //gun.get('alice').get('age').trust(bob);
32607
- if (Gun.is(user)) {
32608
- user.get('pub').get((ctx, ev) => {
32609
- console.log(ctx, ev)
32610
- })
32611
- }
32612
- user.get('trust').get(path).put(theirPubkey);
32613
-
32614
- // do a lookup on this gun chain directly (that gets bob's copy of the data)
32615
- // do a lookup on the metadata trust table for this path (that gets all the pubkeys allowed to write on this path)
32616
- // do a lookup on each of those pubKeys ON the path (to get the collab data "layers")
32617
- // THEN you perform Jachen's mix operation
32618
- // and return the result of that to...
32619
- }
32620
- User.prototype.grant = function(to, cb){
32621
- console.log("`.grant` API MAY BE DELETED OR CHANGED OR RENAMED, DO NOT USE!");
32622
- var gun = this, user = gun.back(-1).user(), pair = user._.sea, path = '';
32623
- gun.back(function(at){ if(at.is){ return } path += (at.get||'') });
32624
- (async function(){
32625
- var enc, sec = await user.get('grant').get(pair.pub).get(path).then();
32626
- sec = await SEA.decrypt(sec, pair);
32627
- if(!sec){
32628
- sec = SEA.random(16).toString();
32629
- enc = await SEA.encrypt(sec, pair);
32630
- user.get('grant').get(pair.pub).get(path).put(enc);
32631
- }
32632
- var pub = to.get('pub').then();
32633
- var epub = to.get('epub').then();
32634
- pub = await pub; epub = await epub;
32635
- var dh = await SEA.secret(epub, pair);
32636
- enc = await SEA.encrypt(sec, dh);
32637
- user.get('grant').get(pub).get(path).put(enc, cb);
32638
- }());
32639
- return gun;
32640
- }
32641
- User.prototype.secret = function(data, cb){
32642
- console.log("`.secret` API MAY BE DELETED OR CHANGED OR RENAMED, DO NOT USE!");
32643
- var gun = this, user = gun.back(-1).user(), pair = user.pair(), path = '';
32644
- gun.back(function(at){ if(at.is){ return } path += (at.get||'') });
32645
- (async function(){
32646
- var enc, sec = await user.get('trust').get(pair.pub).get(path).then();
32647
- sec = await SEA.decrypt(sec, pair);
32648
- if(!sec){
32649
- sec = SEA.random(16).toString();
32650
- enc = await SEA.encrypt(sec, pair);
32651
- user.get('trust').get(pair.pub).get(path).put(enc);
32652
- }
32653
- enc = await SEA.encrypt(data, sec);
32654
- gun.put(enc, cb);
32655
- }());
32656
- return gun;
32657
- }
32658
-
32659
- /**
32660
- * returns the decrypted value, encrypted by secret
32661
- * @returns {Promise<any>}
32662
- // Mark needs to review 1st before officially supported
32663
- User.prototype.decrypt = function(cb) {
32664
- let gun = this,
32665
- path = ''
32666
- gun.back(function(at) {
32667
- if (at.is) {
32668
- return
32669
- }
32670
- path += at.get || ''
32671
- })
32672
- return gun
32673
- .then(async data => {
32674
- if (data == null) {
32675
- return
32676
- }
32677
- const user = gun.back(-1).user()
32678
- const pair = user.pair()
32679
- let sec = await user
32680
- .get('trust')
32681
- .get(pair.pub)
32682
- .get(path)
32683
- sec = await SEA.decrypt(sec, pair)
32684
- if (!sec) {
32685
- return data
32686
- }
32687
- let decrypted = await SEA.decrypt(data, sec)
32688
- return decrypted
32689
- })
32690
- .then(res => {
32691
- cb && cb(res)
32692
- return res
32693
- })
32694
- }
32695
- */
32696
- module.exports = User
32697
- })(USE, './share');
32698
-
32699
- ;USE(function(module){
32700
- var SEA = USE('./sea'), S = USE('./settings'), noop = function() {}, u;
32701
- var Gun = (SEA.window||'').GUN || USE((''+u === typeof MODULE?'.':'')+'./gun', 1);
32702
- // After we have a GUN extension to make user registration/login easy, we then need to handle everything else.
32703
-
32704
- // We do this with a GUN adapter, we first listen to when a gun instance is created (and when its options change)
32705
- Gun.on('opt', function(at){
32706
- if(!at.sea){ // only add SEA once per instance, on the "at" context.
32707
- at.sea = {own: {}};
32708
- at.on('put', check, at); // SEA now runs its firewall on HAM diffs, not all i/o.
32709
- }
32710
- this.to.next(at); // make sure to call the "next" middleware adapter.
32711
- });
32712
-
32713
- // Alright, this next adapter gets run at the per node level in the graph database.
32714
- // correction: 2020 it gets run on each key/value pair in a node upon a HAM diff.
32715
- // This will let us verify that every property on a node has a value signed by a public key we trust.
32716
- // If the signature does not match, the data is just `undefined` so it doesn't get passed on.
32717
- // If it does match, then we transform the in-memory "view" of the data into its plain value (without the signature).
32718
- // Now NOTE! Some data is "system" data, not user data. Example: List of public keys, aliases, etc.
32719
- // This data is self-enforced (the value can only match its ID), but that is handled in the `security` function.
32720
- // From the self-enforced data, we can see all the edges in the graph that belong to a public key.
32721
- // Example: ~ASDF is the ID of a node with ASDF as its public key, signed alias and salt, and
32722
- // its encrypted private key, but it might also have other signed values on it like `profile = <ID>` edge.
32723
- // Using that directed edge's ID, we can then track (in memory) which IDs belong to which keys.
32724
- // Here is a problem: Multiple public keys can "claim" any node's ID, so this is dangerous!
32725
- // This means we should ONLY trust our "friends" (our key ring) public keys, not any ones.
32726
- // I have not yet added that to SEA yet in this alpha release. That is coming soon, but beware in the meanwhile!
32727
-
32728
- function check(msg){ // REVISE / IMPROVE, NO NEED TO PASS MSG/EVE EACH SUB?
32729
- var eve = this, at = eve.as, put = msg.put, soul = put['#'], key = put['.'], val = put[':'], state = put['>'], id = msg['#'], tmp;
32730
- if(!soul || !key){ return }
32731
- if((msg._||'').faith && (at.opt||'').faith && 'function' == typeof msg._){
32732
- SEA.opt.pack(put, function(raw){
32733
- SEA.verify(raw, false, function(data){ // this is synchronous if false
32734
- put['='] = SEA.opt.unpack(data);
32735
- eve.to.next(msg);
32736
- })})
32737
- return
32738
- }
32739
- var no = function(why){ at.on('in', {'@': id, err: msg.err = why}) }; // exploit internal relay stun for now, maybe violates spec, but testing for now. // Note: this may be only the sharded message, not original batch.
32740
- //var no = function(why){ msg.ack(why) };
32741
- (msg._||'').DBG && ((msg._||'').DBG.c = +new Date);
32742
- if(0 <= soul.indexOf('<?')){ // special case for "do not sync data X old" forget
32743
- // 'a~pub.key/b<?9'
32744
- tmp = parseFloat(soul.split('<?')[1]||'');
32745
- if(tmp && (state < (Gun.state() - (tmp * 1000)))){ // sec to ms
32746
- (tmp = msg._) && (tmp.stun) && (tmp.stun--); // THIS IS BAD CODE! It assumes GUN internals do something that will probably change in future, but hacking in now.
32747
- return; // omit!
32748
- }
32749
- }
32750
-
32751
- if('~@' === soul){ // special case for shared system data, the list of aliases.
32752
- check.alias(eve, msg, val, key, soul, at, no); return;
32753
- }
32754
- if('~@' === soul.slice(0,2)){ // special case for shared system data, the list of public keys for an alias.
32755
- check.pubs(eve, msg, val, key, soul, at, no); return;
32756
- }
32757
- //if('~' === soul.slice(0,1) && 2 === (tmp = soul.slice(1)).split('.').length){ // special case, account data for a public key.
32758
- if(tmp = SEA.opt.pub(soul)){ // special case, account data for a public key.
32759
- check.pub(eve, msg, val, key, soul, at, no, at.user||'', tmp); return;
32760
- }
32761
- if(0 <= soul.indexOf('#')){ // special case for content addressing immutable hashed data.
32762
- check.hash(eve, msg, val, key, soul, at, no); return;
32763
- }
32764
- check.any(eve, msg, val, key, soul, at, no, at.user||''); return;
32765
- // removed by dead control flow
32766
- // not handled
32767
- }
32768
- check.hash = function(eve, msg, val, key, soul, at, no){ // mark unbuilt @i001962 's epic hex contrib!
32769
- SEA.work(val, null, function(data){
32770
- function hexToBase64(hexStr) {
32771
- let base64 = "";
32772
- for(let i = 0; i < hexStr.length; i++) {
32773
- base64 += !(i - 1 & 1) ? String.fromCharCode(parseInt(hexStr.substring(i - 1, i + 1), 16)) : ""}
32774
- return btoa(base64);}
32775
- if(data && data === key.split('#').slice(-1)[0]){ return eve.to.next(msg) }
32776
- else if (data && data === hexToBase64(key.split('#').slice(-1)[0])){
32777
- return eve.to.next(msg) }
32778
- no("Data hash not same as hash!");
32779
- }, {name: 'SHA-256'});
32780
- }
32781
- check.alias = function(eve, msg, val, key, soul, at, no){ // Example: {_:#~@, ~@alice: {#~@alice}}
32782
- if(!val){ return no("Data must exist!") } // data MUST exist
32783
- if('~@'+key === link_is(val)){ return eve.to.next(msg) } // in fact, it must be EXACTLY equal to itself
32784
- no("Alias not same!"); // if it isn't, reject.
32785
- };
32786
- check.pubs = function(eve, msg, val, key, soul, at, no){ // Example: {_:#~@alice, ~asdf: {#~asdf}}
32787
- if(!val){ return no("Alias must exist!") } // data MUST exist
32788
- if(key === link_is(val)){ return eve.to.next(msg) } // and the ID must be EXACTLY equal to its property
32789
- no("Alias not same!"); // that way nobody can tamper with the list of public keys.
32790
- };
32791
- check.pub = async function(eve, msg, val, key, soul, at, no, user, pub){ var tmp // Example: {_:#~asdf, hello:'world'~fdsa}}
32792
- const raw = await S.parse(val) || {}
32793
- const verify = (certificate, certificant, cb) => {
32794
- if (certificate.m && certificate.s && certificant && pub)
32795
- // now verify certificate
32796
- return SEA.verify(certificate, pub, data => { // check if "pub" (of the graph owner) really issued this cert
32797
- if (u !== data && u !== data.e && msg.put['>'] && msg.put['>'] > parseFloat(data.e)) return no("Certificate expired.") // certificate expired
32798
- // "data.c" = a list of certificants/certified users
32799
- // "data.w" = lex WRITE permission, in the future, there will be "data.r" which means lex READ permission
32800
- if (u !== data && data.c && data.w && (data.c === certificant || data.c.indexOf('*' || 0) > -1)) {
32801
- // ok, now "certificant" is in the "certificants" list, but is "path" allowed? Check path
32802
- let path = soul.indexOf('/') > -1 ? soul.replace(soul.substring(0, soul.indexOf('/') + 1), '') : ''
32803
- String.match = String.match || Gun.text.match
32804
- const w = Array.isArray(data.w) ? data.w : typeof data.w === 'object' || typeof data.w === 'string' ? [data.w] : []
32805
- for (const lex of w) {
32806
- if ((String.match(path, lex['#']) && String.match(key, lex['.'])) || (!lex['.'] && String.match(path, lex['#'])) || (!lex['#'] && String.match(key, lex['.'])) || String.match((path ? path + '/' + key : key), lex['#'] || lex)) {
32807
- // is Certificant forced to present in Path
32808
- if (lex['+'] && lex['+'].indexOf('*') > -1 && path && path.indexOf(certificant) == -1 && key.indexOf(certificant) == -1) return no(`Path "${path}" or key "${key}" must contain string "${certificant}".`)
32809
- // path is allowed, but is there any WRITE block? Check it out
32810
- if (data.wb && (typeof data.wb === 'string' || ((data.wb || {})['#']))) { // "data.wb" = path to the WRITE block
32811
- var root = eve.as.root.$.back(-1)
32812
- if (typeof data.wb === 'string' && '~' !== data.wb.slice(0, 1)) root = root.get('~' + pub)
32813
- return root.get(data.wb).get(certificant).once(value => { // TODO: INTENT TO DEPRECATE.
32814
- if (value && (value === 1 || value === true)) return no(`Certificant ${certificant} blocked.`)
32815
- return cb(data)
32816
- })
32817
- }
32818
- return cb(data)
32819
- }
32820
- }
32821
- return no("Certificate verification fail.")
32822
- }
32823
- })
32824
- return
32825
- }
32826
-
32827
- if ('pub' === key && '~' + pub === soul) {
32828
- if (val === pub) return eve.to.next(msg) // the account MUST match `pub` property that equals the ID of the public key.
32829
- return no("Account not same!")
32830
- }
32831
-
32832
- if ((tmp = user.is) && tmp.pub && !raw['*'] && !raw['+'] && (pub === tmp.pub || (pub !== tmp.pub && ((msg._.msg || {}).opt || {}).cert))){
32833
- SEA.opt.pack(msg.put, packed => {
32834
- SEA.sign(packed, (user._).sea, async function(data) {
32835
- if (u === data) return no(SEA.err || 'Signature fail.')
32836
- msg.put[':'] = {':': tmp = SEA.opt.unpack(data.m), '~': data.s}
32837
- msg.put['='] = tmp
32838
-
32839
- // if writing to own graph, just allow it
32840
- if (pub === user.is.pub) {
32841
- if (tmp = link_is(val)) (at.sea.own[tmp] = at.sea.own[tmp] || {})[pub] = 1
32842
- JSON.stringifyAsync(msg.put[':'], function(err,s){
32843
- if(err){ return no(err || "Stringify error.") }
32844
- msg.put[':'] = s;
32845
- return eve.to.next(msg);
32846
- })
32847
- return
32848
- }
32849
-
32850
- // if writing to other's graph, check if cert exists then try to inject cert into put, also inject self pub so that everyone can verify the put
32851
- if (pub !== user.is.pub && ((msg._.msg || {}).opt || {}).cert) {
32852
- const cert = await S.parse(msg._.msg.opt.cert)
32853
- // even if cert exists, we must verify it
32854
- if (cert && cert.m && cert.s)
32855
- verify(cert, user.is.pub, _ => {
32856
- msg.put[':']['+'] = cert // '+' is a certificate
32857
- msg.put[':']['*'] = user.is.pub // '*' is pub of the user who puts
32858
- JSON.stringifyAsync(msg.put[':'], function(err,s){
32859
- if(err){ return no(err || "Stringify error.") }
32860
- msg.put[':'] = s;
32861
- return eve.to.next(msg);
32862
- })
32863
- return
32864
- })
32865
- }
32866
- }, {raw: 1})
32867
- })
32868
- return;
32869
- }
32870
-
32871
- SEA.opt.pack(msg.put, packed => {
32872
- SEA.verify(packed, raw['*'] || pub, function(data){ var tmp;
32873
- data = SEA.opt.unpack(data);
32874
- if (u === data) return no("Unverified data.") // make sure the signature matches the account it claims to be on. // reject any updates that are signed with a mismatched account.
32875
- if ((tmp = link_is(data)) && pub === SEA.opt.pub(tmp)) (at.sea.own[tmp] = at.sea.own[tmp] || {})[pub] = 1
32876
-
32877
- // check if cert ('+') and putter's pub ('*') exist
32878
- if (raw['+'] && raw['+']['m'] && raw['+']['s'] && raw['*'])
32879
- // now verify certificate
32880
- verify(raw['+'], raw['*'], _ => {
32881
- msg.put['='] = data;
32882
- return eve.to.next(msg);
32883
- })
32884
- else {
32885
- msg.put['='] = data;
32886
- return eve.to.next(msg);
32887
- }
32888
- });
32889
- })
32890
- return
32891
- };
32892
- check.any = function(eve, msg, val, key, soul, at, no, user){ var tmp, pub;
32893
- if(at.opt.secure){ return no("Soul missing public key at '" + key + "'.") }
32894
- // TODO: Ask community if should auto-sign non user-graph data.
32895
- at.on('secure', function(msg){ this.off();
32896
- if(!at.opt.secure){ return eve.to.next(msg) }
32897
- no("Data cannot be changed.");
32898
- }).on.on('secure', msg);
32899
- return;
32900
- }
32901
-
32902
- var valid = Gun.valid, link_is = function(d,l){ return 'string' == typeof (l = valid(d)) && l }, state_ify = (Gun.state||'').ify;
32903
-
32904
- var pubcut = /[^\w_-]/; // anything not alphanumeric or _ -
32905
- SEA.opt.pub = function(s){
32906
- if(!s){ return }
32907
- s = s.split('~');
32908
- if(!s || !(s = s[1])){ return }
32909
- s = s.split(pubcut).slice(0,2);
32910
- if(!s || 2 != s.length){ return }
32911
- if('@' === (s[0]||'')[0]){ return }
32912
- s = s.slice(0,2).join('.');
32913
- return s;
32914
- }
32915
- SEA.opt.stringy = function(t){
32916
- // TODO: encrypt etc. need to check string primitive. Make as breaking change.
32917
- }
32918
- SEA.opt.pack = function(d,cb,k, n,s){ var tmp, f; // pack for verifying
32919
- if(SEA.opt.check(d)){ return cb(d) }
32920
- if(d && d['#'] && d['.'] && d['>']){ tmp = d[':']; f = 1 }
32921
- JSON.parseAsync(f? tmp : d, function(err, meta){
32922
- var sig = ((u !== (meta||'')[':']) && (meta||'')['~']); // or just ~ check?
32923
- if(!sig){ cb(d); return }
32924
- cb({m: {'#':s||d['#'],'.':k||d['.'],':':(meta||'')[':'],'>':d['>']||Gun.state.is(n, k)}, s: sig});
32925
- });
32926
- }
32927
- var O = SEA.opt;
32928
- SEA.opt.unpack = function(d, k, n){ var tmp;
32929
- if(u === d){ return }
32930
- if(d && (u !== (tmp = d[':']))){ return tmp }
32931
- k = k || O.fall_key; if(!n && O.fall_val){ n = {}; n[k] = O.fall_val }
32932
- if(!k || !n){ return }
32933
- if(d === n[k]){ return d }
32934
- if(!SEA.opt.check(n[k])){ return d }
32935
- var soul = (n && n._ && n._['#']) || O.fall_soul, s = Gun.state.is(n, k) || O.fall_state;
32936
- if(d && 4 === d.length && soul === d[0] && k === d[1] && fl(s) === fl(d[3])){
32937
- return d[2];
32938
- }
32939
- if(s < SEA.opt.shuffle_attack){
32940
- return d;
32941
- }
32942
- }
32943
- SEA.opt.shuffle_attack = 1546329600000; // Jan 1, 2019
32944
- var fl = Math.floor; // TODO: Still need to fix inconsistent state issue.
32945
- // TODO: Potential bug? If pub/priv key starts with `-`? IDK how possible.
32946
-
32947
- })(USE, './index');
32948
- }());
32949
-
32950
-
32951
31401
  /***/ }),
32952
31402
 
32953
31403
  /***/ "./node_modules/has-property-descriptors/index.js":
@@ -58396,6 +56846,17 @@ module.exports = function whichTypedArray(value) {
58396
56846
  "use strict";
58397
56847
  module.exports = __WEBPACK_EXTERNAL_MODULE_gun__;
58398
56848
 
56849
+ /***/ }),
56850
+
56851
+ /***/ "gun/sea":
56852
+ /*!**************************!*\
56853
+ !*** external "Gun.SEA" ***!
56854
+ \**************************/
56855
+ /***/ ((module) => {
56856
+
56857
+ "use strict";
56858
+ module.exports = __WEBPACK_EXTERNAL_MODULE_gun_sea__;
56859
+
58399
56860
  /***/ })
58400
56861
 
58401
56862
  /******/ });
@@ -58500,7 +56961,7 @@ var __webpack_exports__ = {};
58500
56961
  (() => {
58501
56962
  "use strict";
58502
56963
  /*!************************************!*\
58503
- !*** ./src/index.ts + 278 modules ***!
56964
+ !*** ./src/index.ts + 277 modules ***!
58504
56965
  \************************************/
58505
56966
  // ESM COMPAT FLAG
58506
56967
  __webpack_require__.r(__webpack_exports__);
@@ -58521,7 +56982,7 @@ __webpack_require__.d(__webpack_exports__, {
58521
56982
  PluginCategory: () => (/* reexport */ PluginCategory),
58522
56983
  RxJS: () => (/* reexport */ RxJS),
58523
56984
  RxJSHolster: () => (/* reexport */ RxJSHolster),
58524
- SEA: () => (/* reexport */ (sea_default())),
56985
+ SEA: () => (/* reexport */ (external_Gun_SEA_default())),
58525
56986
  ShogunCore: () => (/* reexport */ ShogunCore),
58526
56987
  ShogunStorage: () => (/* reexport */ ShogunStorage),
58527
56988
  Web3Connector: () => (/* reexport */ Web3Connector),
@@ -120331,6 +118792,12 @@ var ZkCredentials = /** @class */ (function () {
120331
118792
 
120332
118793
 
120333
118794
 
118795
+ // EXTERNAL MODULE: external "Gun"
118796
+ var external_Gun_ = __webpack_require__("gun");
118797
+ var external_Gun_default = /*#__PURE__*/__webpack_require__.n(external_Gun_);
118798
+ // EXTERNAL MODULE: external "Gun.SEA"
118799
+ var external_Gun_SEA_ = __webpack_require__("gun/sea");
118800
+ var external_Gun_SEA_default = /*#__PURE__*/__webpack_require__.n(external_Gun_SEA_);
120334
118801
  // EXTERNAL MODULE: ./node_modules/gun/lib/then.js
120335
118802
  var then = __webpack_require__("./node_modules/gun/lib/then.js");
120336
118803
  // EXTERNAL MODULE: ./node_modules/gun/lib/radix.js
@@ -120343,18 +118810,12 @@ var store = __webpack_require__("./node_modules/gun/lib/store.js");
120343
118810
  var rindexed = __webpack_require__("./node_modules/gun/lib/rindexed.js");
120344
118811
  // EXTERNAL MODULE: ./node_modules/gun/lib/webrtc.js
120345
118812
  var webrtc = __webpack_require__("./node_modules/gun/lib/webrtc.js");
120346
- // EXTERNAL MODULE: external "Gun"
120347
- var external_Gun_ = __webpack_require__("gun");
120348
- var external_Gun_default = /*#__PURE__*/__webpack_require__.n(external_Gun_);
120349
- // EXTERNAL MODULE: ./node_modules/gun/sea.js
120350
- var sea = __webpack_require__("./node_modules/gun/sea.js");
120351
- var sea_default = /*#__PURE__*/__webpack_require__.n(sea);
120352
- ;// ./src/gundb/min.ts
120353
-
118813
+ ;// ./src/gundb/gun-es.ts
118814
+ // Import Gun and SEA FIRST - extensions depend on Gun.chain being defined
120354
118815
 
120355
118816
 
118817
+ // Now import Gun extensions - they can safely access Gun.chain
120356
118818
 
120357
- ;// ./src/gundb/gun-es.ts
120358
118819
 
120359
118820
 
120360
118821