Gun: SEA.work on safari generated different results for same input

Created on 9 Feb 2021  路  9Comments  路  Source: amark/gun

When this is run in Safari browser it generates different result each time it is run:

(async ()=>{message = await SEA.work('hello world',null, null, {name: "SHA-256"}); console.log(message);})()

Works fine on Chrome.

Version 14.0.1 (16610.2.11.51.8)
Safari dev console.
image

Also tried undefined instead of null - same result

bug?

Most helpful comment

@i001962 that seems to be right.
@amark @mhelander , should we change SEA to not create a random salt by default?

All 9 comments

not sure why it works on chrome it shouldnt, but the second argument for work is the "salt"
if you do not specify the salt it will be random which is why you get different results each time.
here is the snippet from SEA.work

SEA.work = SEA.work || (async (data, pair, cb, opt) => { try { // used to be named `proof`
      var salt = (pair||{}).epub || pair; // epub not recommended, salt should be random!
      var opt = opt || {};
      if(salt instanceof Function){
        cb = salt;
        salt = u;
      }
      data = (typeof data == 'string')? data : await shim.stringify(data);
      if('sha' === (opt.name||'').toLowerCase().slice(0,3)){
        var rsha = shim.Buffer.from(await sha(data, opt.name), 'binary').toString(opt.encode || 'base64')
        if(cb){ try{ cb(rsha) }catch(e){console.log(e)} }
        return rsha;
      }
      salt = salt || shim.random(9);

Hmm. OK. So there no SEA method for hashing without a salt.
Seems like an important capability for content addressing as instructed here - https://gun.eco/docs/Content-Addressing

I'd keep this open with the following goal:
null, null should not add salt. Unless I'm missing how one would use content addressing which is entirely possible.

var hash = await SEA.work('hash me', null, null, {name: "SHA-256"});
gun.get('#').get(hash).put('hash me');

gun.get('#').get(hash).once(console.log);

To this end (hash addressable content), it may be more useful to default gun.get('#').get(hash).put('hash me'); to return/accept url friendly hex.

@i001962 that seems to be right.
@amark @mhelander , should we change SEA to not create a random salt by default?

Oh, it was a feature, not a bug. As a workaround for Iris, I had used a patched version of work() that only does SHA-256 hashes. Support for null salt should be added. Awesome that this "mystery bug" is fixable 馃槃

@mmalmi correct, by default it extends (with random salt if not provided) else could lead to a security vulnerability in proof of work if a developer is not checking inputs carefully (they'll be vulnerable to an instant rainbow attack).

If you specify SHA tho then see @sirpy 's highlight, it goes into the IF and the salt is ignored (not used) and is not random because it never reaches the shim.random( call. This is safe by default because hashes are used for checksums.

That said, it does look like @i001962 's issue is that Safari is producing proofs of work, given the length (they're long), not hashes (they're short) despite passing SHA in. By chance can you console.log(SEA.err) after calling it? So maybe there is an issue with the options deconstructing that doesn't work in Safari? My Safari crashes entirely => ES6+ not supported, so I can't test/replicate (need someone to PR a refactor to ES5).

(An aside: dangit, I renamed it to SEA.work from SEA.proof but now I'm realizing I probably should have kept it as .proof( because an extension is a proof of work, and a hash is a proof of validity - hmm, unless hashes should actually be part of .verify( not .proof( ? Tho signature verification uses asymmetry while both PBKDF2 or Argon2 are symmetric hashes that extend just like SHA/md5/etc. are symmetric hashes that shrink to a checksum, so they seem more like the same "category" or "family" of work. GAH! I just said "work", not "proof"... whatever we can discuss this later. Naming is just very important to me.)

Sea.hash seems like a reasonable function to create. Verify is like a higher order function (if you will) when comparing it to .hash Same with .work/proof. .hash could evolve later to support multihash https://github.com/multiformats/multihash

@i001962 I still needed you to confirm (A) did the code change fix Safari (see my above comment about me not being able to test myself)? (B) is there a SEA.err after the broken calls?

While the 'fix' does work on safari ie it creates the same result when this is run:

(async ()=>{message = await SEA.work('hello world',null, null, {name: "SHA-256"}); console.log(message);})()

It does NOT respect the encode. eg on safari:
image

on chrome it respects the encode: hex but returns a short hash (looks like base64) when run without an explicit encode
image

Thanks for doing this on your machine, this is now fixed in https://github.com/amark/gun/pull/1062 ! :) Closing.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

bugs181 picture bugs181  路  3Comments

finwo picture finwo  路  5Comments

amark picture amark  路  7Comments

danfinlay picture danfinlay  路  3Comments

biocrypto730 picture biocrypto730  路  5Comments