Instantly share code, notes, and snippets.
Created
January 16, 2020 20:32
-
Star
1
(1)
You must be signed in to star a gist -
Fork
3
(3)
You must be signed in to fork a gist
-
Save pszabop/c18769b19f7f809ae90fcf86fe7a9a4e to your computer and use it in GitHub Desktop.
Example of using Gun to share a secret with another user. Includes unit tests.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// alas this generates the warning `user.pair() IS DEPRECATED AND WILL BE DELETED!!!` | |
// | |
// put a value shared between two users | |
// user and this user (classic public key encryption, except that a session | |
// key is used instead of encrypting the data with the public key. | |
// analagous to `openssl pkeyutl -derive -inkey key.pem -peerkey pubkey.pem -out secret` | |
// | |
// @param: key - the key where the value is stored | |
// @param: value - the value to store at index key | |
// @param: otherUser - the info or public key of the other user to share the value with | |
// | |
// @returns: encrypted version that was put into the database | |
// | |
gundb.userPutShared = async function(key, value, otherUser) { | |
const thisPair = this.gun.user().pair(); | |
const otherPub = otherUser.pub || otherUser; | |
const encryptedValue = await Sea.encrypt(value, await Sea.secret(otherUser, thisPair)); | |
//console.log('--enc value'); | |
//console.log(encryptedValue); | |
return await this.userPut(key, encryptedValue); | |
} | |
/* | |
* get a value shared from another user | |
* (classic public key encryption, except that a session * key is used) | |
* | |
* @param: key - the key where the value is stored | |
* @param: otherUser - the info or public key of the other user who shared this value with us | |
* | |
* @returns: plaintext version of what was shared into the database | |
*/ | |
gundb.userGetShared = async function(key, otherUser) { | |
const thisPair = this.gun.user().pair(); | |
const otherPub = otherUser.pub || otherUser; | |
const encryptedValue = await this.userGet(key, otherPub); | |
const result = await Sea.decrypt(encryptedValue, await Sea.secret(otherUser, thisPair)); | |
return result; | |
} | |
/* | |
* get a value to the key in the current user's or other user's keyspace | |
* | |
* @param key - the unique key where the value is put | |
* @pubKey - optional pubKey or result of user.is if attempting to get another user's info | |
* The default user is the user currently attached to this gundb instance | |
*/ | |
gundb.userGet = async function(key, pubKey) { | |
let value; | |
if (pubKey) { | |
const actualPubKey = pubKey.pub || pubKey; | |
value = await this.gun.user(actualPubKey).get(key).then() | |
} else { | |
value = await this.gun.user().get(key).then(); | |
} | |
try { | |
return JSON.parse(Base64.decode(value)); | |
} catch (e) { | |
console.log(`---unabletoparse: ${value}`); | |
console.log(JSON.stringify(value, null, 2)); | |
return undefined | |
} | |
}; | |
/* | |
* put a value to the key in the current user's keyspace | |
* | |
* @param key - the unique key where the value is put | |
* @param value - the value to be put. | |
*/ | |
gundb.userPut = async function(key, value) { | |
const encoded = Base64.encode(JSON.stringify(value)); | |
const finalValue = await this.gun.user().get(key).put(encoded).then(); | |
return JSON.parse(Base64.decode(finalValue)); | |
}; | |
///-------------------- unit test | |
test('share secret data between two users', async function(t) { | |
const username1 = random.string(16) + '@example.com'; | |
const password1 = 'password1'; | |
const username2 = random.string(16) + '@example.com'; | |
const password2 = 'password2'; | |
const username3 = random.string(16) + '@example.com'; | |
const password3 = 'password3'; | |
const key = 'key' + random.string(16); | |
const value = 'value' + random.string(16); | |
// create three gun instances, two pointing at one | |
const gundb1 = Object.create(gundb); | |
const gundb2 = Object.create(gundb); | |
const gundb3 = Object.create(gundb); | |
gundb1.init({port: 8080}); | |
gundb2.init({port: 8081, peers: ['http://localhost:8080/gun']}); | |
gundb3.init({port: 8082, peers: ['http://localhost:8080/gun']}); | |
// create and authorize a user per gundb | |
const userInfo1 = await gundb1.userCreate(username1, password1); | |
const userInfo2 = await gundb2.userCreate(username2, password2); | |
const userInfo3 = await gundb3.userCreate(username3, password3); | |
// now put something there. Hopefully it gets encrypted? | |
//const putResult = await gundb1.userPut(key, value); | |
const result = await gundb1.userPutShared(key, value, userInfo2); | |
//t.equal(result, value, 'value from grant was what was put'); | |
const otherUserGetResult = await gundb2.userGetShared(key, userInfo1); | |
t.equal(otherUserGetResult, value, 'value the other user sees was what was granted'); | |
const thirdUserGetResult = await gundb3.userGetShared(key, userInfo1); | |
t.equal(thirdUserGetResult, undefined, 'value the third user sees is undefined as they were not granted the right to see it'); | |
//console.log(getResult); | |
gundb1.shutdown(); | |
gundb2.shutdown(); | |
gundb3.shutdown(); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment