Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sodium signatures #203

Open
emilbayes opened this issue Aug 18, 2018 · 2 comments
Open

Sodium signatures #203

emilbayes opened this issue Aug 18, 2018 · 2 comments

Comments

@emilbayes
Copy link
Contributor

emilbayes commented Aug 18, 2018

Hi! The readme specifically mentions that sodium signatures will not work with BEP44, however I've done some research for my rendezvous-point module and this is not true. ed25519-supercop is based on ref10 and so is sodium. The difference is in the private key encoding, but one can convert to supercop keys if need be: https://github.com/emilbayes/sodium2supercop

However, the secret key is not exposed or used beyond generating signatures and as such any implementation can be used, as long as they generate valid EdDSA signatures. I'm happy to make amends to the readme, I just want to make sure to what extent :) I have a verification script here if anyone is interested: https://gist.github.com/emilbayes/66c955cc49da387ee2ab9c3a76aa9238

The examples would look something like the following, using @mafintosh high-level sodium-signatures module. Straight up sodium-native/sodium-universal could also be used with a bit more boilerplate:

var eddsa = require('sodium-signatures')
var dht = new DHT({ verify: eddsa.verify })
var eddsa = require('sodium-signatures')
var keypair = eddsa.keyPair()

var value = Buffer.alloc(200).fill('whatever') // the payload you want to send
var opts = {
  k: keypair.publicKey,
  seq: 0,
  v: value,
  sign: function (buf) {
    return eddsa.sign(buf, keypair.secretKey)
  }
}

var DHT = require('bittorrent-dht')
var dht = new DHT

dht.put(opts, function (err, hash) {
  console.error('error=', err)
  console.log('hash=', hash)
})
@emilbayes
Copy link
Contributor Author

Today this could look like: https://gist.github.com/emilbayes/2be519c110054034501de44682bd7533

const sodium = require('sodium-native')
const DHT = require('bittorrent-dht')
const dht = new DHT({
  verify: sodium.crypto_sign_verify_detached
})

const keys = keygen()

dht.put({
  v: Buffer.from('Hello world'),
  k: keys.pk,
  seq: 0,
  sign: (msg) => {
    const sig = Buffer.alloc(sodium.crypto_sign_BYTES)
    sodium.crypto_sign_detached(sig, msg, keys.sk)
    return sig
  }
}, function (err, hash) {
  // ...
})

// Optionally pass an exisiting secret key and rederive the public key
function keygen (sk) {
  const pk = Buffer.alloc(sodium.crypto_sign_PUBLICKEYBYTES)
  if (sk == null) {
    sk = sodium.sodium_malloc(sodium.crypto_sign_SECRETKEYBYTES)
    sodium.crypto_sign_keypair(pk, sk)
  } else {
    sodium.crypto_sign_ed25519_sk_to_pk(pk, sk)
  }

  return { pk, sk }
}

@emilbayes
Copy link
Contributor Author

One note is that the BEP44 test vectors cannot be implemented due to how private keys are encoded differently. In sodium private keys are a bytearray of publickey || random seed while the test vectors (and supercop) encode private keys as sha512(random seed). Since you cannot get back the original seed (preimage) of the hash function, the two private key formats are incompatible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant