Reputation: 31060
Say I create a gun user like so:
let user = gun.user()
user.create('Bob','password123',console.log)
user.auth('Bob' ,'password123',console.log)
I can see that I can export the key pair using user._.sea
, but am unsure whether I need (/whether it's possible) to export the salt as well. Is it possible to access the act
object of the create
prototype?
What is a good way to export the private key / salt such that the user could save a string (say a jwk) and use to authenticate on a different device?
What functions could you use to import the key in another session?
Upvotes: 0
Views: 110
Reputation: 21
tldr:
//this is a loged in instance of gun.user;
let pair = this.user._.sea;
I show it in a qr code, this code is not polished but not bad.
/**
* Show you private
*/
function showPair() {
let pair = this.user._.sea;
let qr = bs.str2qr(pair)
let w = bs.getGoodWidth();
let img = qr.createImgTag()
let html = ''
html += qr.createSvgTag(undefined, 1, this.user.is.alias, "GUN AUTH PAIR")
html += `<pre>${JSON.stringify(pair, null, 1)}</pre>`
jsPanel.create({
headerTitle: "GUN AUTH PAIR",
headerToolbar: [
"<input name='password' placeholder='password make it secure!'>",
"<button name='recovery'>Freeze Recovery</button>"
],
panelSize: {
width: w,
height: w + 20
},
content: html,
callback: panel => {
let s = panel.querySelector(`svg[role='img']`)
s.setAttribute('width', '99%')
s.setAttribute('height', null)
let i = panel.querySelector(`input[name='password']`)
let b = panel.querySelector(`button[name='recovery']`)
b.addEventListener('click', e => {
let p = i.value;
if (p.length < 12) {
this.resNotify({success: false, msg: 'Make a good password its your only line of defence'});
return;
}
this.registerRecovery(p, (key, id) => {
bs.showQr(id);
})
})
}
})
}
https://bullchat.syon.ca/js/bs.js see example. at https://bullchat.syon.ca login then showPair
var bs = {
//get a qr to this host with param id
id2qr: (id, param = 'id', s) => {
return bs.str2qr(window.location.host + '?' + param + '=' + encodeURIComponent(id), s)
},
//make a string into a qr scaling up size until it works
str2qr: (str, size = 10, setCorrection = ['H', 'Q', /*'M', 'L'*/]) => {
// L : 1,
// M : 0,
// Q : 3,
// H : 2
if (!Array.isArray(setCorrection)) setCorrection = [setCorrection];
let correcti
console.log(str, size)
for (let s = size; s <= 40; s++) {
for (l of setCorrection) {
try {
let qr = qrcode(s, l);
qr.addData(str);
qr.make();
return qr;
} catch (e) {
console.error('failed at error correction: ', l, " size: ", s, ' e: ', e)
}
}
}
return qr.createImgTag();
return bs.str2qr(window.location.host + '?' + param + '=' + encodeURIComponent(id))
},
/**
* Requires qrcode.js see bullchat
* @param id
* @param title
*/
showQr: (id, title = 'My QR') => {
let qr = bs.id2qr(id)
let w = bs.getGoodWidth();
let img = qr.createImgTag()
jsPanel.create({
headerTitle: 'QR Code: ' + title,
panelSize: {
width: w,
height: w + 20
},
content: qr.createSvgTag(undefined, 1, id, title),
callback: panel => {
let s = panel.querySelector(`svg[role='img']`)
s.setAttribute('width', '99%')
s.setAttribute('height', null)
}
})
},
showSvg: (id, title) => {
let w = bs.getGoodWidth();
let img = qr.createImgTag()
jsPanel.create({
headerTitle: 'QR Code: ' + title,
panelSize: {
width: w,
height: w + 20
},
content: qr.createSvgTag(undefined, 1, id, title),
callback: panel => {
let s = panel.querySelector(`svg[role='img']`)
s.setAttribute('width', '99%')
s.setAttribute('height', null)
}
})
},
/**
*
* @param [aspect=8.5/11] = aspect ratio to target w/h ie 1920/1080 or 8.5/11
* @param [thresh=500] - max of 1/2 width or thresh used to find preferred width.
* @param [pad=100] - how much to pad the edges by note 100 = 50 top 50 bottom
* @param opts
*/
getGoodPanelSize(aspect = 8.5 / 11, thresh, pad = 100, opts) {
// opts = opts || {};
// opts.aspect = opts.aspect || 8.5/11
let w = document.body.clientWidth - pad;
let h = document.body.clientHeight - pad;
//the
let t = thresh || Math.max(w / 2, 500)
let gw = bs.getGoodWidth(t, pad)
//if the good height is to tall user the panel height
let ph = Math.min(h, gw * (1 / aspect));
//then compute with based on height to maintain aspect
let pw = Math.min(h, ph * aspect);
return {width: pw, height: ph};
},
/**
* Thresh or screen with whichever smaller
* @param [thresh=500]
* @returns {number}
*/
getGoodWidth: (thresh = 500, pad = 50) => {
let w = document.body.clientWidth - pad;
// let thresh = 500
if (w > thresh) w = thresh;
return w;
// let h = document.body.clientHeight;
},
}
https://bullchat.syon.ca/js/lib/qrcode.js
Upvotes: 2
Reputation: 31060
To export:
Session 1:
let user = gun.user()
user.create('Bob','password123',console.log)
user.auth('Bob' ,'password123',console.log)
JSON.stringify(user._.sea) // prompt user to export / "download"
To import:
Session 2:
let user = gun.user()
let imported_JSON //Prompt user to import JSON as imported_JSON
let pair = JSON.parse(imported_JSON)
user.auth(pair,console.log) // user now authorised on session 2
Upvotes: 0