|
@@ -6,8 +6,8 @@
|
|
|
if(typeof global !== "undefined"){ root = global }
|
|
|
root = root || {};
|
|
|
var console = root.console || {log: function(){}};
|
|
|
- function USE(arg){
|
|
|
- return arg.slice? USE[R(arg)] : function(mod, path){
|
|
|
+ function USE(arg, req){
|
|
|
+ return req? require(arg) : arg.slice? USE[R(arg)] : function(mod, path){
|
|
|
arg(mod = {exports: {}});
|
|
|
USE[R(path)] = mod.exports;
|
|
|
}
|
|
@@ -20,12 +20,24 @@
|
|
|
|
|
|
;USE(function(module){
|
|
|
|
|
|
-
|
|
|
+
|
|
|
+
|
|
|
|
|
|
|
|
|
- function SEA(){}
|
|
|
- if(typeof window !== "undefined"){ (SEA.window = window).SEA = SEA }
|
|
|
+ if(typeof window !== "undefined"){ module.window = window }
|
|
|
|
|
|
+ var tmp = module.window || module;
|
|
|
+ var SEA = tmp.SEA || function(){};
|
|
|
+
|
|
|
+ if(SEA.window = module.window){ try{
|
|
|
+ SEA.window.SEA = SEA;
|
|
|
+ tmp = document.createEvent('CustomEvent');
|
|
|
+ tmp.initCustomEvent('extension', false, false, {type: "SEA"});
|
|
|
+ (window.dispatchEvent || window.fireEvent)(tmp);
|
|
|
+ window.postMessage({type: "SEA"}, '*');
|
|
|
+ } catch(e){} }
|
|
|
+
|
|
|
+ try{ if(typeof common !== "undefined"){ common.exports = SEA } }catch(e){}
|
|
|
module.exports = SEA;
|
|
|
})(USE, './root');
|
|
|
|
|
@@ -148,7 +160,7 @@
|
|
|
const Buffer = USE('./buffer')
|
|
|
const api = {Buffer: Buffer}
|
|
|
|
|
|
- if (typeof __webpack_require__ === 'function' || typeof window !== 'undefined') {
|
|
|
+ if (typeof window !== 'undefined') {
|
|
|
var crypto = window.crypto || window.msCrypto;
|
|
|
var subtle = crypto.subtle || crypto.webkitSubtle;
|
|
|
const TextEncoder = window.TextEncoder
|
|
@@ -162,9 +174,9 @@
|
|
|
})
|
|
|
} else {
|
|
|
try{
|
|
|
- var crypto = require('crypto');
|
|
|
- const { subtle } = require('@trust/webcrypto')
|
|
|
- const { TextEncoder, TextDecoder } = require('text-encoding')
|
|
|
+ var crypto = USE('crypto', 1);
|
|
|
+ const { subtle } = USE('@trust/webcrypto', 1)
|
|
|
+ const { TextEncoder, TextDecoder } = USE('text-encoding', 1)
|
|
|
Object.assign(api, {
|
|
|
crypto,
|
|
|
subtle,
|
|
@@ -173,7 +185,7 @@
|
|
|
random: (len) => Buffer.from(crypto.randomBytes(len))
|
|
|
});
|
|
|
|
|
|
- const WebCrypto = require('node-webcrypto-ossl')
|
|
|
+ const WebCrypto = USE('node-webcrypto-ossl', 1)
|
|
|
api.ossl = new WebCrypto({directory: 'ossl'}).subtle
|
|
|
|
|
|
|
|
@@ -189,6 +201,7 @@
|
|
|
})(USE, './shim');
|
|
|
|
|
|
;USE(function(module){
|
|
|
+ const SEA = USE('./root');
|
|
|
const Buffer = USE('./buffer')
|
|
|
const settings = {}
|
|
|
|
|
@@ -225,6 +238,7 @@
|
|
|
jwk: keysToEcdsaJwk,
|
|
|
recall: authsettings
|
|
|
})
|
|
|
+ SEA.opt = settings;
|
|
|
module.exports = settings
|
|
|
})(USE, './settings');
|
|
|
|
|
@@ -267,49 +281,40 @@
|
|
|
var SEA = USE('./root');
|
|
|
var shim = USE('./shim');
|
|
|
var S = USE('./settings');
|
|
|
+ var sha = USE('./sha256');
|
|
|
var u;
|
|
|
|
|
|
- SEA.work = async (data, pair, cb) => { try {
|
|
|
- var salt = pair.epub || pair;
|
|
|
+ SEA.work = SEA.work || (async (data, pair, cb, opt) => { try {
|
|
|
+ var salt = (pair||{}).epub || pair;
|
|
|
+ var opt = opt || {};
|
|
|
if(salt instanceof Function){
|
|
|
cb = salt;
|
|
|
salt = u;
|
|
|
}
|
|
|
salt = salt || shim.random(9);
|
|
|
- if (SEA.window) {
|
|
|
-
|
|
|
- const key = await shim.subtle.importKey(
|
|
|
- 'raw', new shim.TextEncoder().encode(data), { name: 'PBKDF2' }, false, ['deriveBits']
|
|
|
- )
|
|
|
- const result = await shim.subtle.deriveBits({
|
|
|
- name: 'PBKDF2',
|
|
|
- iterations: S.pbkdf2.iter,
|
|
|
- salt: new shim.TextEncoder().encode(salt),
|
|
|
- hash: S.pbkdf2.hash,
|
|
|
- }, key, S.pbkdf2.ks * 8)
|
|
|
- data = shim.random(data.length)
|
|
|
- const r = shim.Buffer.from(result, 'binary').toString('utf8')
|
|
|
- if(cb){ try{ cb(r) }catch(e){console.log(e)} }
|
|
|
- return r;
|
|
|
+ if('SHA-256' === opt.name){
|
|
|
+ var rsha = shim.Buffer.from(await sha(data), 'binary').toString('utf8')
|
|
|
+ if(cb){ try{ cb(rsha) }catch(e){console.log(e)} }
|
|
|
+ return rsha;
|
|
|
}
|
|
|
-
|
|
|
- const crypto = shim.crypto;
|
|
|
- const hash = crypto.pbkdf2Sync(
|
|
|
- data,
|
|
|
- new shim.TextEncoder().encode(salt),
|
|
|
- S.pbkdf2.iter,
|
|
|
- S.pbkdf2.ks,
|
|
|
- S.pbkdf2.hash.replace('-', '').toLowerCase()
|
|
|
+ const key = await (shim.ossl || shim.subtle).importKey(
|
|
|
+ 'raw', new shim.TextEncoder().encode(data), { name: opt.name || 'PBKDF2' }, false, ['deriveBits']
|
|
|
)
|
|
|
- data = shim.random(data.length)
|
|
|
- const r = hash && hash.toString('utf8')
|
|
|
+ const result = await (shim.ossl || shim.subtle).deriveBits({
|
|
|
+ name: opt.name || 'PBKDF2',
|
|
|
+ iterations: opt.iterations || S.pbkdf2.iter,
|
|
|
+ salt: new shim.TextEncoder().encode(opt.salt || salt),
|
|
|
+ hash: opt.hash || S.pbkdf2.hash,
|
|
|
+ }, key, opt.length || (S.pbkdf2.ks * 8))
|
|
|
+ data = shim.random(data.length)
|
|
|
+ const r = shim.Buffer.from(result, 'binary').toString('utf8')
|
|
|
if(cb){ try{ cb(r) }catch(e){console.log(e)} }
|
|
|
return r;
|
|
|
} catch(e) {
|
|
|
SEA.err = e;
|
|
|
if(cb){ cb() }
|
|
|
return;
|
|
|
- }}
|
|
|
+ }});
|
|
|
|
|
|
module.exports = SEA.work;
|
|
|
})(USE, './work');
|
|
@@ -321,7 +326,7 @@
|
|
|
var Buff = (typeof Buffer !== 'undefined')? Buffer : shim.Buffer;
|
|
|
|
|
|
|
|
|
- SEA.pair = async (cb) => { try {
|
|
|
+ SEA.pair = SEA.pair || (async (cb) => { try {
|
|
|
|
|
|
const ecdhSubtle = shim.ossl || shim.subtle
|
|
|
|
|
@@ -372,7 +377,7 @@
|
|
|
SEA.err = e;
|
|
|
if(cb){ cb() }
|
|
|
return;
|
|
|
- }}
|
|
|
+ }});
|
|
|
|
|
|
module.exports = SEA.pair;
|
|
|
})(USE, './pair');
|
|
@@ -383,7 +388,7 @@
|
|
|
var S = USE('./settings');
|
|
|
var sha256hash = USE('./sha256');
|
|
|
|
|
|
- SEA.sign = async (data, pair, cb) => { try {
|
|
|
+ SEA.sign = SEA.sign || (async (data, pair, cb) => { try {
|
|
|
if(data && data.slice
|
|
|
&& 'SEA{' === data.slice(0,4)
|
|
|
&& '"m":' === data.slice(4,8)){
|
|
@@ -409,7 +414,7 @@
|
|
|
SEA.err = e;
|
|
|
if(cb){ cb() }
|
|
|
return;
|
|
|
- }}
|
|
|
+ }});
|
|
|
|
|
|
module.exports = SEA.sign;
|
|
|
})(USE, './sign');
|
|
@@ -422,7 +427,7 @@
|
|
|
var parse = USE('./parse');
|
|
|
var u;
|
|
|
|
|
|
- SEA.verify = async (data, pair, cb) => { try {
|
|
|
+ SEA.verify = SEA.verify || (async (data, pair, cb) => { try {
|
|
|
const json = parse(data)
|
|
|
if(false === pair){
|
|
|
const raw = (json !== data)?
|
|
@@ -447,7 +452,7 @@
|
|
|
SEA.err = e;
|
|
|
if(cb){ cb() }
|
|
|
return;
|
|
|
- }}
|
|
|
+ }});
|
|
|
|
|
|
module.exports = SEA.verify;
|
|
|
})(USE, './verify');
|
|
@@ -472,13 +477,13 @@
|
|
|
var S = USE('./settings');
|
|
|
var aeskey = USE('./aeskey');
|
|
|
|
|
|
- SEA.encrypt = async (data, pair, cb, opt) => { try {
|
|
|
+ SEA.encrypt = SEA.encrypt || (async (data, pair, cb, opt) => { try {
|
|
|
var opt = opt || {};
|
|
|
const key = pair.epriv || pair;
|
|
|
const msg = JSON.stringify(data)
|
|
|
const rand = {s: shim.random(8), iv: shim.random(16)};
|
|
|
const ct = await aeskey(key, rand.s, opt)
|
|
|
- .then((aes) => shim.subtle.encrypt({
|
|
|
+ .then((aes) => ( shim.subtle).encrypt({
|
|
|
name: opt.name || 'AES-GCM', iv: new Uint8Array(rand.iv)
|
|
|
}, aes, new shim.TextEncoder().encode(msg)))
|
|
|
const r = 'SEA'+JSON.stringify({
|
|
@@ -493,7 +498,7 @@
|
|
|
SEA.err = e;
|
|
|
if(cb){ cb() }
|
|
|
return;
|
|
|
- }}
|
|
|
+ }});
|
|
|
|
|
|
module.exports = SEA.encrypt;
|
|
|
})(USE, './encrypt');
|
|
@@ -505,23 +510,22 @@
|
|
|
var aeskey = USE('./aeskey');
|
|
|
var parse = USE('./parse');
|
|
|
|
|
|
- SEA.decrypt = async (data, pair, cb, opt) => { try {
|
|
|
+ SEA.decrypt = SEA.decrypt || (async (data, pair, cb, opt) => { try {
|
|
|
var opt = opt || {};
|
|
|
const key = pair.epriv || pair;
|
|
|
const json = parse(data)
|
|
|
const ct = await aeskey(key, shim.Buffer.from(json.s, 'utf8'), opt)
|
|
|
- .then((aes) => shim.subtle.decrypt({
|
|
|
+ .then((aes) => ( shim.subtle).decrypt({
|
|
|
name: opt.name || 'AES-GCM', iv: new Uint8Array(shim.Buffer.from(json.iv, 'utf8'))
|
|
|
}, aes, new Uint8Array(shim.Buffer.from(json.ct, 'utf8'))))
|
|
|
const r = parse(new shim.TextDecoder('utf8').decode(ct))
|
|
|
-
|
|
|
if(cb){ try{ cb(r) }catch(e){console.log(e)} }
|
|
|
return r;
|
|
|
} catch(e) {
|
|
|
SEA.err = e;
|
|
|
if(cb){ cb() }
|
|
|
return;
|
|
|
- }}
|
|
|
+ }});
|
|
|
|
|
|
module.exports = SEA.decrypt;
|
|
|
})(USE, './decrypt');
|
|
@@ -531,7 +535,7 @@
|
|
|
var shim = USE('./shim');
|
|
|
var S = USE('./settings');
|
|
|
|
|
|
- SEA.secret = async (key, pair, cb) => { try {
|
|
|
+ SEA.secret = SEA.secret || (async (key, pair, cb) => { try {
|
|
|
const pub = key.epub || key
|
|
|
const epub = pair.epub
|
|
|
const epriv = pair.epriv
|
|
@@ -555,7 +559,7 @@
|
|
|
SEA.err = e;
|
|
|
if(cb){ cb() }
|
|
|
return;
|
|
|
- }}
|
|
|
+ }});
|
|
|
|
|
|
const keysToEcdhJwk = (pub, d) => {
|
|
|
|
|
@@ -605,7 +609,7 @@
|
|
|
SEA.encrypt = USE('./encrypt');
|
|
|
SEA.decrypt = USE('./decrypt');
|
|
|
|
|
|
- SEA.random = getRandomBytes;
|
|
|
+ SEA.random = SEA.random || getRandomBytes;
|
|
|
|
|
|
|
|
|
|
|
@@ -613,7 +617,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
- SEA.Buffer = Buffer;
|
|
|
+ SEA.Buffer = SEA.Buffer || Buffer;
|
|
|
|
|
|
|
|
|
|
|
@@ -621,7 +625,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
- SEA.keyid = async (pub) => {
|
|
|
+ SEA.keyid = SEA.keyid || (async (pub) => {
|
|
|
try {
|
|
|
|
|
|
const pb = Buffer.concat(
|
|
@@ -639,7 +643,7 @@
|
|
|
console.log(e)
|
|
|
throw e
|
|
|
}
|
|
|
- }
|
|
|
+ });
|
|
|
|
|
|
|
|
|
|
|
@@ -649,7 +653,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
- var Gun = (SEA.window||{}).Gun || require('./gun');
|
|
|
+ var Gun = (SEA.window||{}).Gun || USE('./gun', 1);
|
|
|
Gun.SEA = SEA;
|
|
|
SEA.Gun = Gun;
|
|
|
|
|
@@ -662,9 +666,9 @@
|
|
|
|
|
|
const queryGunAliases = (alias, gunRoot) => new Promise((resolve, reject) => {
|
|
|
|
|
|
- gunRoot.get('~@'+alias).get((rat, rev) => {
|
|
|
- rev.off();
|
|
|
- if (!rat.put) {
|
|
|
+ gunRoot.get('~@'+alias).once((data, key) => {
|
|
|
+
|
|
|
+ if (!data) {
|
|
|
|
|
|
const err = 'No user!'
|
|
|
Gun.log(err)
|
|
@@ -674,19 +678,18 @@
|
|
|
const aliases = []
|
|
|
let c = 0
|
|
|
|
|
|
- Gun.obj.map(rat.put, (at, pub) => {
|
|
|
+ Gun.obj.map(data, (at, pub) => {
|
|
|
if (!pub.slice || '~' !== pub.slice(0, 1)) {
|
|
|
|
|
|
return
|
|
|
}
|
|
|
++c
|
|
|
|
|
|
- gunRoot.get(pub).get((at, ev) => {
|
|
|
+ gunRoot.get(pub).once(data => {
|
|
|
pub = pub.slice(1)
|
|
|
- ev.off()
|
|
|
--c
|
|
|
- if (at.put){
|
|
|
- aliases.push({ pub, at })
|
|
|
+ if (data){
|
|
|
+ aliases.push({ pub, put: data })
|
|
|
}
|
|
|
if (!c && (c = -1)) {
|
|
|
resolve(aliases)
|
|
@@ -710,7 +713,7 @@
|
|
|
const authenticate = async (alias, pass, gunRoot) => {
|
|
|
|
|
|
const aliases = (await queryGunAliases(alias, gunRoot))
|
|
|
- .filter(({ pub, at: { put } = {} } = {}) => !!pub && !!put)
|
|
|
+ .filter(a => !!a.pub && !!a.put)
|
|
|
|
|
|
if (!aliases.length) {
|
|
|
throw { err: 'Public key does not exist!' }
|
|
@@ -718,14 +721,14 @@
|
|
|
let err
|
|
|
|
|
|
|
|
|
- const users = await Promise.all(aliases.map(async ({ at: at, pub: pub }, i) => {
|
|
|
+ const users = await Promise.all(aliases.map(async (a, i) => {
|
|
|
|
|
|
- const auth = parseProps(at.put.auth)
|
|
|
+ const auth = parseProps(a.put.auth)
|
|
|
|
|
|
|
|
|
try {
|
|
|
const proof = await SEA.work(pass, auth.s)
|
|
|
- const props = { pub: pub, proof: proof, at: at }
|
|
|
+
|
|
|
|
|
|
|
|
|
MARK TO @mhelander : pub vs epub!???
|
|
@@ -733,24 +736,24 @@
|
|
|
const salt = auth.salt
|
|
|
const sea = await SEA.decrypt(auth.ek, proof)
|
|
|
if (!sea) {
|
|
|
- err = 'Failed to decrypt secret! ' + i +'/'+aliases.length;
|
|
|
+ err = 'Failed to decrypt secret! ' + (i+1) +'/'+aliases.length;
|
|
|
return
|
|
|
}
|
|
|
|
|
|
|
|
|
const priv = sea.priv
|
|
|
const epriv = sea.epriv
|
|
|
- const epub = at.put.epub
|
|
|
+ const epub = a.put.epub
|
|
|
|
|
|
err = null
|
|
|
- if(typeof window !== 'undefined'){
|
|
|
- var tmp = window.sessionStorage;
|
|
|
+ if(SEA.window){
|
|
|
+ var tmp = SEA.window.sessionStorage;
|
|
|
if(tmp && gunRoot._.opt.remember){
|
|
|
- window.sessionStorage.alias = alias;
|
|
|
- window.sessionStorage.tmp = pass;
|
|
|
+ SEA.window.sessionStorage.alias = alias;
|
|
|
+ SEA.window.sessionStorage.tmp = pass;
|
|
|
}
|
|
|
}
|
|
|
- return Object.assign(props, { priv: priv, salt: salt, epub: epub, epriv: epriv })
|
|
|
+ return {priv: priv, pub: a.put.pub, salt: salt, epub: epub, epriv: epriv };
|
|
|
} catch (e) {
|
|
|
err = 'Failed to decrypt secret!'
|
|
|
throw { err }
|
|
@@ -862,10 +865,25 @@
|
|
|
const finalizeLogin = async (alias, key, gunRoot, opts) => {
|
|
|
const user = gunRoot._.user
|
|
|
|
|
|
-
|
|
|
+ var tmp = user._.tag;
|
|
|
var opt = user._.opt;
|
|
|
- user._ = key.at.$._;
|
|
|
+ user._ = gunRoot.get('~'+key.pub)._;
|
|
|
user._.opt = opt;
|
|
|
+ var tags = user._.tag;
|
|
|
+
|
|
|
+
|
|
|
+ var t = tags[tag.tag];
|
|
|
+ console.log("hm??", tag, t);
|
|
|
+ if(!t){
|
|
|
+ tags[tag.tag] = tag;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if(tag.last){
|
|
|
+ tag.last.to = t.to;
|
|
|
+ t.last = tag.last = t.last || tag.last;
|
|
|
+ }
|
|
|
+ t.to = tag.to;
|
|
|
+ })*/
|
|
|
|
|
|
|
|
|
|
|
@@ -880,7 +898,8 @@
|
|
|
|
|
|
|
|
|
try {
|
|
|
- gunRoot._.on('auth', user._)
|
|
|
+ gunRoot._.on('auth', user._)
|
|
|
+
|
|
|
} catch (e) {
|
|
|
console.log('Your \'auth\' callback crashed with:', e)
|
|
|
}
|
|
@@ -1300,7 +1319,8 @@
|
|
|
}
|
|
|
|
|
|
|
|
|
- User.prototype.recall = async function(setvalidity, options){
|
|
|
+ User.prototype.recall = function(setvalidity, options){
|
|
|
+ var gun = this;
|
|
|
const gunRoot = this.back(-1)
|
|
|
|
|
|
let validity
|
|
@@ -1317,7 +1337,7 @@
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- return this;
|
|
|
+ return gun;
|
|
|
}
|
|
|
|
|
|
if (!Gun.val.is(setvalidity)) {
|
|
@@ -1340,13 +1360,15 @@
|
|
|
authsettings.hook = (Gun.obj.has(opts, 'hook') && typeof opts.hook === 'function')
|
|
|
? opts.hook : _initial_authsettings.hook
|
|
|
|
|
|
- return await authRecall(gunRoot)
|
|
|
+ (async function(){ await authRecall(gunRoot) }());
|
|
|
+ return gun;
|
|
|
} catch (e) {
|
|
|
const err = 'No session!'
|
|
|
Gun.log(err)
|
|
|
|
|
|
|
|
|
- return { err: (e && e.err) || err }
|
|
|
+
|
|
|
+ return gun;
|
|
|
}
|
|
|
}
|
|
|
User.prototype.alive = async function(){
|
|
@@ -1563,7 +1585,7 @@
|
|
|
if(tmp = relpub(soul)){
|
|
|
check['any'+soul+key] = 1;
|
|
|
SEA.verify(val, pub = tmp, function(data){ var rel;
|
|
|
- if(!data){ return each.end({err: "Mismatched owner on '" + key + "'."}) }
|
|
|
+ if(u === data){ return each.end({err: "Mismatched owner on '" + key + "'."}) }
|
|
|
if((rel = Gun.val.link.is(data)) && pub === relpub(rel)){
|
|
|
(at.sea.own[rel] = at.sea.own[rel] || {})[pub] = true;
|
|
|
}
|