func (snLog SNLog) MarshalBinary() ([]byte, error) { // abstract.Write used to encode/ marshal crypto types b := bytes.Buffer{} abstract.Write(&b, &snLog.v, snLog.Suite) abstract.Write(&b, &snLog.V, snLog.Suite) abstract.Write(&b, &snLog.V_hat, snLog.Suite) // gob is used to encode non-crypto types enc := gob.NewEncoder(&b) err := enc.Encode(snLog.CMTRoots) return b.Bytes(), err }
func FromPointToByte(p abstract.Point, params P256Params) []byte { b := bytes.Buffer{} abstract.Write(&b, p, params.Suite) //b,err := p.MarshalBinary() //CheckErr(err,"[-] Error while marshiling point") return b.Bytes() }
func RunClient(s1, s2 Server, params P256Params, ch chan string) { // Create the client client := &Client{Params: params, Ch: ch, Servers: [2]Server{s1, s2}} // Connect to the servers b1 := client.Connect(s1.Address, 0) b2 := client.Connect(s2.Address, 1) defer func() { client.Servers[0].Con.Close(); client.Servers[1].Con.Close() }() if !b1 || !b2 { fmt.Fprintf(os.Stderr, "Could not connect to servers. Abort.") os.Exit(1) } // Message to send msg := GenerateRandomBytes(1024) client.SendToBoth(msg, "Error while sending original message") client.Ch <- "Sent message to both servers (" + strconv.Itoa(len(msg)) + " bytes)" // Receive the partial commitment of each client.Ch <- fmt.Sprintf("Waiting for the partial commitment of both servers...") pcb1, pcb2 := client.ReceiveFromBoth("Error while waiting the two partial commitment ..") client.Ch <- fmt.Sprintf("Received partial commitment from servers (%d,%d bytes) ", len(pcb1), len(pcb2)) pc1, pc2 := FromByteToPoint(pcb1, params), FromByteToPoint(pcb2, params) // Aggregate the commitment and send back to the servers aggregateCommitment := pc1.Add(pc1, pc2) acb := FromPointToByte(aggregateCommitment, params) client.SendToBoth(acb, "Error while sending the aggregateCommitment to both servers") client.Ch <- fmt.Sprintf("Sent aggregate commitment (%d bytes) to both servers", len(acb)) //compute collective challenge challenge := hashSchnorr(params.Suite, msg, aggregateCommitment) // Receive partial response share from clients prb1, prb2 := client.ReceiveFromBoth("Error while receiving partial response from servers") pr1, pr2 := FromByteToSecret(prb1, params), FromByteToSecret(prb2, params) client.Ch <- "Received both partial responses of servers..." // VERIFY // compute combined secret + combined public keys combinedResponse := pr1.Add(pr1, pr2) combinedPublicKey := s1.PublicKey.Add(s1.PublicKey, s2.PublicKey) // Combined Signature (to check with the already coded Schnorr verify) signature := bytes.Buffer{} sig := basicSig{challenge, combinedResponse} abstract.Write(&signature, &sig, params.Suite) err := SchnorrVerify(params.Suite, msg, combinedPublicKey, signature.Bytes()) client.Ch <- "Verifying signature ..." CheckErr(err, "[-] Varying failed :( ") client.Ch <- "Signature passed !! " // ACK client.SendToBoth([]byte("ACK"), "Error while sending ACK to servers.. ") time.Sleep(1 * time.Second) }
// Saves only the public key to disk. func SchnorrSavePubkey(path string, suite abstract.Suite, k SchnorrPublicKey) error { buf := bytes.Buffer{} abstract.Write(&buf, &k, suite) f, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR, 0644) if err != nil { return err } defer f.Close() _, e2 := f.Write(buf.Bytes()) return e2 }
// Saves the keypair as a binary blob on disk. The file format // matches abstract.Write(...) so whatever that uses, we're using here. func SchnorrSaveKeypair(path string, suite abstract.Suite, kv SchnorrKeyset) error { buf := bytes.Buffer{} abstract.Write(&buf, &kv, suite) f, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR, 0600) if err != nil { return err } defer f.Close() _, e2 := f.Write(buf.Bytes()) return e2 }
func encodeAsB64(y abstract.Point) string { // there must be better ways of doing this. Ideally, // we should have JSON marshalling for the // point, secret types in dedis/crypto // but we don't, so, that's a shame. suite := ed25519.NewAES128SHA256Ed25519(true) buf := bytes.Buffer{} abstract.Write(&buf, &y, suite) return hex.EncodeToString(buf.Bytes()) }
// 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() }
// Generate a new public/private keypair with the given ciphersuite // and Save it to the application's previously-loaded configuration. func (f *File) GenKey(keys *Keys, suite abstract.Suite) (KeyPair, error) { // Create the map if it doesn't exist // if *keys == nil { // *keys = make(map[string] KeyInfo) // } // Create a fresh public/private keypair p := KeyPair{} p.Gen(suite, random.Stream) pubId := p.PubId() // Write the private key file secname := f.dirName + "/sec-" + pubId r := util.Replacer{} if err := r.Open(secname); err != nil { return KeyPair{}, err } defer r.Abort() // Write the secret key if err := abstract.Write(r.File, &p.Secret, suite); err != nil { return KeyPair{}, err } // Commit the secret key if err := r.Commit(); err != nil { return KeyPair{}, err } // Re-write the config file with the new public key *keys = append(*keys, KeyInfo{suite.String(), pubId}) if err := f.Save(); err != nil { return KeyPair{}, err } return p, nil }
// Signs a given message and returns the signature. // If no signature is possible due to an error // returns the error in the second retval. func SchnorrSign(suite abstract.Suite, kv SchnorrKeyset, msg []byte) ([]byte, error) { rsource := make([]byte, 16) _, err := rand.Read(rsource) if err != nil { return nil, 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) k := suite.Secret().Pick(rct) // some k r := suite.Point().Mul(nil, k) // g^k 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 hct := suite.Cipher(h) e := suite.Secret().Pick(hct) // H(m||r) s := suite.Secret() s.Mul(kv.X, e).Sub(k, s) // k - xe sig := SchnorrSignature{S: s, E: e} buf := bytes.Buffer{} abstract.Write(&buf, &sig, suite) return buf.Bytes(), nil }
func TestMultisignature5ServerScenario(t *testing.T) { suite := ed25519.NewAES128SHA256Ed25519(true) // Generate ourselves two keypairs, one for each "server" kv_1, err := SchnorrGenerateKeypair(suite) if err != nil { t.Error(err.Error()) } kv_2, err := SchnorrGenerateKeypair(suite) if err != nil { t.Error(err.Error()) } kv_3, err := SchnorrGenerateKeypair(suite) if err != nil { t.Error(err.Error()) } kv_4, err := SchnorrGenerateKeypair(suite) if err != nil { t.Error(err.Error()) } kv_5, err := SchnorrGenerateKeypair(suite) if err != nil { t.Error(err.Error()) } // Make a random message and "send" it to the server randomdata := make([]byte, 1024) _, err = rand.Read(randomdata) if err != nil { fmt.Println(err.Error()) return } // client side // compute the shared public key given the public keys of each // participant. pks := []SchnorrPublicKey{SchnorrExtractPubkey(kv_1), SchnorrExtractPubkey(kv_2), SchnorrExtractPubkey(kv_3), SchnorrExtractPubkey(kv_4), SchnorrExtractPubkey(kv_5)} sharedpubkey := SchnorrMComputeSharedPublicKey(suite, pks) // SERVER // In response to this each server will generate two // arbitrary secrets and respond with a commitment. commit1, err := SchnorrMGenerateCommitment(suite) if err != nil { t.Error(err.Error()) } commit2, err := SchnorrMGenerateCommitment(suite) if err != nil { t.Error(err.Error()) } commit3, err := SchnorrMGenerateCommitment(suite) if err != nil { t.Error(err.Error()) } commit4, err := SchnorrMGenerateCommitment(suite) if err != nil { t.Error(err.Error()) } commit5, err := SchnorrMGenerateCommitment(suite) if err != nil { t.Error(err.Error()) } // Client side commit_array := []SchnorrMPublicCommitment{SchnorrMPublicCommitment{commit1.PublicCommitment().T}, SchnorrMPublicCommitment{commit2.PublicCommitment().T}, SchnorrMPublicCommitment{commit3.PublicCommitment().T}, SchnorrMPublicCommitment{commit4.PublicCommitment().T}, SchnorrMPublicCommitment{commit5.PublicCommitment().T}} aggregate_commitment := SchnorrMComputeAggregateCommitment(suite, commit_array) // client and servers collective_challenge := SchnorrMComputeCollectiveChallenge(suite, randomdata, aggregate_commitment) // servers respond to client with responses response_1 := SchnorrMUnmarshallCCComputeResponse(suite, kv_1, commit1, collective_challenge) response_2 := SchnorrMUnmarshallCCComputeResponse(suite, kv_2, commit2, collective_challenge) response_3 := SchnorrMUnmarshallCCComputeResponse(suite, kv_3, commit3, collective_challenge) response_4 := SchnorrMUnmarshallCCComputeResponse(suite, kv_4, commit4, collective_challenge) response_5 := SchnorrMUnmarshallCCComputeResponse(suite, kv_5, commit5, collective_challenge) // finally, we compute a signature given the responses. responsearr := []SchnorrMResponse{response_1, response_2, response_3, response_4, response_5} sig := SchnorrMComputeSignatureFromResponses(suite, collective_challenge, responsearr) // After all that, we should be able to validate the signature // against the group public key. First we serialize the signature buf := bytes.Buffer{} abstract.Write(&buf, &sig, suite) bsig := buf.Bytes() verified, err := SchnorrVerify(suite, sharedpubkey.GetSchnorrPK(), randomdata, bsig) if err != nil { t.Error("Error during Verification") } if verified == false { t.Error("Verification of signature failed.") } }
func (c *hashProver) Put(message interface{}) error { return abstract.Write(&c.msg, message, c.suite) }
// Sign creates an optionally anonymous, optionally linkable // signature on a given message. // // The caller supplies one or more public keys representing an anonymity set, // and the private key corresponding to one of those public keys. // The resulting signature proves to a verifier that the owner of // one of these public keys signed the message, // without revealing which key-holder signed the message, // offering anonymity among the members of this explicit anonymity set. // The other users whose keys are listed in the anonymity set need not consent // or even be aware that they have been included in an anonymity set: // anyone having a suitable public key may be "conscripted" into a set. // // If the provided anonymity set contains only one public key (the signer's), // then this function produces a traditional non-anonymous signature, // equivalent in both size and performance to a standard ElGamal signature. // // The caller may request either unlinkable or linkable anonymous signatures. // If linkScope is nil, this function generates an unlinkable signature, // which contains no information about which member signed the message. // The anonymity provided by unlinkable signatures is forward-secure, // in that a signature reveals nothing about which member generated it, // even if all members' private keys are later released. // For cryptographic background on unlinkable anonymity-set signatures - // also known as ring signatures or ad-hoc group signatures - // see Rivest, "How to Leak a Secret" at // http://people.csail.mit.edu/rivest/RivestShamirTauman-HowToLeakASecret.pdf. // // If the caller passes a non-nil linkScope, // the resulting anonymous signature will be linkable. // This means that given two signatures produced using the same linkScope, // a verifier will be able to tell whether // the same or different anonymity set members produced those signatures. // In particular, verifying a linkable signature yields a linkage tag. // This linkage tag has a 1-to-1 correspondence with the signer's public key // within a given linkScope, but is cryptographically unlinkable // to either the signer's public key or to linkage tags in other scopes. // The provided linkScope may be an arbitrary byte-string; // the only significance these scopes have is whether they are equal or unequal. // For details on the linkable signature algorithm this function implements, // see Liu/Wei/Wong, // "Linkable Spontaneous Anonymous Group Signature for Ad Hoc Groups" at // http://www.cs.cityu.edu.hk/~duncan/papers/04liuetal_lsag.pdf. // // Linkage tags may be used to protect against sock-puppetry or Sybil attacks // in situations where a verifier needs to know how many distinct members // of an anonymity set are present or signed messages in a given context. // It is cryptographically hard for one anonymity set member // to produce signatures with different linkage tags in the same scope. // An important and fundamental downside, however, is that // linkable signatures do NOT offer forward-secure anonymity. // If an anonymity set member's private key is later released, // it is trivial to check whether or not that member produced a given signature. // Also, anonymity set members who did NOT sign a message could // (voluntarily or under coercion) prove that they did not sign it, // e.g., simply by signing some other message in that linkage context // and noting that the resulting linkage tag comes out different. // Thus, linkable anonymous signatures are not appropriate to use // in situations where there may be significant risk // that members' private keys may later be compromised, // or that members may be persuaded or coerced into revealing whether or not // they produced a signature of interest. // func Sign(suite abstract.Suite, random cipher.Stream, message []byte, anonymitySet Set, linkScope []byte, mine int, privateKey abstract.Secret) []byte { // Note that Rivest's original ring construction directly supports // heterogeneous rings containing public keys of different types - // e.g., a mixture of RSA keys and DSA keys with varying parameters. // Our ring signature construction currently supports // only homogeneous rings containing compatible keys // drawn from the cipher suite (e.g., the same elliptic curve). // The upside to this constrint is greater flexibility: // e.g., we also easily obtain linkable ring signatures, // which are not readily feasible with the original ring construction. n := len(anonymitySet) // anonymity set size L := []abstract.Point(anonymitySet) // public keys in anonymity set pi := mine // If we want a linkable ring signature, produce correct linkage tag, // as a pseudorandom base point multiplied by our private key. // Liu's scheme specifies the linkScope as a hash of the ring; // this is one reasonable choice of linkage scope, // but there are others, so we parameterize this choice. var linkBase, linkTag abstract.Point if linkScope != nil { linkStream := suite.Cipher(linkScope) linkBase, _ = suite.Point().Pick(nil, linkStream) linkTag = suite.Point().Mul(linkBase, privateKey) } // First pre-hash the parameters to H1 // that are invariant for different ring positions, // so that we don't have to hash them many times. H1pre := signH1pre(suite, linkScope, linkTag, message) // Pick a random commit for my ring position u := suite.Secret().Pick(random) var UB, UL abstract.Point UB = suite.Point().Mul(nil, u) if linkScope != nil { UL = suite.Point().Mul(linkBase, u) } // Build the challenge ring s := make([]abstract.Secret, n) c := make([]abstract.Secret, n) c[(pi+1)%n] = signH1(suite, H1pre, UB, UL) var P, PG, PH abstract.Point P = suite.Point() PG = suite.Point() if linkScope != nil { PH = suite.Point() } for i := (pi + 1) % n; i != pi; i = (i + 1) % n { s[i] = suite.Secret().Pick(random) PG.Add(PG.Mul(nil, s[i]), P.Mul(L[i], c[i])) if linkScope != nil { PH.Add(PH.Mul(linkBase, s[i]), P.Mul(linkTag, c[i])) } c[(i+1)%n] = signH1(suite, H1pre, PG, PH) //fmt.Printf("s%d %s\n",i,s[i].String()) //fmt.Printf("c%d %s\n",(i+1)%n,c[(i+1)%n].String()) } s[pi] = suite.Secret() s[pi].Mul(privateKey, c[pi]).Sub(u, s[pi]) // s_pi = u - x_pi c_pi // Encode and return the signature buf := bytes.Buffer{} if linkScope != nil { // linkable ring signature sig := lSig{uSig{c[0], s}, linkTag} abstract.Write(&buf, &sig, suite) } else { // unlinkable ring signature sig := uSig{c[0], s} abstract.Write(&buf, &sig, suite) } return buf.Bytes() }
func (dp *deniableProver) Put(message interface{}) error { // Add onto accumulated prover message return abstract.Write(dp.msg, message, dp.suite) }
func FromSecretToByte(s abstract.Secret, params P256Params) []byte { b := bytes.Buffer{} abstract.Write(&b, s, params.Suite) return b.Bytes() }
/* This function implements the signer protocol from the blind signature paper and can be bound via closure given a specific set of parameters and send to the serve() function This is not the best accept() handler ever written, but it's better than the client side code */ func signBlindlySchnorr(conn net.Conn, suite abstract.Suite, kv crypto.SchnorrKeyset, sharedinfo []byte) { defer conn.Close() fmt.Println("SERVER", "Sending initial parameters") signerParams, err := crypto.NewPrivateParams(suite, sharedinfo) if err != nil { fmt.Println("SERVER", "Error creating new private parameters", err.Error()) return } // "send" these to the user. userPublicParams := signerParams.DerivePubParams() buffer := bytes.Buffer{} abstract.Write(&buffer, &userPublicParams, suite) conn.Write(buffer.Bytes()) // now we need to wait for the client to send us "e" ch := make(chan []byte) errorCh := make(chan error) // this neat little routine for wrapping read connections // in a class unashamedly stolen from stackoverflow: // http://stackoverflow.com/a/9764191 go func(ch chan []byte, eCh chan error) { for { // try to read the data fmt.Println("SERVER", "Read goroutine off and going") buffer := make([]byte, 1026) _, err := conn.Read(buffer) if err != nil { // send an error if it's encountered errorCh <- err return } // send data if we read some. ch <- buffer } }(ch, errorCh) for { select { case data := <-ch: fmt.Println("SERVER", "Received Message") var challenge crypto.WISchnorrChallengeMessage buffer := bytes.NewBuffer(data) err = abstract.Read(buffer, &challenge, suite) if err != nil { fmt.Println("SERVER", "Error", err.Error()) return } response := crypto.ServerGenerateResponse(suite, challenge, signerParams, kv) respbuffer := bytes.Buffer{} abstract.Write(&respbuffer, &response, suite) conn.Write(respbuffer.Bytes()) fmt.Println("SERVER", "We're done") return case err := <-errorCh: if err == io.EOF { return } // we should, really, log instead. fmt.Println("Encountered error serving client") fmt.Println(err.Error()) break } } }
func runClientProtocol(configFilePath string) (bool, error) { // first stage, let's retrieve everything from // the configuration file that the client needs var config SchnorrMGroupConfig suite := ed25519.NewAES128SHA256Ed25519(true) fcontents, err := ioutil.ReadFile(configFilePath) if err != nil { fmt.Println("Error reading file") fmt.Println(err.Error()) os.Exit(1) } err = json.Unmarshal(fcontents, &config) if err != nil { fmt.Println("Error unmarshalling") fmt.Println(err.Error()) os.Exit(1) } // and now, for our next trick, a random 1KB blob randomdata := make([]byte, 1024) _, err = rand.Read(randomdata) if err != nil { fmt.Println(err.Error()) return false, err } reportChan := make(chan controllerMessage) var syncChans []chan []byte for i, _ := range config.Members { syncChan := make(chan []byte) syncChans = append(syncChans, syncChan) fmt.Println("CLIENT", "C", "Launching goroutine worker") go serverComms(config, i, randomdata, reportChan, syncChan) } var respCount int = 0 commitmentArray := make([]crypto.SchnorrMPublicCommitment, len(config.Members), len(config.Members)) fmt.Println("CLIENT", "C", "Controller getting ready to receive") for { select { case msg := <-reportChan: // we should probably check all our client threads have responded // once and only once, but we won't buf := bytes.NewBuffer(msg.Message) commitment := crypto.SchnorrMPublicCommitment{} err := abstract.Read(buf, &commitment, suite) if err != nil { fmt.Println("CLIENT", "Read Error") fmt.Println(err.Error()) return false, err } // we have our abstract point. // let's go fmt.Println("CLIENT", "C", "Controller got message index", msg.MemberIndex) commitmentArray[msg.MemberIndex] = commitment respCount = respCount + 1 default: } if respCount == len(config.Members) { // reset and break respCount = 0 break } } fmt.Println("CLIENT", "C", "Controller received all responses, preparing to aggregate") // sum the points aggregateCommmitment := crypto.SchnorrMComputeAggregateCommitment(suite, commitmentArray) collectiveChallenge := crypto.SchnorrMComputeCollectiveChallenge(suite, randomdata, aggregateCommmitment) bAggregateCommmitment := bytes.Buffer{} abstract.Write(&bAggregateCommmitment, &aggregateCommmitment, suite) // report for _, ch := range syncChans { fmt.Println("CLIENT", "C", "Sending aggcommitbytes back to workers") ch <- bAggregateCommmitment.Bytes() } // now wait for the server responses, aggregate them and compute // a signature from the combined servers. fmt.Println("CLIENT", "C", "Controller getting ready to receive") responseArray := make([]crypto.SchnorrMResponse, len(config.Members), len(config.Members)) for { select { case msg := <-reportChan: // we should probably check all our client threads have responded // once and only once, but we won't buf := bytes.NewBuffer(msg.Message) response := crypto.SchnorrMResponse{} err := abstract.Read(buf, &response, suite) if err != nil { return false, err } fmt.Println("CLIENT", "C", "Received from", msg.MemberIndex) // we have our abstract point. // let's go responseArray[msg.MemberIndex] = response respCount = respCount + 1 fmt.Println("CLIENT", "C", "Received responses", respCount) default: } if respCount == len(config.Members) { break } } sig := crypto.SchnorrMComputeSignatureFromResponses(suite, collectiveChallenge, responseArray) fmt.Println("Signature created, is") fmt.Println(sig) return true, nil }
func signOneKBMSchnorr(conn net.Conn, suite abstract.Suite, kv crypto.SchnorrKeyset) { defer conn.Close() fmt.Println(suite) ch := make(chan []byte) errorCh := make(chan error) // this neat little routine for wrapping read connections // in a class unashamedly stolen from stackoverflow: // http://stackoverflow.com/a/9764191 go func(ch chan []byte, eCh chan error) { for { // try to read the data fmt.Println("SERVER", "Read goroutine off and going") buffer := make([]byte, 1026) _, err := conn.Read(buffer) if err != nil { // send an error if it's encountered errorCh <- err return } // send data if we read some. ch <- buffer } }(ch, errorCh) var internalState byte = INIT var message []byte var aggregateCommitment crypto.SchnorrMAggregateCommmitment var privateCommit crypto.SchnorrMPrivateCommitment for { select { case data := <-ch: // validate state transition - we can only // transfer to the next state in the protocol // anything else and we simply ignore the message // eventually we time out and close the connection newState := data[0] fmt.Println("SERVER", "Selected data channel, states are", newState, internalState) if newState != (internalState + 1) { continue } internalState = newState payload := data[2:] switch newState { case MESSAGE: fmt.Println("SERVER", "Received Message") message = payload privateCommitment, err := crypto.SchnorrMGenerateCommitment(suite) if err != nil { fmt.Println("Error generating commitment") fmt.Println(err.Error()) break } privateCommit = privateCommitment publicCommitment := privateCommitment.PublicCommitment() buf := bytes.Buffer{} abstract.Write(&buf, &publicCommitment, suite) conn.Write(buf.Bytes()) case COMMITMENT: fmt.Println("SERVER", "Received Commitment") buf := bytes.NewBuffer(payload) err := abstract.Read(buf, &aggregateCommitment, suite) if err != nil { fmt.Println("Error binary decode of aggregateCommitment") fmt.Println(err.Error()) break } collectiveChallenge := crypto.SchnorrMComputeCollectiveChallenge(suite, message, aggregateCommitment) response := crypto.SchnorrMUnmarshallCCComputeResponse(suite, kv, privateCommit, collectiveChallenge) outBuf := bytes.Buffer{} abstract.Write(&outBuf, &response, suite) conn.Write(outBuf.Bytes()) // we're now at the end, we can break and close connection break default: fmt.Println("Didn't understand message, received:") fmt.Println(data) } case err := <-errorCh: if err == io.EOF { return } // we should, really, log instead. fmt.Println("Encountered error serving client") fmt.Println(err.Error()) break // well, the *idea* was to have this but frustratingly // it does not compile. Oh well. //case time.Tick(time.Minute): // more robust handling of connections. // don't allow clients to hold the server open // indefinitely. //break } } }
/* Runs through the "user" side of the protocol i.e. the party requesting a partially blind signature */ func main() { kingpin.MustParse(app.Parse(os.Args[1:])) var kfilepath string = *appPrivatekeyfile var kinfopath string = *appInfo var hostspec string = *appHostspec suite := ed25519.NewAES128SHA256Ed25519(true) fmt.Println("CLIENT", "Connecting to", hostspec) pubKey, err := crypto.SchnorrLoadPubkey(kfilepath, suite) if err != nil { fmt.Println("CLIENT", "Error loading public key"+err.Error()) return } info, err := LoadInfo(kinfopath) if err != nil { fmt.Println("CLIENT", "Error loading info"+err.Error()) return } message := make([]byte, 1024) _, err = rand.Read(message) if err != nil { fmt.Println(err.Error()) return } conn, err := net.Dial("tcp", hostspec) if err != nil { fmt.Println("CLIENT", "Error connecting to server", err.Error()) return } defer conn.Close() // first up, let's receive the signer's parameter set buffer := make([]byte, 1026) _, err = conn.Read(buffer) if err != nil { fmt.Println("CLIENT", "Error reading from server", err.Error()) return } var userPublicParams crypto.WISchnorrPublicParams decodeBuffer := bytes.NewBuffer(buffer) err = abstract.Read(decodeBuffer, &userPublicParams, suite) // now we've got that, complete the challenge phase (i.e. let's generate E) challenge, userPrivateParams, err := crypto.ClientGenerateChallenge(suite, userPublicParams, pubKey, info, message) if err != nil { fmt.Println("CLIENT", "Error generating challenge", err.Error()) return } // encode and send to server. challengebuffer := bytes.Buffer{} abstract.Write(&challengebuffer, &challenge, suite) conn.Write(challengebuffer.Bytes()) // and now we wait for the server to respond to this: secondread := make([]byte, 1024) _, err = conn.Read(secondread) if err != nil { fmt.Println("CLIENT", "Error reading from server", err.Error()) return } var responseMessage crypto.WISchnorrResponseMessage decodeBuffer = bytes.NewBuffer(secondread) err = abstract.Read(decodeBuffer, &responseMessage, suite) if err != nil { fmt.Println("CLIENT", "Error reading response", err.Error()) return } // we've got the response message, time to sign and check. // finally, we can sign the message and check it verifies. sig, worked := crypto.ClientSignBlindly(suite, userPrivateParams, responseMessage, pubKey, message) //fmt.Println(blindSignature) if worked != true { fmt.Println("CLIENT", "Error preforming blind signature") return } // now verify this worked fine. result, err := crypto.VerifyBlindSignature(suite, pubKey, sig, info, message) if err != nil { fmt.Println("CLIENT", "Error handling signature verification", err.Error()) return } if result != true { fmt.Println("CLIENT", "Signature did not correctly verify.") return } fmt.Println("CLIENT", "Signature OK -", sig) return }
// Encodes the message for sending. func (msg *RequestInsuranceMessage) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} abstract.Write(&b, msg, INSURE_GROUP) return b.Bytes(), nil // return protobuf.Encode(msg); }