Skip to content

Instantly share code, notes, and snippets.

@wilsonianb
Last active December 16, 2018 10:58
Show Gist options
  • Save wilsonianb/3e7354ee08ad2a9325c2b311c96f7a65 to your computer and use it in GitHub Desktop.
Save wilsonianb/3e7354ee08ad2a9325c2b311c96f7a65 to your computer and use it in GitHub Desktop.
const brorand = require('brorand')
const elliptic = require('elliptic')
const Ed25519 = elliptic.eddsa('ed25519')
const hashjs = require('hash.js')
function hash(message) {
return hashjs.sha512().update(message).digest().slice(0, 32)
}
function getL(Xs) {
return Ed25519.hashInt.apply(Ed25519, Xs)
}
function getAggregatePublicKey(L, Xs) {
let X = Ed25519.decodePoint(Xs[0]).mul(Ed25519.hashInt(L, Xs[0]))
for (let i=1; i<Xs.length; i++) {
X = X.add(Ed25519.decodePoint(Xs[i]).mul(Ed25519.hashInt(L, Xs[i])))
}
return Ed25519.encodePoint(X)
}
function getR(Rs) {
let R = Rs[0]
for (let i=1; i<Rs.length; i++) {
R = R.add(Rs[i])
}
return Ed25519.encodePoint(R)
}
function getSi(ri, X, R, m, L, xi, Xi) {
const message = elliptic.utils.parseBytes(m);
var s_ = Ed25519.hashInt(R, X, message)
.mul(Ed25519.hashInt(L, Xi))
.mul(xi)
var si = ri.add(s_).umod(Ed25519.curve.n)
return Ed25519.makeSignature({ R: Ed25519.decodePoint(R), S: si, Rencoded: R })
}
function combine(sigs, R) {
let S = sigs[0].S()
for (let i=1; i<sigs.length; i++) {
S = S.add(sigs[i].S())
}
return Ed25519.makeSignature({ R: Ed25519.decodePoint(R), S: S, Rencoded: R })
}
// https://blockstream.com/2018/01/23/musig-key-aggregation-schnorr-signatures.html
const n = 7
let xs = []
let Xs = []
for (let i=0; i<n; i++) {
const kp = Ed25519.keyFromSecret(hash(brorand(16)))
xs.push(kp.priv())
Xs.push(kp.pubBytes())
}
// Call L = H(X1,X2,…)
const L = getL(Xs)
// Call X the sum of all H(L,Xi)Xi
const X = getAggregatePublicKey(L, Xs)
// Each signer chooses a random nonce ri, and shares Ri = riG with the other signers
let rs = []
let Rs = []
let ts = []
for (let i=0; i<n; i++) {
const kp = Ed25519.keyFromSecret(hash(brorand(16)))
rs.push(kp.priv())
Rs.push(kp.pub())
ts.push(Ed25519.hashInt(kp.pub()))
}
// Call R the sum of the Ri points
const R = getR(Rs)
const msg = Ed25519.hashInt('howdy')
// Each signer computes si = ri + H(X,R,m)H(L,Xi)xi
let sigs = []
for (let i=0; i<n; i++) {
sigs.push(getSi(rs[i], X, R, msg, L, xs[i], Xs[i]))
}
// The final signature is (R,s) where s is the sum of the si values
const s = combine(sigs, R)
// Verification satisfies sG = R + H(X,R,m)X
console.log(Ed25519.verify(msg, s, X))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment