Skip to content

Instantly share code, notes, and snippets.

@pszabop
Created January 16, 2020 20:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save pszabop/c18769b19f7f809ae90fcf86fe7a9a4e to your computer and use it in GitHub Desktop.
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.
// 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