mirror of
https://github.com/amark/gun.git
synced 2025-06-06 06:06:50 +00:00
Refactored SafeBuffer & fixed two failing tests
This commit is contained in:
parent
4a8423ea15
commit
68d8da1fdd
193
sea.js
193
sea.js
@ -15,117 +15,6 @@
|
|||||||
|
|
||||||
var Gun = (typeof window !== 'undefined' ? window : global).Gun || require('./gun');
|
var Gun = (typeof window !== 'undefined' ? window : global).Gun || require('./gun');
|
||||||
|
|
||||||
function SafeBuffer(...props) {
|
|
||||||
console.warn('new SafeBuffer() is depreciated, please use SafeBuffer.from()')
|
|
||||||
return this.from(...props)
|
|
||||||
}
|
|
||||||
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)
|
|
||||||
if (!bytes || !bytes.length) {
|
|
||||||
throw new TypeError('Invalid first argument for type \'hex\'.')
|
|
||||||
}
|
|
||||||
buf = new ArrayBuffer(input.length / 2)
|
|
||||||
const bufView = new Uint8Array(buf)
|
|
||||||
bytes.map((byte, index) => bufView[index] = parseInt(byte, 16))
|
|
||||||
} else if (enc === 'utf8') {
|
|
||||||
const { length } = input
|
|
||||||
buf = new ArrayBuffer(length * 2)
|
|
||||||
const bufView = new Uint16Array(buf)
|
|
||||||
Array.from({ length }).map((_, i) => bufView[i] = input.charCodeAt(i))
|
|
||||||
} else if (enc === 'base64') {
|
|
||||||
const bytes = atob(input)
|
|
||||||
const { length } = bytes
|
|
||||||
buf = new ArrayBuffer(length)
|
|
||||||
const bufView = new Uint8Array(buf)
|
|
||||||
Array.from({ length }).map((_, i) => bufView[i] = bytes.charCodeAt(i))
|
|
||||||
} else {
|
|
||||||
console.info(`SafeBuffer.from unknown encoding: '${enc}'`)
|
|
||||||
}
|
|
||||||
return buf
|
|
||||||
}
|
|
||||||
if (Array.isArray(input)) {
|
|
||||||
const { length } = input
|
|
||||||
buf = new ArrayBuffer(length)
|
|
||||||
const bufView = new Uint8Array(buf)
|
|
||||||
input.map((byte, i) => bufView[i] = byte)
|
|
||||||
return buf
|
|
||||||
}
|
|
||||||
if (input instanceof ArrayBuffer) {
|
|
||||||
const { byteLength, length = byteLength } = input
|
|
||||||
buf = new ArrayBuffer(length)
|
|
||||||
const bufView = new Uint8Array(buf)
|
|
||||||
const itmView = new Uint8Array(input)
|
|
||||||
Array.from({ length }).map((_, i) => bufView[i] = itmView[i])
|
|
||||||
return buf
|
|
||||||
}
|
|
||||||
if (input instanceof Uint8Array) {
|
|
||||||
const { byteLength, length = byteLength } = input
|
|
||||||
buf = new ArrayBuffer(length)
|
|
||||||
const bufView = new Uint8Array(buf)
|
|
||||||
Array.from({ length }).map((_, i) => bufView[i] = input[i])
|
|
||||||
return buf
|
|
||||||
}
|
|
||||||
},
|
|
||||||
alloc(length, fill = 0 /*, enc*/ ) {
|
|
||||||
buf = new ArrayBuffer(length)
|
|
||||||
const bufView = new Uint8Array(buf)
|
|
||||||
Array.from({ length }).map((_, i) => bufView[i] = fill)
|
|
||||||
return buf
|
|
||||||
},
|
|
||||||
concat(arr) { // octet array
|
|
||||||
if (!Array.isArray(arr)) {
|
|
||||||
throw new TypeError('First argument must be Array containing ArrayBuffer or Uint8Array instances.')
|
|
||||||
}
|
|
||||||
const length = arr.reduce((sum, item) => {
|
|
||||||
const { byteLength, length = byteLength } = item
|
|
||||||
return sum + length
|
|
||||||
}, 0)
|
|
||||||
buf = new ArrayBuffer(length)
|
|
||||||
const bufView = new Uint8Array(buf)
|
|
||||||
arr.reduce((index, item) => {
|
|
||||||
const { byteLength, length = byteLength } = item
|
|
||||||
const itmView = new Uint8Array(item)
|
|
||||||
Array.from({ length }).map((_, i) => bufView[index + i] = itmView[i])
|
|
||||||
return index + length
|
|
||||||
}, 0)
|
|
||||||
return buf
|
|
||||||
}
|
|
||||||
})
|
|
||||||
SafeBuffer.prototype.from = SafeBuffer.from
|
|
||||||
ArrayBuffer.prototype.toString = function(enc = 'utf8', start, end) {
|
|
||||||
if (enc === 'hex') {
|
|
||||||
const { byteLength: length } = this
|
|
||||||
const bufView = new Uint8Array(this)
|
|
||||||
return Array.from({ length })
|
|
||||||
.map((_, i) => bufView[i].toString(16))
|
|
||||||
.map((byte) => byte.toString(16).padStart(2, '0')).join('')
|
|
||||||
}
|
|
||||||
if (enc === 'utf8') {
|
|
||||||
const { byteLength, length = byteLength } = this
|
|
||||||
const bufView = new Uint16Array(this)
|
|
||||||
return Array.from({ length })
|
|
||||||
.map((_, i) => String.fromCharCode(bufView[i])).join('')
|
|
||||||
}
|
|
||||||
if (enc === 'base64') {
|
|
||||||
return btoa(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// var Buffer = SafeBuffer;
|
|
||||||
if(typeof Buffer === 'undefined'){
|
|
||||||
var Buffer = require('safe-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;
|
||||||
|
|
||||||
@ -158,6 +47,78 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(typeof Buffer === 'undefined'){
|
||||||
|
var Buffer = require('safe-buffer').Buffer; //eslint-disable-line no-redeclare
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is Buffer implementation used in SEA:
|
||||||
|
function SafeBuffer(...props) {
|
||||||
|
console.warn('new SafeBuffer() is depreciated, please use SafeBuffer.from()')
|
||||||
|
return this.from(...props)
|
||||||
|
}
|
||||||
|
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 = new Uint8Array(bytes)
|
||||||
|
} else if (enc === 'utf8') {
|
||||||
|
const src = new TextEncoder().encode(input)
|
||||||
|
buf = new Uint8Array(src)
|
||||||
|
} else if (enc === 'base64') {
|
||||||
|
const bytes = atob(input)
|
||||||
|
buf = new Uint8Array(bytes)
|
||||||
|
} else {
|
||||||
|
console.info(`SafeBuffer.from unknown encoding: '${enc}'`)
|
||||||
|
}
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
if (Array.isArray(input)
|
||||||
|
|| input instanceof ArrayBuffer
|
||||||
|
|| input instanceof Uint8Array) {
|
||||||
|
return new Uint8Array(input)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
alloc(length, fill = 0 /*, enc*/ ) {
|
||||||
|
return new Uint8Array(Array.from({ length }, () => fill))
|
||||||
|
},
|
||||||
|
concat(arr) { // octet array
|
||||||
|
if (!Array.isArray(arr)) {
|
||||||
|
throw new TypeError('First argument must be Array containing ArrayBuffer or Uint8Array instances.')
|
||||||
|
}
|
||||||
|
return new Uint8Array(arr.reduce((ret, item) => ret.concat(Array.from(item)), []))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
SafeBuffer.prototype.from = SafeBuffer.from
|
||||||
|
Uint8Array.prototype.toString = function(enc = 'utf8', start, end) {
|
||||||
|
if (enc === 'hex') {
|
||||||
|
const { byteLength: length } = this
|
||||||
|
return Array.from({ length })
|
||||||
|
.map((_, i) => this[i].toString(16))
|
||||||
|
.map((byte) => byte.toString(16).padStart(2, '0')).join('')
|
||||||
|
}
|
||||||
|
if (enc === 'utf8') {
|
||||||
|
const { byteLength, length = byteLength } = this
|
||||||
|
return Array.from({ length })
|
||||||
|
.map((_, i) => String.fromCharCode(this[i])).join('')
|
||||||
|
}
|
||||||
|
if (enc === 'base64') {
|
||||||
|
return btoa(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// var Buffer = SafeBuffer;
|
||||||
|
|
||||||
// Encryption parameters - TODO: maybe to be changed via init?
|
// Encryption parameters - TODO: maybe to be changed via init?
|
||||||
var pbkdf2 = {
|
var pbkdf2 = {
|
||||||
hash: 'SHA-256',
|
hash: 'SHA-256',
|
||||||
@ -587,7 +548,8 @@
|
|||||||
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){
|
||||||
@ -1065,8 +1027,11 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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){
|
||||||
@ -1088,7 +1053,7 @@
|
|||||||
try{
|
try{
|
||||||
var hash = crypto.pbkdf2Sync(
|
var hash = crypto.pbkdf2Sync(
|
||||||
pass,
|
pass,
|
||||||
Buffer.from(salt, 'utf8'),
|
new TextEncoder().encode(salt),
|
||||||
pbkdf2.iter,
|
pbkdf2.iter,
|
||||||
pbkdf2.ks,
|
pbkdf2.ks,
|
||||||
pbkdf2.hash.replace('-', '').toLowerCase()
|
pbkdf2.hash.replace('-', '').toLowerCase()
|
||||||
|
@ -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