Snippets - amark/gun GitHub Wiki

Simple encryption - 1 to 1

This an example of how you can share encrypted data between two people. Summary:

  • user1 generates a secret based on his private key and user2's pub key
  • user1 encrypts a plain text message using the secret
  • user2 generates the equivalent of the same secret using user2 private key and user1 pub key
  • user2 decrypts the encrypted message using the secret
///////////////////////////////////
// On my side - logged in as myself
///////////////////////////////////
var myPair = gun.user()._.sea;
// retrieve bob's user
const bob = gun.user(bobPublicKey);
// generate encryption secret using bob's epub and my pair
// this means only bob will be able to regenerate this secret with my pub key and his pair
const secret = await SEA.secret(bob.epub, myPair)
// encrypt the data using the secret
const encryptedData = await SEA.encrypt('private message for bob', secret);

////////////////////////////////////
// on Bob's side - logged in as Bob
///////////////////////////////////
const myPair = gun.user()._.sea;
// generate the secret - this will output the same secret generated by myself
// but this time we generate with bobs pair and my epub
const secret = await SEA.secret(myPair.epub, bob)
// just decrypt the data using the secret
const decryptedData = await SEA.decrypt(encryptedData, secret);

Multiple people encryption

This example shows how to encrypt data that can be decrypted by multiple people, each of them having their own secret.

Summary:

  • user1 comes up with a plain text encryption key (it can be any text string)
  • user1 encrypts some sensitive data using the plain text encryption key
  • user1 wants to allow user2 to decrypt the data so he is generating a secret based on user1 private key and user2 pub key
  • user1 uses this secret to encrypt the encryption key and shares this secret with user2
  • user2 generates a secret with user2 private key and user1 pub key
  • user2 uses the secret to decrypt the encryption key which was shared with him by user1
  • user2 uses this decrypted encryption key to decrypt the sensitive data that he wanted
(async () => {
  
  /////////////////////////////////////////////////////////////////
  // Instead of logging in with actual users, we are 
  // going to generate SEA pairs which is basically the same thing
  /////////////////////////////////////////////////////////////////
  
  // User 1 encrypts one message
  const user1 = await SEA.pair();
  
  const plainMessage = 'Hello, how are you?';
  const encryptionKey = 'this is my encryption key which is a normal string';
  const encryptedMessage = await SEA.encrypt(plainMessage, encryptionKey);
  
  // User 2, 3 and 4 will receive the message and decrypt it
  const user2 = await SEA.pair();
  const user3 = await SEA.pair();
  const user4 = await SEA.pair();
  
  // Each user gets an encrypted encryption key. If you print them, they all different
  const encryptedEncryptionKeyUser2 = await SEA.encrypt(encryptionKey, await SEA.secret(user2.epub, user1));
  const encryptedEncryptionKeyUser3 = await SEA.encrypt(encryptionKey, await SEA.secret(user3.epub, user1));
  const encryptedEncryptionKeyUser4 = await SEA.encrypt(encryptionKey, await SEA.secret(user4.epub, user1));
  
 
  // Each user decrypts his own encrypted encryption key
  // These three decrypted encryptions keys that we get are all the same
  const decryptedEncryptionKeyUser2 = await SEA.decrypt(
    encryptedEncryptionKeyUser2, 
    await SEA.secret(user1.epub, user2)
  );
  const decryptedEncryptionKeyUser3 = await SEA.decrypt(
    encryptedEncryptionKeyUser3, 
    await SEA.secret(user1.epub, user3)
  );
  const decryptedEncryptionKeyUser4 = await SEA.decrypt(
    encryptedEncryptionKeyUser4, 
    await SEA.secret(user1.epub, user4)
  );
  
  // Each user decrypts the encrypted message using the decrypted encryption key
  const decryptedMessageUser2 = await SEA.decrypt(encryptedMessage, decryptedEncryptionKeyUser2);
  const decryptedMessageUser3 = await SEA.decrypt(encryptedMessage, decryptedEncryptionKeyUser3);
  const decryptedMessageUser4 = await SEA.decrypt(encryptedMessage, decryptedEncryptionKeyUser4);
});

Saving Arrays in Gun

Gun does not allow saving arrays directly. Because of this, we have to turn arrays into indexed objects. Technically, they become objects but practically we can still use it as collections of items.

In order to do achieve this, we need two functions. The function getIndexedObjectFromArray converts Arrays into something that Gun likes. The second one, getArrayFromIndexedObject turns them back into plain Arrays.

const getIndexedObjectFromArray = (arr) => {
  return arr.reduce((acc, item) => {
    return {
      ...acc,
      [item.id]: item,
    }
  }, {});
};

const getArrayFromIndexedObject = (indexedObj) => {
  return Object.values(indexedObj);
};

If you have this array which you want to save in Gun:

const animals = [{ id: '1', name: 'Dog'}, { id: '2', name: 'Cat'}];

const indexedAnimals = getIndexedObjectFromArray(animals);
/*
{
    "1": {
        "id": "1",
        "name": "Dog"
    },
    "2": {
        "id": "2",
        "name": "Cat"
    }
};
*/

// save to gun
gun.get('animals').put(indexedAnimals);


// retrieve from gun individual animals
gun.get('animals').get('1').on(/* do something */);

// retrieve from gun the entire collection as a whole
gun.get('animals').load((data) => {
  delete data._;
  const normalAnimals = getArrayFromIndexedObject(data);
  /*
  [
    {
        "id": "1",
        "name": "Dog"
    },
    {
        "id": "2",
        "name": "Cat"
    }
  ]
  */
});