// Verify checks a signature generated by Sign. // // The caller provides the message, anonymity set, and linkage scope // with which the signature was purportedly produced. // If the signature is a valid linkable signature (linkScope != nil), // this function returns a linkage tag that uniquely corresponds // to the signer within the given linkScope. // If the signature is a valid unlinkable signature (linkScope == nil), // returns an empty but non-nil byte-slice instead of a linkage tag on success. // Returns a nil linkage tag and an error if the signature is invalid. func Verify(suite abstract.Suite, message []byte, anonymitySet Set, linkScope []byte, signatureBuffer []byte) ([]byte, error) { n := len(anonymitySet) // anonymity set size L := []abstract.Point(anonymitySet) // public keys in ring // Decode the signature buf := bytes.NewBuffer(signatureBuffer) var linkBase, linkTag abstract.Point sig := lSig{} sig.S = make([]abstract.Secret, n) if linkScope != nil { // linkable ring signature if err := abstract.Read(buf, &sig, suite); err != nil { return nil, err } linkStream := suite.Cipher(linkScope) linkBase, _ = suite.Point().Pick(nil, linkStream) linkTag = sig.Tag } else { // unlinkable ring signature if err := abstract.Read(buf, &sig.uSig, suite); err != nil { return nil, err } } // Pre-hash the ring-position-invariant parameters to H1. H1pre := signH1pre(suite, linkScope, linkTag, message) // Verify the signature var P, PG, PH abstract.Point P = suite.Point() PG = suite.Point() if linkScope != nil { PH = suite.Point() } s := sig.S ci := sig.C0 for i := 0; i < n; i++ { PG.Add(PG.Mul(nil, s[i]), P.Mul(L[i], ci)) if linkScope != nil { PH.Add(PH.Mul(linkBase, s[i]), P.Mul(linkTag, ci)) } ci = signH1(suite, H1pre, PG, PH) } if !ci.Equal(sig.C0) { return nil, errors.New("invalid signature") } // Return the re-encoded linkage tag, for uniqueness checking if linkScope != nil { tag, _ := linkTag.MarshalBinary() return tag, nil } else { return []byte{}, nil } }
// Retrieve a public/private keypair for a given KeyInfo configuration record. func (f *File) Key(key *KeyInfo, suites map[string]abstract.Suite) (KeyPair, error) { // XXX support passphrase-encrypted or system-keychain keys // Lookup the appropriate ciphersuite for this public key. suite := suites[key.Suite] if suite == nil { return KeyPair{}, errors.New("Unsupported ciphersuite '" + key.Suite + "'") } // Read the private key file secname := f.dirName + "/sec-" + key.PubId secf, err := os.Open(secname) if err != nil { return KeyPair{}, err } defer secf.Close() p := KeyPair{} p.Suite = suite if err := abstract.Read(secf, &p.Secret, suite); err != nil { return KeyPair{}, err } // Reconstruct and verify the public key p.Public = suite.Point().Mul(nil, p.Secret) if p.PubId() != key.PubId { return KeyPair{}, errors.New("Secret does not yield public key " + key.PubId) } return p, nil }
// 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 }
func FromByteToSecret(b []byte, params P256Params) abstract.Secret { secret := params.Suite.Secret() //err := secret.UnmarshalBinary(b) //CheckErr(err,"[-] Error while unmarshaling secret") abstract.Read(bytes.NewBuffer(b), secret, params.Suite) return secret }
func ElGamalVerify(suite abstract.Suite, message []byte, publicKey abstract.Point, signatureBuffer []byte, g abstract.Point) error { // Decode the signature buf := bytes.NewBuffer(signatureBuffer) sig := basicSig{} if err := abstract.Read(buf, &sig, suite); err != nil { return err } r := sig.R c := sig.C // Compute base**(r + x*c) == T var P, T abstract.Point P = suite.Point() T = suite.Point() T.Add(T.Mul(g, r), P.Mul(publicKey, c)) // Verify that the hash based on the message and T // matches the challange c from the signature c = hashElGamal(suite, message, T) if !c.Equal(sig.C) { return errors.New("invalid signature") } return nil }
func (snLog *SNLog) UnmarshalBinary(data []byte) error { // abstract.Read used to decode/ unmarshal crypto types b := bytes.NewBuffer(data) err := abstract.Read(b, snLog, snLog.Suite) // gob is used to decode non-crypto types rem, _ := snLog.MarshalBinary() snLog.CMTRoots = data[len(rem):] return err }
func FromByteToPoint(b []byte, params P256Params) abstract.Point { point := params.Suite.Point() //err := point.UnmarshalBinary(b) //CheckErr(err,"[-] Error while unmarshling a point") err := abstract.Read(bytes.NewBuffer(b), point, params.Suite) CheckErr(err, "Error in FromByteToPoint ...") return point }
// Prover will call this after Put()ing all commits for a given step, // to get the master challenge to be used in its challenge/responses. func (dp *deniableProver) PubRand(data ...interface{}) error { if _, err := dp.proofStep(); err != nil { // finish proof step return err } if err := dp.challengeStep(); err != nil { // run challenge step return err } return abstract.Read(dp.pubrand, data, dp.suite) }
func decodeFromB64(buf []byte) abstract.Point { suite := ed25519.NewAES128SHA256Ed25519(true) str := string(buf) decodedBytes, _ := hex.DecodeString(str) P := suite.Point() decoded := bytes.NewBuffer(decodedBytes) _ = abstract.Read(decoded, &P, suite) return P }
// Loads only the public key from disk. func SchnorrLoadPubkey(path string, suite abstract.Suite) (SchnorrPublicKey, error) { fcontents, err := ioutil.ReadFile(path) if err != nil { return SchnorrPublicKey{}, err } buf := bytes.NewBuffer(fcontents) kv := SchnorrPublicKey{} err2 := abstract.Read(buf, &kv, suite) return kv, err2 }
// Decodes a message received. // NOTE: In order to be encoded properly, public polynomials need to be // initialized with the right group and minimum number of shares. func (msg *RequestInsuranceMessage) UnmarshalBinary(data []byte) (*RequestInsuranceMessage, error) { msg.PubCommit = new(poly.PubPoly) msg.PubCommit.Init(INSURE_GROUP, TSHARES, nil) msg.PubKey = KEY_SUITE.Point() msg.Share = INSURE_GROUP.Secret().Pick(random.Stream) msg.ShareNumber = nist.NewInt(int64(0), big.NewInt(int64(math.MaxInt64))) b := bytes.NewBuffer(data) err := abstract.Read(b, msg, INSURE_GROUP) if err != nil { panic(err) } return msg, err // return msg, protobuf.Decode(data, msg) }
// Get the next public random challenge. func (dv *deniableVerifier) PubRand(data ...interface{}) error { // Signal that we need the next challenge dv.done <- false // Wait for it chal := <-dv.inbox // Produce the appropriate publicly random stream dv.pubrand = dv.suite.Cipher(chal) if err := abstract.Read(dv.pubrand, data, dv.suite); err != nil { return err } // Get the next proof message dv.getProof() return nil }
/* 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 }
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 }
// Get private randomness func (c *hashProver) PriRand(data ...interface{}) { if err := abstract.Read(c.prirand, data, c.suite); err != nil { panic("error reading random stream: " + err.Error()) } }
// Get public randomness that depends on every bit in the proof so far. func (c *hashVerifier) PubRand(data ...interface{}) error { c.consumeMsg() // Stir in newly-read data return abstract.Read(c.pubrand, data, c.suite) }
// Read structured data from the proof func (c *hashVerifier) Get(message interface{}) error { return abstract.Read(&c.proof, message, c.suite) }
// Get private randomness func (dp *deniableProver) PriRand(data ...interface{}) { if err := abstract.Read(dp.prirand, data, dp.suite); err != nil { panic("error reading random stream: " + err.Error()) } }
// Read structured data from the proof func (dv *deniableVerifier) Get(message interface{}) error { return abstract.Read(dv.prbuf, message, dv.suite) }
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 } } }
/* 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 } } }
// Get public randomness that depends on every bit in the proof so far. func (c *hashProver) PubRand(data ...interface{}) error { c.consumeMsg() return abstract.Read(c.pubrand, data, c.suite) }