This commit is contained in:
noname 2024-11-19 03:28:03 +07:00
parent a647f99464
commit a7e482755a
8 changed files with 94 additions and 42 deletions

4
gun.js
View File

@ -765,8 +765,8 @@
(Gun.window||{}).console = (Gun.window||{}).console || {log: function(){}};
(C = console).only = function(i, s){ return (C.only.i && i === C.only.i && C.only.i++) && (C.log.apply(C, arguments) || s) };
;"Please do not remove welcome log unless you are paying for a monthly sponsorship, thanks!";
Gun.log.once("welcome", "Hello wonderful person! :) Thanks for using GUN, please ask for help on http://chat.gun.eco if anything takes you longer than 5min to figure out!");
// ;"Please do not remove welcome log unless you are paying for a monthly sponsorship, thanks!";
// Gun.log.once("welcome", "Hello wonderful person! :) Thanks for using GUN, please ask for help on http://chat.gun.eco if anything takes you longer than 5min to figure out!");
})(USE, './root');
;USE(function(module){

2
gun.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -99,7 +99,7 @@
if (u !== data && u !== data.e && msg.put['>'] && msg.put['>'] > parseFloat(data.e)) return no("Certificate expired.") // certificate expired
// "data.c" = a list of certificants/certified users
// "data.w" = lex WRITE permission, in the future, there will be "data.r" which means lex READ permission
if (u !== data && data.c && data.w && (data.c === certificant || data.c.indexOf('*' || certificant) > -1)) {
if (u !== data && data.c && data.w && (data.c === certificant || data.c.indexOf('*') > -1 || data.c.indexOf(certificant) > -1)) {
// ok, now "certificant" is in the "certificants" list, but is "path" allowed? Check path
let path = soul.indexOf('/') > -1 ? soul.replace(soul.substring(0, soul.indexOf('/') + 1), '') : ''
String.match = String.match || Gun.text.match

View File

@ -15,51 +15,101 @@
return;
}});
//SEA.pair = async (data, proof, cb) => { try {
SEA.pair = SEA.pair || (async (cb, opt) => { try {
var ecdhSubtle = shim.ossl || shim.subtle;
// First: ECDSA keys for signing/verifying...
var sa = await shim.subtle.generateKey({name: 'ECDSA', namedCurve: 'P-256'}, true, [ 'sign', 'verify' ])
.then(async (keys) => {
// privateKey scope doesn't leak out from here!
//const { d: priv } = await shim.subtle.exportKey('jwk', keys.privateKey)
// Generate deterministic keys if opt.seed is provided
if (opt && opt.seed) {
const encoder = new shim.TextEncoder();
// Generate deterministic private keys using SHA-256
const signPrivateKeyBytes = new Uint8Array(
await shim.subtle.digest('SHA-256', encoder.encode(opt.seed + '-sign'))
);
const encryptPrivateKeyBytes = new Uint8Array(
await shim.subtle.digest('SHA-256', encoder.encode(opt.seed + '-encrypt'))
);
// Convert to base64url format
const toBase64Url = buffer =>
shim.Buffer.from(buffer)
.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
// Format private keys
const signPriv = toBase64Url(signPrivateKeyBytes).slice(0, 43);
const encryptPriv = toBase64Url(encryptPrivateKeyBytes).slice(0, 43);
// Generate public key components deterministically
const signPubXBytes = await shim.subtle.digest(
'SHA-256',
encoder.encode(signPriv + '-x')
);
const signPubYBytes = await shim.subtle.digest(
'SHA-256',
encoder.encode(signPriv + '-y')
);
const encryptPubXBytes = await shim.subtle.digest(
'SHA-256',
encoder.encode(encryptPriv + '-x')
);
const encryptPubYBytes = await shim.subtle.digest(
'SHA-256',
encoder.encode(encryptPriv + '-y')
);
// Format public keys
const signPubX = toBase64Url(signPubXBytes).slice(0, 43);
const signPubY = toBase64Url(signPubYBytes).slice(0, 43);
const encryptPubX = toBase64Url(encryptPubXBytes).slice(0, 43);
const encryptPubY = toBase64Url(encryptPubYBytes).slice(0, 43);
// Format the result
var r = {
pub: signPubX + '.' + signPubY,
priv: signPriv,
epub: encryptPubX + '.' + encryptPubY,
epriv: encryptPriv
};
if(cb){ try{ cb(r) }catch(e){console.log(e)} }
return r;
}
// If no seed provided, generate random keys (existing logic)
var sa = await shim.subtle.generateKey(
{name: 'ECDSA', namedCurve: 'P-256'},
true,
['sign', 'verify']
).then(async (keys) => {
var key = {};
key.priv = (await shim.subtle.exportKey('jwk', keys.privateKey)).d;
var pub = await shim.subtle.exportKey('jwk', keys.publicKey);
//const pub = Buff.from([ x, y ].join(':')).toString('base64') // old
key.pub = pub.x+'.'+pub.y; // new
// x and y are already base64
// pub is UTF8 but filename/URL safe (https://www.ietf.org/rfc/rfc3986.txt)
// but split on a non-base64 letter.
key.pub = pub.x+'.'+pub.y;
return key;
})
});
// To include PGPv4 kind of keyId:
// const pubId = await SEA.keyid(keys.pub)
// Next: ECDH keys for encryption/decryption...
try{
var dh = await ecdhSubtle.generateKey({name: 'ECDH', namedCurve: 'P-256'}, true, ['deriveKey'])
.then(async (keys) => {
// privateKey scope doesn't leak out from here!
var key = {};
key.epriv = (await ecdhSubtle.exportKey('jwk', keys.privateKey)).d;
var pub = await ecdhSubtle.exportKey('jwk', keys.publicKey);
//const epub = Buff.from([ ex, ey ].join(':')).toString('base64') // old
key.epub = pub.x+'.'+pub.y; // new
// ex and ey are already base64
// epub is UTF8 but filename/URL safe (https://www.ietf.org/rfc/rfc3986.txt)
// but split on a non-base64 letter.
return key;
})
var dh = await ecdhSubtle.generateKey(
{name: 'ECDH', namedCurve: 'P-256'},
true,
['deriveKey']
).then(async (keys) => {
var key = {};
key.epriv = (await ecdhSubtle.exportKey('jwk', keys.privateKey)).d;
var pub = await ecdhSubtle.exportKey('jwk', keys.publicKey);
key.epub = pub.x+'.'+pub.y;
return key;
});
}catch(e){
if(SEA.window){ throw e }
if(e == 'Error: ECDH is not a supported algorithm'){ console.log('Ignoring ECDH...') }
else { throw e }
} dh = dh || {};
var r = { pub: sa.pub, priv: sa.priv, /* pubId, */ epub: dh.epub, epriv: dh.epriv }
var r = { pub: sa.pub, priv: sa.priv, epub: dh.epub, epriv: dh.epriv }
if(cb){ try{ cb(r) }catch(e){console.log(e)} }
return r;
} catch(e) {

View File

@ -83,6 +83,7 @@ function list(each){ each = each || function(x){return x}
}
function set(word, is){
// TODO: Perf on random write is decent, but short keys or seq seems significantly slower.
var b = this, has = b.all[word];
if(has){ return b(word, is) } // updates to in-memory items will always match exactly.
var page = b.page(word=''+word), tmp; // before we assume this is an insert tho, we need to check
@ -103,21 +104,22 @@ function set(word, is){
function split(p, b){ // TODO: use closest hash instead of half.
//console.time();
//var S = performance.now();
var L = sort(p), l = L.length, i = l/2 >> 0, j = i, half = L[j], tmp;
//console.timeEnd();
var next = {first: half.substring(), size: 0, substring: sub, toString: to, book: b, get: b, read: list}, f = next.from = [];
//console.time();
while(tmp = L[i++]){
f.push(tmp);
next.size += (tmp.is||'').length||1;
tmp.page = next;
}
//console.timeEnd(); console.time();
p.from = p.from.slice(0, j);
p.size -= next.size;
b.list.splice(spot(next.first, b.list)+1, 0, next); // TODO: BUG! Make sure next.first is decoded text. // TODO: BUG! spot may need parse too?
//console.timeEnd();
if(b.split){ b.split(next, p) }
//console.log(S = (performance.now() - S), 'split');
//console.BIG = console.BIG > S? console.BIG : S;
}
function slot(t){ return heal((t=t||'').substring(1, t.length-1).split(t[0]), t[0]) } B.slot = slot; // TODO: check first=last & pass `s`.

View File

@ -76,10 +76,10 @@ function Mesh(root){
if((tmp = msg['><']) && 'string' == typeof tmp){ tmp.slice(0,99).split(',').forEach(function(k){ this[k] = 1 }, (msg._).yo = {}) } // Peers already sent to, do not resend.
// DAM ^
if(tmp = msg.dam){
(dup_track(id)||{}).via = peer;
if(tmp = mesh.hear[tmp]){
tmp(msg, peer, root);
}
dup_track(id);
return;
}
if(tmp = msg.ok){ msg._.near = tmp['/'] }

View File

@ -307,7 +307,7 @@ module.exports = Gun;
(Gun.window||{}).console = (Gun.window||{}).console || {log: function(){}};
(C = console).only = function(i, s){ return (C.only.i && i === C.only.i && C.only.i++) && (C.log.apply(C, arguments) || s) };
;"Please do not remove welcome log unless you are paying for a monthly sponsorship, thanks!";
Gun.log.once("welcome", "Hello wonderful person! :) Thanks for using GUN, please ask for help on http://chat.gun.eco if anything takes you longer than 5min to figure out!");
// ;"Please do not remove welcome log unless you are paying for a monthly sponsorship, thanks!";
// Gun.log.once("welcome", "Hello wonderful person! :) Thanks for using GUN, please ask for help on http://chat.gun.eco if anything takes you longer than 5min to figure out!");
}());

View File

@ -19,10 +19,10 @@ Gun.on('opt', function(root){
var mesh = opt.mesh = opt.mesh || Gun.Mesh(root);
var wire = mesh.wire || opt.wire;
var wired = mesh.wire || opt.wire;
mesh.wire = opt.wire = open;
function open(peer){ try{
if(!peer || !peer.url){ return wire && wire(peer) }
if(!peer || !peer.url){ return wired && wired(peer) }
var url = peer.url.replace(/^http/, 'ws');
var wire = peer.wire = new opt.WebSocket(url);
wire.onclose = function(){