mirror of
https://github.com/amark/gun.git
synced 2025-06-06 06:06:50 +00:00
commit
226e7f2796
@ -1,7 +1,8 @@
|
|||||||
language: node_js
|
language: node_js
|
||||||
node_js:
|
node_js:
|
||||||
- 4.0
|
- 4.0
|
||||||
- 4.2
|
- 4.2
|
||||||
- 5.0
|
- 5.0
|
||||||
- 6.8
|
- 6.8
|
||||||
- 7.9
|
- 7.9
|
||||||
|
- 8.6
|
||||||
|
2
gun.min.js
vendored
2
gun.min.js
vendored
File diff suppressed because one or more lines are too long
@ -52,10 +52,8 @@
|
|||||||
"ws": "~>4.0.0"
|
"ws": "~>4.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"spark-md5": "^3.0.0",
|
|
||||||
"@std/esm": "^0.8.3",
|
"@std/esm": "^0.8.3",
|
||||||
"@trust/webcrypto": "^0.7.1",
|
"@trust/webcrypto": "^0.7.1",
|
||||||
"buffer": "^5.0.7",
|
|
||||||
"express": ">=4.15.2",
|
"express": ">=4.15.2",
|
||||||
"fake-indexeddb": "^2.0.3",
|
"fake-indexeddb": "^2.0.3",
|
||||||
"hapi": "^16.1.1",
|
"hapi": "^16.1.1",
|
||||||
|
206
sea.js
206
sea.js
@ -15,23 +15,15 @@
|
|||||||
|
|
||||||
var Gun = (typeof window !== 'undefined' ? window : global).Gun || require('./gun');
|
var Gun = (typeof window !== 'undefined' ? window : global).Gun || require('./gun');
|
||||||
|
|
||||||
if(typeof buffer !== 'undefined'){
|
|
||||||
var Buffer = buffer.Buffer;
|
|
||||||
}
|
|
||||||
if(typeof Buffer === 'undefined'){
|
|
||||||
var Buffer = require('buffer').Buffer; //eslint-disable-line no-redeclare
|
|
||||||
}
|
|
||||||
|
|
||||||
var subtle, subtleossl, TextEncoder, TextDecoder, getRandomBytes;
|
var subtle, subtleossl, TextEncoder, TextDecoder, getRandomBytes;
|
||||||
var sessionStorage, localStorage, indexedDB;
|
var sessionStorage, localStorage, indexedDB;
|
||||||
|
|
||||||
if(typeof window !== 'undefined'){
|
if(typeof window !== 'undefined'){
|
||||||
if(typeof window.SparkMD5 !== 'undefined'){
|
|
||||||
var SparkMD5 = window.SparkMD5;
|
|
||||||
}
|
|
||||||
var wc = window.crypto || window.msCrypto; // STD or M$
|
var wc = window.crypto || window.msCrypto; // STD or M$
|
||||||
subtle = wc.subtle || wc.webkitSubtle; // STD or iSafari
|
subtle = wc.subtle || wc.webkitSubtle; // STD or iSafari
|
||||||
getRandomBytes = function(len){ return wc.getRandomValues(new Buffer(len)) };
|
getRandomBytes = function(len){
|
||||||
|
return Buffer.from(wc.getRandomValues(new Uint8Array(Buffer.alloc(len))));
|
||||||
|
};
|
||||||
TextEncoder = window.TextEncoder;
|
TextEncoder = window.TextEncoder;
|
||||||
TextDecoder = window.TextDecoder;
|
TextDecoder = window.TextDecoder;
|
||||||
sessionStorage = window.sessionStorage;
|
sessionStorage = window.sessionStorage;
|
||||||
@ -44,7 +36,7 @@
|
|||||||
var webcrypto = new WebCrypto({directory: 'key_storage'});
|
var webcrypto = new WebCrypto({directory: 'key_storage'});
|
||||||
subtleossl = webcrypto.subtle;
|
subtleossl = webcrypto.subtle;
|
||||||
subtle = require('@trust/webcrypto').subtle; // All but ECDH
|
subtle = require('@trust/webcrypto').subtle; // All but ECDH
|
||||||
getRandomBytes = function(len){ return crypto.randomBytes(len) };
|
getRandomBytes = function(len){ return Buffer.from(crypto.randomBytes(len)) };
|
||||||
TextEncoder = require('text-encoding').TextEncoder;
|
TextEncoder = require('text-encoding').TextEncoder;
|
||||||
TextDecoder = require('text-encoding').TextDecoder;
|
TextDecoder = require('text-encoding').TextDecoder;
|
||||||
// Let's have Storage for NodeJS / testing
|
// Let's have Storage for NodeJS / testing
|
||||||
@ -57,11 +49,100 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(typeof SparkMD5 === 'undefined'){
|
// This is Array extended to have .toString(['utf8'|'hex'|'base64'])
|
||||||
var SparkMD5 = require('spark-md5'); //eslint-disable-line no-redeclare
|
function SeaArray() {}
|
||||||
|
Object.assign(SeaArray, { from: Array.from })
|
||||||
|
SeaArray.prototype = Object.create(Array.prototype)
|
||||||
|
SeaArray.prototype.toString = function(enc = 'utf8', start = 0, end) {
|
||||||
|
const { length } = this
|
||||||
|
if (enc === 'hex') {
|
||||||
|
const buf = new Uint8Array(this)
|
||||||
|
return [ ...Array(((end && (end + 1)) || length) - start).keys()]
|
||||||
|
.map((i) => buf[ i + start ].toString(16).padStart(2, '0')).join('')
|
||||||
|
}
|
||||||
|
if (enc === 'utf8') {
|
||||||
|
return Array.from(
|
||||||
|
{ length: (end || length) - start },
|
||||||
|
(_, i) => String.fromCharCode(this[ i + start])
|
||||||
|
).join('')
|
||||||
|
}
|
||||||
|
if (enc === 'base64') {
|
||||||
|
return btoa(this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encryption parameters - TODO: maybe to be changed via init?
|
// This is Buffer implementation used in SEA:
|
||||||
|
function SafeBuffer(...props) {
|
||||||
|
console.warn('new SafeBuffer() is depreciated, please use SafeBuffer.from()')
|
||||||
|
return SafeBuffer.from(...props)
|
||||||
|
}
|
||||||
|
SafeBuffer.prototype = Object.create(Array.prototype)
|
||||||
|
Object.assign(SafeBuffer, {
|
||||||
|
// (data, enc) where typeof data === 'string' then enc === 'utf8'|'hex'|'base64'
|
||||||
|
from() {
|
||||||
|
if (!Object.keys(arguments).length) {
|
||||||
|
throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.')
|
||||||
|
}
|
||||||
|
const input = arguments[0]
|
||||||
|
let buf
|
||||||
|
if (typeof input === 'string') {
|
||||||
|
const enc = arguments[1] || 'utf8'
|
||||||
|
if (enc === 'hex') {
|
||||||
|
const bytes = input.match(/([\da-fA-F]{2})/g)
|
||||||
|
.map((byte) => parseInt(byte, 16))
|
||||||
|
if (!bytes || !bytes.length) {
|
||||||
|
throw new TypeError('Invalid first argument for type \'hex\'.')
|
||||||
|
}
|
||||||
|
buf = SeaArray.from(bytes)
|
||||||
|
} else if (enc === 'utf8') {
|
||||||
|
const { length } = input
|
||||||
|
const words = new Uint16Array(length)
|
||||||
|
Array.from({ length }, (_, i) => words[i] = input.charCodeAt(i))
|
||||||
|
buf = SeaArray.from(words)
|
||||||
|
} else if (enc === 'base64') {
|
||||||
|
const dec = atob(input)
|
||||||
|
const { length } = dec
|
||||||
|
const bytes = new Uint8Array(length)
|
||||||
|
Array.from({ length }, (_, i) => bytes[i] = dec.charCodeAt(i))
|
||||||
|
buf = SeaArray.from(bytes)
|
||||||
|
} else if (enc === 'binary') {
|
||||||
|
buf = SeaArray.from(input)
|
||||||
|
} else {
|
||||||
|
console.info(`SafeBuffer.from unknown encoding: '${enc}'`)
|
||||||
|
}
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
const { byteLength, length = byteLength } = input
|
||||||
|
if (length) {
|
||||||
|
let buf
|
||||||
|
if (input instanceof ArrayBuffer) {
|
||||||
|
buf = new Uint8Array(input)
|
||||||
|
}
|
||||||
|
return SeaArray.from(buf || input)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
alloc(length, fill = 0 /*, enc*/ ) {
|
||||||
|
return SeaArray.from(new Uint8Array(Array.from({ length }, () => fill)))
|
||||||
|
},
|
||||||
|
|
||||||
|
allocUnsafe(length) {
|
||||||
|
return SeaArray.from(new Uint8Array(Array.from({ length })))
|
||||||
|
},
|
||||||
|
|
||||||
|
concat(arr) { // octet array
|
||||||
|
if (!Array.isArray(arr)) {
|
||||||
|
throw new TypeError('First argument must be Array containing ArrayBuffer or Uint8Array instances.')
|
||||||
|
}
|
||||||
|
return SeaArray.from(arr.reduce((ret, item) => ret.concat(Array.from(item)), []))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
SafeBuffer.prototype.from = SafeBuffer.from
|
||||||
|
SafeBuffer.prototype.toString = SeaArray.prototype.toString
|
||||||
|
|
||||||
|
const Buffer = SafeBuffer
|
||||||
|
|
||||||
|
// Encryption parameters
|
||||||
var pbkdf2 = {
|
var pbkdf2 = {
|
||||||
hash: 'SHA-256',
|
hash: 'SHA-256',
|
||||||
iter: 50000,
|
iter: 50000,
|
||||||
@ -84,7 +165,7 @@
|
|||||||
};
|
};
|
||||||
// This creates Web Cryptography API compliant JWK for sign/verify purposes
|
// This creates Web Cryptography API compliant JWK for sign/verify purposes
|
||||||
function keystoecdsajwk(pub,priv){
|
function keystoecdsajwk(pub,priv){
|
||||||
var pubkey = (new Buffer(pub, 'base64')).toString('utf8').split(':');
|
var pubkey = Buffer.from(pub, 'base64').toString('utf8').split(':');
|
||||||
var jwk = priv ? {d: priv, key_ops: ['sign']} : {key_ops: ['verify']};
|
var jwk = priv ? {d: priv, key_ops: ['sign']} : {key_ops: ['verify']};
|
||||||
return Object.assign(jwk, {
|
return Object.assign(jwk, {
|
||||||
kty: 'EC',
|
kty: 'EC',
|
||||||
@ -136,8 +217,8 @@
|
|||||||
root.get(pub).get(function(at, ev){
|
root.get(pub).get(function(at, ev){
|
||||||
pub = pub.slice(4);
|
pub = pub.slice(4);
|
||||||
ev.off(); c--;
|
ev.off(); c--;
|
||||||
if(at.put){
|
if(at.put){
|
||||||
aliases.push({pub: pub, at: at});
|
aliases.push({pub: pub, at: at});
|
||||||
}
|
}
|
||||||
if(!c && (c = -1)){ resolve(aliases) }
|
if(!c && (c = -1)){ resolve(aliases) }
|
||||||
});
|
});
|
||||||
@ -166,7 +247,7 @@
|
|||||||
.catch(function(e){ reject({err: 'Failed to create proof!'}) })
|
.catch(function(e){ reject({err: 'Failed to create proof!'}) })
|
||||||
.then(function(proof){
|
.then(function(proof){
|
||||||
var user = {pub: pub, proof: proof, at: at};
|
var user = {pub: pub, proof: proof, at: at};
|
||||||
// the proof of work is evidence that we've spent some time/effort trying to log in, this slows brute force.
|
// the proof of work is evidence that we've spent some time/effort trying to log in, this slows brute force.
|
||||||
/*
|
/*
|
||||||
MARK TO @mhelander : pub vs epub!???
|
MARK TO @mhelander : pub vs epub!???
|
||||||
*/
|
*/
|
||||||
@ -275,7 +356,7 @@
|
|||||||
// IF authsettings.validity === 0 THEN no remember-me, ever
|
// IF authsettings.validity === 0 THEN no remember-me, ever
|
||||||
// IF PIN then signed 'remember' to window.sessionStorage and 'auth' to IndexedDB
|
// IF PIN then signed 'remember' to window.sessionStorage and 'auth' to IndexedDB
|
||||||
var pin = (Gun.obj.has(opts, 'pin') && opts.pin) || Gun.text.random(10);
|
var pin = (Gun.obj.has(opts, 'pin') && opts.pin) || Gun.text.random(10);
|
||||||
pin = new Buffer(pin, 'utf8').toString('base64');
|
pin = Buffer.from(pin, 'utf8').toString('base64');
|
||||||
|
|
||||||
if(proof && user && user.alias && authsettings.validity){
|
if(proof && user && user.alias && authsettings.validity){
|
||||||
var args = {alias: user.alias};
|
var args = {alias: user.alias};
|
||||||
@ -303,7 +384,7 @@
|
|||||||
var alias = Gun.obj.has(authprops, 'alias') && authprops.alias
|
var alias = Gun.obj.has(authprops, 'alias') && authprops.alias
|
||||||
|| sessionStorage.getItem('user');
|
|| sessionStorage.getItem('user');
|
||||||
var pin = Gun.obj.has(authprops, 'pin')
|
var pin = Gun.obj.has(authprops, 'pin')
|
||||||
&& new Buffer(authprops.pin, 'utf8').toString('base64');
|
&& Buffer.from(authprops.pin, 'utf8').toString('base64');
|
||||||
|
|
||||||
var checkRememberData = function(decr){
|
var checkRememberData = function(decr){
|
||||||
if(Gun.obj.has(decr, 'proof')
|
if(Gun.obj.has(decr, 'proof')
|
||||||
@ -455,13 +536,18 @@
|
|||||||
// This recalls Web Cryptography API CryptoKeys from IndexedDB or creates & stores
|
// This recalls Web Cryptography API CryptoKeys from IndexedDB or creates & stores
|
||||||
function recallCryptoKey(p,s,o){ // {pub, key}|proof, salt, optional:['sign']
|
function recallCryptoKey(p,s,o){ // {pub, key}|proof, salt, optional:['sign']
|
||||||
o = o || ['encrypt', 'decrypt']; // Default operations
|
o = o || ['encrypt', 'decrypt']; // Default operations
|
||||||
var importKey = function(key){ return subtle.importKey(
|
var importKey = function(key){
|
||||||
'raw',
|
return makeKey((Gun.obj.has(key, 'key') && key.key) || key, s || getRandomBytes(8))
|
||||||
makeKey((Gun.obj.has(key, 'key') && key.key) || key, s || getRandomBytes(8)),
|
.then(function(hashedKey){
|
||||||
'AES-CBC',
|
return subtle.importKey(
|
||||||
false,
|
'raw',
|
||||||
o
|
new Uint8Array(hashedKey),
|
||||||
); };
|
'AES-CBC',
|
||||||
|
false,
|
||||||
|
o
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
return new Promise(function(resolve){
|
return new Promise(function(resolve){
|
||||||
if(authsettings.validity && typeof window !== 'undefined'
|
if(authsettings.validity && typeof window !== 'undefined'
|
||||||
&& Gun.obj.has(p, 'pub') && Gun.obj.has(p, 'key')){
|
&& Gun.obj.has(p, 'pub') && Gun.obj.has(p, 'key')){
|
||||||
@ -485,12 +571,13 @@
|
|||||||
function sha256hash(m){
|
function sha256hash(m){
|
||||||
var hashSubtle = subtleossl || subtle;
|
var hashSubtle = subtleossl || subtle;
|
||||||
try{ m = m.slice ? m : JSON.stringify(m) }catch(e){} //eslint-disable-line no-empty
|
try{ m = m.slice ? m : JSON.stringify(m) }catch(e){} //eslint-disable-line no-empty
|
||||||
return hashSubtle.digest(pbkdf2.hash, new TextEncoder("utf-8").encode(m));
|
return hashSubtle.digest(pbkdf2.hash, new TextEncoder().encode(m))
|
||||||
|
.then(function(hash){ return Buffer.from(hash) });
|
||||||
}
|
}
|
||||||
// This internal func returns SHA-1 hashed data for KeyID generation
|
// This internal func returns SHA-1 hashed data for KeyID generation
|
||||||
function sha1hash(b){
|
function sha1hash(b){
|
||||||
var hashSubtle = subtleossl || subtle;
|
var hashSubtle = subtleossl || subtle;
|
||||||
return hashSubtle.digest('SHA-1', b);
|
return hashSubtle.digest('SHA-1', new ArrayBuffer(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
// How does it work?
|
// How does it work?
|
||||||
@ -678,8 +765,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
var doIt = function(resolve, reject){
|
var doIt = function(resolve, reject){
|
||||||
// opts = { hook: function({ iat, exp, alias, proof }),
|
// opts = { hook: function({ iat, exp, alias, proof }) }
|
||||||
// session: false } // true uses random PIN, no PIN UX error generated
|
|
||||||
// iat == Date.now() when issued, exp == seconds to expire from iat
|
// iat == Date.now() when issued, exp == seconds to expire from iat
|
||||||
// How this works:
|
// How this works:
|
||||||
// called when app bootstraps, with wanted options
|
// called when app bootstraps, with wanted options
|
||||||
@ -957,18 +1043,18 @@
|
|||||||
to.next(msg); // pass forward any data we do not know how to handle or process (this allows custom security protocols).
|
to.next(msg); // pass forward any data we do not know how to handle or process (this allows custom security protocols).
|
||||||
}
|
}
|
||||||
|
|
||||||
// Does enc/dec key like OpenSSL - works with CryptoJS encryption/decryption
|
|
||||||
function makeKey(p,s){
|
function makeKey(p,s){
|
||||||
var ps = Buffer.concat([new Buffer(p, 'utf8'), s]);
|
var ps = Buffer.concat([Buffer.from(p, 'utf8'), s]);
|
||||||
var h128 = new Buffer((new SparkMD5()).appendBinary(ps).end(true), 'binary');
|
return sha256hash(ps.toString('utf8')).then(function(s){
|
||||||
return Buffer.concat([
|
return Buffer.from(s, 'binary');
|
||||||
h128,
|
});
|
||||||
new Buffer((new SparkMD5()).appendBinary(Buffer.concat([h128, ps])).end(true), 'binary')
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// These SEA functions support both callback AND Promises
|
|
||||||
var SEA = {};
|
var SEA = {};
|
||||||
|
// This is Buffer used in SEA and usable from Gun/SEA application also.
|
||||||
|
// For documentation see https://nodejs.org/api/buffer.html
|
||||||
|
SEA.Buffer = SafeBuffer;
|
||||||
|
// These SEA functions support both callback AND Promises
|
||||||
// create a wrapper library around Web Crypto API.
|
// create a wrapper library around Web Crypto API.
|
||||||
// now wrap the various AES, ECDSA, PBKDF2 functions we called above.
|
// now wrap the various AES, ECDSA, PBKDF2 functions we called above.
|
||||||
SEA.proof = function(pass,salt,cb){
|
SEA.proof = function(pass,salt,cb){
|
||||||
@ -984,13 +1070,13 @@
|
|||||||
}, key, pbkdf2.ks*8);
|
}, key, pbkdf2.ks*8);
|
||||||
}).then(function(result){
|
}).then(function(result){
|
||||||
pass = getRandomBytes(pass.length);
|
pass = getRandomBytes(pass.length);
|
||||||
return new Buffer(result, 'binary').toString('base64');
|
return Buffer.from(result, 'binary').toString('base64');
|
||||||
}).then(resolve).catch(function(e){ Gun.log(e); reject(e) });
|
}).then(resolve).catch(function(e){ Gun.log(e); reject(e) });
|
||||||
}) || function(resolve, reject){ // For NodeJS crypto.pkdf2 rocks
|
}) || function(resolve, reject){ // For NodeJS crypto.pkdf2 rocks
|
||||||
try{
|
try{
|
||||||
var hash = crypto.pbkdf2Sync(
|
var hash = crypto.pbkdf2Sync(
|
||||||
pass,
|
pass,
|
||||||
new Buffer(salt, 'utf8'),
|
new TextEncoder().encode(salt),
|
||||||
pbkdf2.iter,
|
pbkdf2.iter,
|
||||||
pbkdf2.ks,
|
pbkdf2.ks,
|
||||||
pbkdf2.hash.replace('-', '').toLowerCase()
|
pbkdf2.hash.replace('-', '').toLowerCase()
|
||||||
@ -1005,13 +1091,13 @@
|
|||||||
SEA.keyid = function(p,cb){
|
SEA.keyid = function(p,cb){
|
||||||
var doIt = function(resolve, reject){
|
var doIt = function(resolve, reject){
|
||||||
// base64('base64(x):base64(y)') => Buffer(xy)
|
// base64('base64(x):base64(y)') => Buffer(xy)
|
||||||
var pb = Buffer.concat((new Buffer(p, 'base64')).toString('utf8').split(':')
|
var pb = Buffer.concat(Buffer.from(p, 'base64').toString('utf8').split(':')
|
||||||
.map(function(t){ return new Buffer(t, 'base64') }));
|
.map(function(t){ return Buffer.from(t, 'base64') }));
|
||||||
// id is PGPv4 compliant raw key
|
// id is PGPv4 compliant raw key
|
||||||
var id = Buffer.concat([new Buffer([0x99, pb.length/0x100, pb.length%0x100]), pb]);
|
var id = Buffer.concat([Buffer.from([0x99, pb.length/0x100, pb.length%0x100]), pb]);
|
||||||
sha1hash(id).then(function(sha1){
|
sha1hash(id).then(function(sha1){
|
||||||
var hash = new Buffer(sha1, 'binary');
|
var hash = Buffer.from(sha1, 'binary');
|
||||||
resolve(hash.slice(hash.length-8).toString('hex')); // 16-bit ID as hex
|
resolve(hash.toString('hex', hash.length-8)); // 16-bit ID as hex
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
if(cb){ doIt(cb, function(){cb()}) } else { return new Promise(doIt) }
|
if(cb){ doIt(cb, function(){cb()}) } else { return new Promise(doIt) }
|
||||||
@ -1026,7 +1112,7 @@
|
|||||||
return {priv: k.d};
|
return {priv: k.d};
|
||||||
}).then(function(keys){
|
}).then(function(keys){
|
||||||
return subtle.exportKey('jwk', pubkey).then(function(k){
|
return subtle.exportKey('jwk', pubkey).then(function(k){
|
||||||
keys.pub = (new Buffer([k.x, k.y].join(':'))).toString('base64');
|
keys.pub = Buffer.from([k.x, k.y].join(':')).toString('base64');
|
||||||
// return SEA.keyid(keys.pub).then(function(id){
|
// return SEA.keyid(keys.pub).then(function(id){
|
||||||
// keys.pubId = id;
|
// keys.pubId = id;
|
||||||
// return keys;
|
// return keys;
|
||||||
@ -1045,7 +1131,7 @@
|
|||||||
return keys;
|
return keys;
|
||||||
}).then(function(keys){
|
}).then(function(keys){
|
||||||
return ecdhSubtle.exportKey('jwk', pubkey).then(function(k){
|
return ecdhSubtle.exportKey('jwk', pubkey).then(function(k){
|
||||||
keys.epub = (new Buffer([k.x, k.y].join(':'))).toString('base64');
|
keys.epub = Buffer.from([k.x, k.y].join(':')).toString('base64');
|
||||||
return keys;
|
return keys;
|
||||||
});
|
});
|
||||||
}).catch(function(e){ Gun.log(e); reject(e) });
|
}).catch(function(e){ Gun.log(e); reject(e) });
|
||||||
@ -1058,7 +1144,7 @@
|
|||||||
SEA.derive = function(m,p,cb){
|
SEA.derive = function(m,p,cb){
|
||||||
var ecdhSubtle = subtleossl || subtle;
|
var ecdhSubtle = subtleossl || subtle;
|
||||||
var keystoecdhjwk = function(pub, priv){
|
var keystoecdhjwk = function(pub, priv){
|
||||||
var pubkey = (new Buffer(pub, 'base64')).toString('utf8').split(':');
|
var pubkey = Buffer.from(pub, 'base64').toString('utf8').split(':');
|
||||||
var jwk = priv ? {d: priv, key_ops: ['decrypt']} : {key_ops: ['encrypt']};
|
var jwk = priv ? {d: priv, key_ops: ['decrypt']} : {key_ops: ['encrypt']};
|
||||||
var ret = Object.assign(jwk, {
|
var ret = Object.assign(jwk, {
|
||||||
kty: 'EC',
|
kty: 'EC',
|
||||||
@ -1095,8 +1181,8 @@
|
|||||||
var jwk = keystoecdsajwk(p.pub, p.priv);
|
var jwk = keystoecdsajwk(p.pub, p.priv);
|
||||||
sha256hash(m.slice ? m : JSON.stringify(m)).then(function(mm){
|
sha256hash(m.slice ? m : JSON.stringify(m)).then(function(mm){
|
||||||
subtle.importKey('jwk', jwk, ecdsakeyprops, false, ['sign']).then(function(key){
|
subtle.importKey('jwk', jwk, ecdsakeyprops, false, ['sign']).then(function(key){
|
||||||
subtle.sign(ecdsasignprops, key, mm)
|
subtle.sign(ecdsasignprops, key, new Uint8Array(mm))
|
||||||
.then(function(s){ resolve(new Buffer(s, 'binary').toString('base64')) })
|
.then(function(s){ resolve(Buffer.from(s, 'binary').toString('base64')) })
|
||||||
.catch(function(e){ Gun.log(e); reject(e) });
|
.catch(function(e){ Gun.log(e); reject(e) });
|
||||||
}).catch(function(e){ Gun.log(e); reject(e) });
|
}).catch(function(e){ Gun.log(e); reject(e) });
|
||||||
});
|
});
|
||||||
@ -1108,7 +1194,7 @@
|
|||||||
subtle.importKey('jwk', keystoecdsajwk(p), ecdsakeyprops, false, ['verify'])
|
subtle.importKey('jwk', keystoecdsajwk(p), ecdsakeyprops, false, ['verify'])
|
||||||
.then(function(key){
|
.then(function(key){
|
||||||
sha256hash(m).then(function(mm){
|
sha256hash(m).then(function(mm){
|
||||||
subtle.verify(ecdsasignprops, key, new Buffer(s, 'base64'), mm)
|
subtle.verify(ecdsasignprops, key, new Uint8Array(Buffer.from(s, 'base64')), new Uint8Array(mm))
|
||||||
.then(function(v){ resolve(v) })
|
.then(function(v){ resolve(v) })
|
||||||
.catch(function(e){ Gun.log(e); reject(e) });
|
.catch(function(e){ Gun.log(e); reject(e) });
|
||||||
});
|
});
|
||||||
@ -1124,10 +1210,10 @@
|
|||||||
m = (m.slice && m) || JSON.stringify(m);
|
m = (m.slice && m) || JSON.stringify(m);
|
||||||
recallCryptoKey(p, s).then(function(aesKey){
|
recallCryptoKey(p, s).then(function(aesKey){
|
||||||
subtle.encrypt({
|
subtle.encrypt({
|
||||||
name: 'AES-CBC', iv: iv
|
name: 'AES-CBC', iv: new Uint8Array(iv)
|
||||||
}, aesKey, new TextEncoder().encode(m)).then(function(ct){
|
}, aesKey, new TextEncoder().encode(m)).then(function(ct){
|
||||||
aesKey = getRandomBytes(32);
|
aesKey = getRandomBytes(32);
|
||||||
r.ct = new Buffer(ct, 'binary').toString('base64');
|
r.ct = Buffer.from(ct, 'binary').toString('base64');
|
||||||
return JSON.stringify(r);
|
return JSON.stringify(r);
|
||||||
}).then(resolve).catch(function(e){ Gun.log(e); reject(e) });
|
}).then(resolve).catch(function(e){ Gun.log(e); reject(e) });
|
||||||
}).catch(function(e){ Gun.log(e); reject(e)} );
|
}).catch(function(e){ Gun.log(e); reject(e)} );
|
||||||
@ -1137,12 +1223,12 @@
|
|||||||
SEA.dec = function(m,p,cb){
|
SEA.dec = function(m,p,cb){
|
||||||
var doIt = function(resolve, reject){
|
var doIt = function(resolve, reject){
|
||||||
try{ m = m.slice ? JSON.parse(m) : m }catch(e){} //eslint-disable-line no-empty
|
try{ m = m.slice ? JSON.parse(m) : m }catch(e){} //eslint-disable-line no-empty
|
||||||
var iv = new Buffer(m.iv, 'hex');
|
var iv = new Uint8Array(Buffer.from(m.iv, 'hex'));
|
||||||
var s = new Buffer(m.s, 'hex');
|
var s = new Uint8Array(Buffer.from(m.s, 'hex'));
|
||||||
recallCryptoKey(p, s).then(function(aesKey){
|
recallCryptoKey(p, s).then(function(aesKey){
|
||||||
subtle.decrypt({
|
subtle.decrypt({
|
||||||
name: 'AES-CBC', iv: iv
|
name: 'AES-CBC', iv: iv
|
||||||
}, aesKey, new Buffer(m.ct, 'base64')).then(function(ct){
|
}, aesKey, new Uint8Array(Buffer.from(m.ct, 'base64'))).then(function(ct){
|
||||||
aesKey = getRandomBytes(32);
|
aesKey = getRandomBytes(32);
|
||||||
var ctUtf8 = new TextDecoder('utf8').decode(ct);
|
var ctUtf8 = new TextDecoder('utf8').decode(ct);
|
||||||
try{ return ctUtf8.slice ? JSON.parse(ctUtf8) : ctUtf8;
|
try{ return ctUtf8.slice ? JSON.parse(ctUtf8) : ctUtf8;
|
||||||
@ -1176,7 +1262,7 @@
|
|||||||
if(!m){ if(false === p){ return resolve(m) }
|
if(!m){ if(false === p){ return resolve(m) }
|
||||||
return resolve();
|
return resolve();
|
||||||
}
|
}
|
||||||
if(!m.slice || 'SEA[' !== m.slice(0,4)){
|
if(!m.slice || 'SEA[' !== m.slice(0,4)){
|
||||||
if(false === p){ return resolve(m) }
|
if(false === p){ return resolve(m) }
|
||||||
return resolve()
|
return resolve()
|
||||||
}
|
}
|
||||||
@ -1185,7 +1271,7 @@
|
|||||||
}catch(e){ return reject(e) }
|
}catch(e){ return reject(e) }
|
||||||
m = m || '';
|
m = m || '';
|
||||||
d = m[0];
|
d = m[0];
|
||||||
try{ d = d.slice ? JSON.parse(d) : d }catch(e){}
|
try{ d = d.slice ? JSON.parse(d) : d }catch(e){}
|
||||||
if(false === p){ resolve(d) }
|
if(false === p){ resolve(d) }
|
||||||
SEA.verify(m[0], p, m[1]).then(function(ok){
|
SEA.verify(m[0], p, m[1]).then(function(ok){
|
||||||
if(!ok){ return resolve() }
|
if(!ok){ return resolve() }
|
||||||
|
@ -67,9 +67,9 @@ Gun.SEA && describe('SEA', function(){
|
|||||||
// proof - generates PBKDF2 hash from user's alias and password
|
// proof - generates PBKDF2 hash from user's alias and password
|
||||||
// which is then used to decrypt user's auth record
|
// which is then used to decrypt user's auth record
|
||||||
if(type === 'callback'){
|
if(type === 'callback'){
|
||||||
Gun.SEA.proof(alias, pass, check);
|
Gun.SEA.proof(pass, Gun.text.random(64), check);
|
||||||
} else {
|
} else {
|
||||||
Gun.SEA.proof(alias, pass).then(check).catch(done);
|
Gun.SEA.proof(pass, Gun.text.random(64)).then(check).catch(done);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -509,8 +509,8 @@ Gun().user && describe('Gun', function(){
|
|||||||
expect(ack).to.not.be('');
|
expect(ack).to.not.be('');
|
||||||
expect(ack).to.not.have.key('err');
|
expect(ack).to.not.have.key('err');
|
||||||
expect(ack).to.have.key('ok');
|
expect(ack).to.have.key('ok');
|
||||||
//expect(gun.back(-1)._.user).to.not.have.keys([ 'sea', 'pub' ]);
|
expect(gun.back(-1)._.user._).to.not.have.keys([ 'sea', 'pub' ]);
|
||||||
expect(gun.back(-1)._.user).to.not.be.ok();
|
// expect(gun.back(-1)._.user).to.not.be.ok();
|
||||||
}catch(e){ done(e); return }
|
}catch(e){ done(e); return }
|
||||||
done();
|
done();
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user