func NewNode(hn coconet.Host, suite abstract.Suite, random cipher.Stream) *Node { sn := &Node{Host: hn, suite: suite} sn.PrivKey = suite.Secret().Pick(random) sn.PubKey = suite.Point().Mul(nil, sn.PrivKey) sn.peerKeys = make(map[string]abstract.Point) sn.closed = make(chan error, 20) sn.done = make(chan int, 10) sn.commitsDone = make(chan int, 10) sn.viewChangeCh = make(chan string, 0) sn.RoundCommits = make(map[int][]*SigningMessage) sn.RoundResponses = make(map[int][]*SigningMessage) sn.FailureRate = 0 h := fnv.New32a() h.Write([]byte(hn.Name())) seed := h.Sum32() sn.Rand = rand.New(rand.NewSource(int64(seed))) sn.Host.SetSuite(suite) sn.VoteLog = NewVoteLog() sn.Actions = make(map[int][]*Vote) sn.RoundsPerView = 0 sn.Rounds = make(map[int]Round) sn.MaxWait = 50 * time.Second return sn }
/* GenerateZ takes some random agreed information and creates Z the "public-only" key that is witness-independent as per the paper. We've probably broken that slightly in this implementation because I could not pick a point without generating it via a Secret, instead of directly via a Point - that is, even as a 32-byte string, we cannot decode on C25519 (and this wouldn't work for abstract suites anyway). However, it demonstrates the idea. */ func GenerateZ(suite abstract.Suite, info []byte) (abstract.Point, error) { hasher := sha3.New256() hasher.Write(info) zraw := hasher.Sum(nil) //I think this might be cheating zrawCt := suite.Cipher(zraw) zfactor := suite.Secret().Pick(zrawCt) Z := suite.Point() Z.Mul(nil, zfactor) // every 32-bit integer exists on Curve25519 only if we have the fullgroup // this should work, but doesn't. /*var Z abstract.Point zrawBuf := bytes.NewBuffer(zraw) err := abstract.Read(zrawBuf, &Z, suite); if err != nil { return nil, err }*/ return Z, nil }
// Binary shuffle ("biffle") for 2 ciphertexts based on general ZKPs. func Biffle(suite abstract.Suite, G, H abstract.Point, X, Y [2]abstract.Point, rand abstract.Cipher) ( Xbar, Ybar [2]abstract.Point, prover proof.Prover) { // Pick the single-bit permutation. bit := int(random.Byte(rand) & 1) // Pick a fresh ElGamal blinding factor for each pair var beta [2]abstract.Secret for i := 0; i < 2; i++ { beta[i] = suite.Secret().Pick(rand) } // Create the output pair vectors for i := 0; i < 2; i++ { pi_i := i ^ bit Xbar[i] = suite.Point().Mul(G, beta[pi_i]) Xbar[i].Add(Xbar[i], X[pi_i]) Ybar[i] = suite.Point().Mul(H, beta[pi_i]) Ybar[i].Add(Ybar[i], Y[pi_i]) } or := bifflePred() secrets := map[string]abstract.Secret{ "beta0": beta[0], "beta1": beta[1]} points := bifflePoints(suite, G, H, X, Y, Xbar, Ybar) choice := map[proof.Predicate]int{or: bit} prover = or.Prover(suite, secrets, points, choice) return }
// Checks the signature against // the message func SchnorrVerify(suite abstract.Suite, kp SchnorrPublicKey, msg []byte, sig []byte) (bool, error) { buf := bytes.NewBuffer(sig) signature := SchnorrSignature{} err := abstract.Read(buf, &signature, suite) if err != nil { return false, err } s := signature.S e := signature.E var gs, ye, r abstract.Point gs = suite.Point().Mul(nil, s) // g^s ye = suite.Point().Mul(kp.Y, e) // y^e r = suite.Point().Add(gs, ye) // g^xy^e r_bin, _ := r.MarshalBinary() msg_and_r := append(msg, r_bin...) hasher := sha3.New256() hasher.Write(msg_and_r) h := hasher.Sum(nil) // again I'm hoping this just reads the state out // and doesn't actually perform any ops lct := suite.Cipher(h) ev := suite.Secret().Pick(lct) return ev.Equal(e), nil }
/* The servergenerateresponse function is fairly self explanatory - this function provides an answer to the challenge message provided by the user. */ func ServerGenerateResponse(suite abstract.Suite, challenge WISchnorrChallengeMessage, privateParameters WISchnorrBlindPrivateParams, privKey SchnorrKeyset) WISchnorrResponseMessage { c := suite.Secret() c.Sub(challenge.E, privateParameters.D) r := suite.Secret() r.Mul(c, privKey.X).Sub(privateParameters.U, r) return WISchnorrResponseMessage{r, c, privateParameters.S, privateParameters.D} }
// Read a secret in hexadceimal from string func ReadSecretHex(suite abstract.Suite, str string) (abstract.Secret, error) { enc, err := hex.DecodeString(str) if err != nil { return nil, err } sec := suite.Secret() err = sec.UnmarshalBinary(enc) return sec, err }
// GenerateKeyPair generates a new random private/public keypair in the specified group func GenerateKeyPair(suite abstract.Suite) (*PriKey, *PubKey) { secret := suite.Secret().Pick(suite.Cipher(nil)) base := suite.Point().Base() pk := PubKey{suite, base, suite.Point().Mul(base, secret)} sk := PriKey{pk, secret} return &sk, &pk }
// generate keys for the tree func (t *Tree) GenKeys(suite abstract.Suite, rand abstract.Cipher) { t.TraverseTree(func(t *Tree) { PrivKey := suite.Secret().Pick(rand) PubKey := suite.Point().Mul(nil, PrivKey) prk, _ := PrivKey.MarshalBinary() pbk, _ := PubKey.MarshalBinary() t.PriKey = string(hex.EncodeToString(prk)) t.PubKey = string(hex.EncodeToString(pbk)) }) }
// (Server side) This function reads the collective challenge // from the wire, generates and serializes a response // to that as a raw "secret" func SchnorrMUnmarshallCCComputeResponse(suite abstract.Suite, kv SchnorrKeyset, privatecommit SchnorrMPrivateCommitment, cc []byte) SchnorrMResponse { hct := suite.Cipher(cc) c := suite.Secret().Pick(hct) r := suite.Secret() r.Mul(c, kv.X).Sub(privatecommit.V, r) return SchnorrMResponse{r} }
func signH1(suite abstract.Suite, H1pre abstract.Cipher, PG, PH abstract.Point) abstract.Secret { H1 := H1pre.Clone() PGb, _ := PG.MarshalBinary() H1.Write(PGb) if PH != nil { PHb, _ := PH.MarshalBinary() H1.Write(PHb) } H1.Message(nil, nil, nil) // finish message absorption return suite.Secret().Pick(H1) }
/* This is the function that given the client's challenge and response from the server is able to compute the final blind signature. This is done on the user side (blindly to the signer). */ func ClientSignBlindly(suite abstract.Suite, clientParameters WISchnorrClientParamersList, responseMsg WISchnorrResponseMessage, pubKey SchnorrPublicKey, msg []byte) (WIBlindSignature, bool) { rho := suite.Secret() omega := suite.Secret() sigma := suite.Secret() delta := suite.Secret() rho.Add(responseMsg.R, clientParameters.T1) omega.Add(responseMsg.C, clientParameters.T2) sigma.Add(responseMsg.S, clientParameters.T3) delta.Add(responseMsg.D, clientParameters.T4) gp := suite.Point() gp.Mul(nil, rho) yw := suite.Point() yw.Mul(pubKey.Y, omega) gpyw := suite.Point() gpyw.Add(gp, yw) bGpyw, _ := gpyw.MarshalBinary() gs := suite.Point() gs.Mul(nil, sigma) zd := suite.Point() zd.Mul(clientParameters.Z, delta) gszd := suite.Point() gszd.Add(gs, zd) bGszd, _ := gszd.MarshalBinary() bZ, _ := clientParameters.Z.MarshalBinary() var combinedmsg []byte combinedmsg = append(combinedmsg, bGpyw...) combinedmsg = append(combinedmsg, bGszd...) combinedmsg = append(combinedmsg, bZ...) combinedmsg = append(combinedmsg, msg...) hasher := sha3.New256() hasher.Write(combinedmsg) bSig := hasher.Sum(nil) bSigCt := suite.Cipher(bSig) sig := suite.Secret().Pick(bSigCt) vsig := suite.Secret() vsig.Add(omega, delta) //fmt.Println(sig) //fmt.Println(vsig) return WIBlindSignature{rho, omega, sigma, delta}, sig.Equal(vsig) }
func ElGamalEncrypt(suite abstract.Suite, pubkey abstract.Point, M abstract.Point) ( K, C abstract.Point, remainder []byte) { // Embed the message (or as much of it as will fit) into a curve point. //M, remainder := suite.Point().Pick(message, random.Stream) // ElGamal-encrypt the point to produce ciphertext (K,C). k := suite.Secret().Pick(random.Stream) // ephemeral private key K = suite.Point().Mul(nil, k) // ephemeral DH public key S := suite.Point().Mul(pubkey, k) // ephemeral DH shared secret C = S.Add(S, M) // message blinded with secret return }
// The schnorrGenerateKeypair does exactly that - // it generates a valid keypair for later use // in producing signatures. // I wanted to add a little bit of proper key // management to the process but I couldn't work out // how to pass a simple random stream to suite.Secret().Pick(). // I looked into Go streams very briefly but decided // I was spending too much time on that // instead I passed /dev/urandom through the cipher // interface. func SchnorrGenerateKeypair(suite abstract.Suite) (SchnorrKeyset, error) { rsource := make([]byte, 16) _, err := rand.Read(rsource) if err != nil { return SchnorrKeyset{}, err } rct := suite.Cipher(rsource) x := suite.Secret().Pick(rct) // some x y := suite.Point().Mul(nil, x) // y = g^x \in G, DLP. return SchnorrKeyset{x, y}, nil }
// this function produces a signature given a response from the server. func SchnorrMComputeSignatureFromResponses(suite abstract.Suite, cc []byte, responses []SchnorrMResponse) SchnorrSignature { hct := suite.Cipher(cc) c := suite.Secret().Pick(hct) // H(m||r) var r abstract.Secret = responses[0].R for _, response := range responses[1:] { r.Add(r, response.R) } return SchnorrSignature{S: r, E: c} }
func SchnorrMGenerateCommitment(suite abstract.Suite) (SchnorrMPrivateCommitment, error) { rsource := make([]byte, 16) _, err := rand.Read(rsource) if err != nil { return SchnorrMPrivateCommitment{}, err } // I have no idea if I just encrypted randomness or not // I'm hoping this just reads the state out. rct := suite.Cipher(rsource) v := suite.Secret().Pick(rct) // some v t := suite.Point().Mul(nil, v) // g^v = t return SchnorrMPrivateCommitment{T: t, V: v}, nil }
func newHost(suite abstract.Suite, rand cipher.Stream, hostname string) *host { h := &host{} h.name = hostname h.log.init(suite) h.pri = suite.Secret().Pick(rand) h.pub = suite.Point().Mul(nil, h.pri) h.id = abstract.HashBytes(suite, h.pub.Encode()) h.peers = make(map[string]*peer) h.trees = make(map[string]*treeNode) return h }
// ReadPrivKey will read the file and decrypt the private key inside // It takes a suite to decrypt and a filename to know where to read // Returns the secret and an error if anything wrong occured func ReadPrivKey(suite abstract.Suite, fileName string) (abstract.Secret, error) { secret := suite.Secret() // Opening files privFile, err := os.Open(fileName) if err != nil { return nil, err } defer privFile.Close() // Read the keys err = suite.Read(privFile, &secret) if err != nil { return nil, err } return secret, nil }
// Initialize... func (sk *SKEME) Init(suite abstract.Suite, rand cipher.Stream, lpri PriKey, rpub Set, hide bool) { sk.suite = suite sk.hide = hide sk.lpri, sk.rpub = lpri, rpub // Create our Diffie-Hellman keypair sk.lx = suite.Secret().Pick(rand) sk.lX = suite.Point().Mul(nil, sk.lx) sk.lXb, _ = sk.lX.MarshalBinary() // Encrypt and send the DH key to the receiver. // This is a deviation from SKEME, to protect message metadata // and further harden messages against tampering or active MITM DoS. sk.lm = Encrypt(suite, rand, sk.lXb, rpub, hide) }
func (c *ownedCoder) RelaySetup(suite abstract.Suite, trusteeinfo [][]byte) { c.commonSetup(suite) // Decode the trustees' composite verifiable DC-net secrets ntrustees := len(trusteeinfo) c.vkeys = make([]abstract.Secret, ntrustees) c.vkey = suite.Secret() for i := range c.vkeys { c.vkeys[i] = c.suite.Secret() c.vkeys[i].UnmarshalBinary(trusteeinfo[i]) c.vkey.Add(c.vkey, c.vkeys[i]) } c.pnull = c.suite.Point().Null() }
func benchGenKeys(suite abstract.Suite, nkeys int) ([]abstract.Point, abstract.Secret) { rand := random.Stream // Create an anonymity set of random "public keys" X := make([]abstract.Point, nkeys) for i := range X { // pick random points X[i], _ = suite.Point().Pick(nil, rand) } // Make just one of them an actual public/private keypair (X[mine],x) x := suite.Secret().Pick(rand) X[0] = suite.Point().Mul(nil, x) return X, x }
// This simplified implementation of ElGamal Signatures is based on // crypto/anon/sig.go func ElGamalSign(suite abstract.Suite, random cipher.Stream, message []byte, privateKey abstract.Secret) BasicSig { // Create random secret v and public point commitment T v := suite.Secret().Pick(random) T := suite.Point().Mul(nil, v) // Create challenge c based on message and T c := hashElGamal(suite, message, T) // Compute response r = v - x*c r := suite.Secret() r.Mul(privateKey, c).Sub(v, r) // Return verifiable signature {c, r} sig := BasicSig{c, r} return sig }
// XXX belongs in crypto package? func keyPair(suite abstract.Suite, rand cipher.Stream, hide bool) (abstract.Point, abstract.Secret, []byte) { x := suite.Secret().Pick(rand) X := suite.Point().Mul(nil, x) if !hide { Xb, _ := X.MarshalBinary() return X, x, Xb } Xh := X.(abstract.Hiding) for { Xb := Xh.HideEncode(rand) // try to encode as uniform blob if Xb != nil { return X, x, Xb // success } x.Pick(rand) // try again with a new key X.Mul(nil, x) } }
// Generates all of the private parameters aside // from the private / public key pair. Do that // separately. func NewPrivateParams(suite abstract.Suite, info []byte) (WISchnorrBlindPrivateParams, error) { r1 := make([]byte, 16) r2 := make([]byte, 16) r3 := make([]byte, 16) v := make([]byte, 16) _, err := rand.Read(r1) if err != nil { return WISchnorrBlindPrivateParams{}, err } _, err = rand.Read(r2) if err != nil { return WISchnorrBlindPrivateParams{}, err } _, err = rand.Read(r3) if err != nil { return WISchnorrBlindPrivateParams{}, err } _, err = rand.Read(v) if err != nil { return WISchnorrBlindPrivateParams{}, err } rc1 := suite.Cipher(r1) rc2 := suite.Cipher(r2) rc3 := suite.Cipher(r3) z, err := GenerateZ(suite, info) if err != nil { return WISchnorrBlindPrivateParams{}, err } u := suite.Secret().Pick(rc1) s := suite.Secret().Pick(rc2) d := suite.Secret().Pick(rc3) a := suite.Point().Mul(nil, u) // g^u b1 := suite.Point().Mul(nil, s) // g^s b2 := suite.Point().Mul(z, d) // z^d b := suite.Point().Add(b1, b2) // g^sz^d return WISchnorrBlindPrivateParams{u, s, d, z, a, b}, nil }
func (c *ownedCoder) ClientSetup(suite abstract.Suite, sharedsecrets []abstract.Cipher) { c.commonSetup(suite) keysize := suite.Cipher(nil).KeySize() // Use the provided shared secrets to seed // a pseudorandom public-key encryption secret, and // a pseudorandom DC-nets cipher shared with each peer. npeers := len(sharedsecrets) c.vkeys = make([]abstract.Secret, npeers) c.vkey = suite.Secret() c.dcciphers = make([]abstract.Cipher, npeers) for i := range sharedsecrets { c.vkeys[i] = suite.Secret().Pick(sharedsecrets[i]) c.vkey.Add(c.vkey, c.vkeys[i]) key := make([]byte, keysize) sharedsecrets[i].Partial(key, key, nil) c.dcciphers[i] = suite.Cipher(key) } }
// This simplified implementation of Schnorr Signatures is based on // crypto/anon/sig.go // The ring structure is removed and // The anonimity set is reduced to one public key = no anonimity func SchnorrSign(suite abstract.Suite, random cipher.Stream, message []byte, privateKey abstract.Secret) net.BasicSignature { // Create random secret v and public point commitment T v := suite.Secret().Pick(random) T := suite.Point().Mul(nil, v) // Create challenge c based on message and T c := hashSchnorr(suite, message, T) // Compute response r = v - x*c r := suite.Secret() r.Mul(privateKey, c).Sub(v, r) // Return verifiable si,gnature {c, r} // Verifier will be able to compute v = r + x*c // And check that hashElgamal for T and the message == c sig := net.BasicSignature{Chall: c, Resp: r} return sig }
// verifyChallenge will reconstruct the challenge in order to see if any of the // components of the challenge has been spoofed or not. It may be a different // timestamp . func VerifyChallenge(suite abstract.Suite, reply *StampSignature) error { dbg.Lvlf3("Reply is %+v", reply) // marshal the V pbuf, err := reply.AggCommit.MarshalBinary() if err != nil { return err } c := suite.Cipher(pbuf) // concat timestamp and merkle root var b bytes.Buffer if err := binary.Write(&b, binary.LittleEndian, reply.Timestamp); err != nil { return err } cbuf := append(b.Bytes(), reply.MerkleRoot...) c.Message(nil, nil, cbuf) challenge := suite.Secret().Pick(c) if challenge.Equal(reply.Challenge) { return nil } return errors.New("Challenge reconstructed is not equal to the one given") }
func NewShuffler(suite abstract.Suite, id, k, N int) *shuffler { rand := suite.Cipher([]byte(fmt.Sprintf("key%d", id))) // This server's own keypair. h := suite.Secret().Pick(rand) H := suite.Point().Mul(nil, h) // The keypairs for the other servers. HH := make([]abstract.Point, N) for i := 0; i < N; i++ { r := suite.Cipher([]byte(fmt.Sprintf("key%d", i))) x := suite.Secret().Pick(r) HH[i] = suite.Point().Mul(nil, x) } // Constructors for use with protobuf. cons := func(t reflect.Type) interface{} { switch t { case tSecret: return suite.Secret() case tPoint: return suite.Point() default: return nil } } s := &shuffler{suite, id, k, N, h, H, HH, cons, nil, nil, nil} return s }
// This simplified implementation of ElGamal Signatures is based on // crypto/anon/sig.go // The ring structure is removed and // The anonimity set is reduced to one public key = no anonimity func ElGamalSign(suite abstract.Suite, random cipher.Stream, message []byte, privateKey abstract.Secret, g abstract.Point) []byte { // Create random secret v and public point commitment T v := suite.Secret().Pick(random) T := suite.Point().Mul(g, v) // Create challenge c based on message and T c := hashElGamal(suite, message, T) // Compute response r = v - x*c r := suite.Secret() r.Mul(privateKey, c).Sub(v, r) // Return verifiable signature {c, r} // Verifier will be able to compute v = r + x*c // And check that hashElgamal for T and the message == c buf := bytes.Buffer{} sig := basicSig{c, r} abstract.Write(&buf, &sig, suite) return buf.Bytes() }
/* This function implements the verification protocol and can be used by any party given a decoded schnorr signature, a message and valid information. Invalid information will break the protocol and produce an invalid message; this is tested for in the unit test code. */ func VerifyBlindSignature(suite abstract.Suite, pk SchnorrPublicKey, sig WIBlindSignature, info []byte, msg []byte) (bool, error) { z, err := GenerateZ(suite, info) if err != nil { return false, err } gp := suite.Point().Mul(nil, sig.P) yw := suite.Point().Mul(pk.Y, sig.W) gpyw := suite.Point().Add(gp, yw) gs := suite.Point().Mul(nil, sig.S) zd := suite.Point().Mul(z, sig.D) gszd := suite.Point().Add(gs, zd) bP1, _ := gpyw.MarshalBinary() bP2, _ := gszd.MarshalBinary() bZ, _ := z.MarshalBinary() var combinedmsg []byte combinedmsg = append(combinedmsg, bP1...) combinedmsg = append(combinedmsg, bP2...) combinedmsg = append(combinedmsg, bZ...) combinedmsg = append(combinedmsg, msg...) hasher := sha3.New256() hasher.Write(combinedmsg) bSig := hasher.Sum(nil) bSigCt := suite.Cipher(bSig) hsig := suite.Secret().Pick(bSigCt) vsig := suite.Secret() vsig.Add(sig.W, sig.D) return hsig.Equal(vsig), nil }
// A simple verification of a Schnorr signature given the message func VerifySchnorr(suite abstract.Suite, message []byte, publicKey abstract.Point, c, r abstract.Secret) error { // Check that: base**r_hat * X_hat**c == V_hat // Equivalent to base**(r+xc) == base**(v) == T in vanillaElGamal Aux := suite.Point() V_clean := suite.Point() V_clean.Add(V_clean.Mul(nil, r), Aux.Mul(publicKey, c)) // T is the recreated V_hat T := suite.Point().Null() T.Add(T, V_clean) // Verify that the hash based on the message and T // matches the challange c from the signature // copy of hashSchnorr bufPoint, _ := T.MarshalBinary() cipher := suite.Cipher(bufPoint) cipher.Message(nil, nil, message) hash := suite.Secret().Pick(cipher) if !hash.Equal(c) { return errors.New("invalid signature") } return nil }