Search code examples
javascriptgraphgungundb

GunDB SEA let other user write to user space


I need to exchange private data in user space.

because gun.grant and gun.trust is deprecated, I followed this example:

https://gun.eco/docs/SEA#quickstart

<script src="https://cdn.jsdelivr.net/npm/gun/gun.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gun/sea.js"></script>
<script>
// var Gun = require('gun'); // in NodeJS 
// require('gun/sea');
var SEA = Gun.SEA;
;(async () => {
var pair = await SEA.pair();
var enc = await SEA.encrypt('hello self', pair);
var data = await SEA.sign(enc, pair);
console.log(data);
var msg = await SEA.verify(data, pair.pub);
var dec = await SEA.decrypt(msg, pair);
var proof = await SEA.work(dec, pair);
var check = await SEA.work('hello self', pair);
console.log(dec);
console.log(proof === check);
// now let's share private data with someone:
var alice = await SEA.pair();
var bob = await SEA.pair();
var enc = await SEA.encrypt('shared secret', await SEA.secret(bob.epub, alice));
await SEA.decrypt(enc, await SEA.secret(alice.epub, bob));
// `.secret` is Elliptic-curve Diffie–Hellman
// Bob allows Alice to write to part of his graph, he creates a certificate for Alice
var certificate = await SEA.certify(alice.pub, ["^AliceOnly.*"], bob)
// Alice logs in 
const gun = Gun();
await gun.user().auth(alice);
// and uses the certificate
await gun.get('~'+bob.pub).get('AliceOnly').get('do-not-tell-anyone').put(enc, null, {opt: {cert: certificate}})
await gun.get('~'+bob.pub).get('AliceOnly').get('do-not-tell-anyone').once(console.log) // return 'enc'
})();
</script>

but it always throws "Certificate verification fail."

I tried user.auth instead of SEA.pair() but still not working


Solution

  • SEA.certify will replace the deprecated methods to enable others to write on your graph. SEA.certify

    var Alice = await SEA.pair()
    var Bob = await SEA.pair()
    var Dave = await SEA.pair()
    
    // Alice wants to allow Bob and Dave to use write to her "inbox" and "stories" UNTIL TOMORROW
    // On Alice's side:
    var certificate = await SEA.certify([Bob.pub, Dave.pub], [{"*": "inbox", "+": "*"}, {"*": "stories"}], Alice, null, {expiry: Gun.state()+(60*60*24*1000)})
    
    // Now on Bob/Dave's side, they can write to Alice's graph using gun.put:
    gun.get('~'+Alice.pub).get('inbox').get('deeper'+Bob.pub).put('hello world', null, {opt: {cert: certificate}}) // {opt: {cert: certificate}} is how you use Certificate in gun.put
    

    On a related note, there are some other very useful encryption examples here.

    For the sake of this answer I will post them:

    1-to-1 encryption

    ///////////////////////////////////
    // 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 users encryption

    (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);
    });