func TestSmallConfigHealthyEd25519(t *testing.T) { suite := ed25519.NewAES128SHA256Ed25519(true) RoundsPerView := 100 if err := runTreeSmallConfig(sign.MerkleTree, RoundsPerView, suite, 0); err != nil { t.Fatal(err) } }
/* runs through the process of setting up the server as specified in the args */ func main() { kingpin.MustParse(app.Parse(os.Args[1:])) var port int = *appPort var kfilepath string = *appPrivatekeyfile var kinfopath string = *appInfo fmt.Printf("Sigserv3 - listening on port %d.\n", port) suite := ed25519.NewAES128SHA256Ed25519(true) kv, err := crypto.SchnorrLoadKeypair(kfilepath, suite) if err != nil { fmt.Println("Error " + err.Error()) return } info, err := LoadInfo(kinfopath) if err != nil { fmt.Println("Error " + err.Error()) return } // I don't know if there's a way to // do std::bind-like behaviour in GO. // for C++ what I'd do is pretty simple: // newfunc := std::bind(&func, args to bind) var signBlindImpl connectionhandler = func(conn net.Conn) { signBlindlySchnorr(conn, suite, kv, info) } serve(port, signBlindImpl) }
/* Create a group configuration file. This is really a convenience feature more than anything, making it easier to direct the client than supplying all the arguments on the command line. */ func runMultiSignatureGen(group []SchnorrMSHostSpec, outputFile string) error { var config SchnorrMGroupConfig var pkeys []crypto.SchnorrPublicKey suite := ed25519.NewAES128SHA256Ed25519(true) for _, mshp := range group { pkey, err := crypto.SchnorrLoadPubkey(mshp.KeyFilePath, suite) if err != nil { fmt.Println(err.Error()) os.Exit(1) } pkeys = append(pkeys, pkey) member := SchnorrMMember{mshp.HostName, mshp.Port, pkey} config.Members = append(config.Members, member) } jointKey := crypto.SchnorrMComputeSharedPublicKey(suite, pkeys) config.JointKey = jointKey.GetSchnorrPK() data, _ := json.Marshal(config) f, err := os.OpenFile(outputFile, os.O_CREATE|os.O_RDWR, 0644) if err != nil { return err } defer f.Close() _, err = f.Write(data) return err }
func main() { var port int var kfilepath string flag.IntVar(&port, "port", 1111, "Listen on given port") flag.StringVar(&kfilepath, "keyfile", "", "Use the keyfile specified") flag.Parse() fmt.Printf("Sigserv1 - listening on port %d.\n", port) suite := ed25519.NewAES128SHA256Ed25519(true) kv, err := crypto.SchnorrLoadKeypair(kfilepath, suite) if err != nil { fmt.Println("Error " + err.Error()) return } // I don't know if there's a way to // do std::bind-like behaviour in GO. // for C++ what I'd do is pretty simple: // newfunc := std::bind(&func, args to bind) var signOneKBImpl connectionhandler = func(conn net.Conn) { signOneKBMSchnorr(conn, suite, kv) } serve(port, signOneKBImpl) }
// Helper function to create some stuff for testing func initialize() (abstract.Suite, *PriKey, *PubKey, abstract.Point) { suite := ed25519.NewAES128SHA256Ed25519(true) sk, pk := GenerateKeyPair(suite) el, _ := suite.Point().Pick(nil, suite.Cipher(nil)) return suite, sk, pk, el }
// Returns a map of all suites func All() Suites { s := make(Suites) s.add(nist.NewAES128SHA256P256()) s.add(nist.NewAES128SHA256QR512()) s.add(edwards.NewAES128SHA256Ed25519(false)) s.add(ed25519.NewAES128SHA256Ed25519(false)) return s }
func main() { var port int var hostname string var kfilepath string flag.StringVar(&kfilepath, "keyfile", "", "Use the keyfile specified") flag.StringVar(&hostname, "host", "localhost", "Connect to the specified host") flag.IntVar(&port, "port", 1111, "Use the specified port") flag.Parse() suite := ed25519.NewAES128SHA256Ed25519(true) pk, err := crypto.SchnorrLoadPubkey(kfilepath, suite) if err != nil { fmt.Println("Error " + err.Error()) return } fmt.Println(pk.Y) var hostspec string hostspec = fmt.Sprintf("%s:%d", hostname, port) fmt.Println("Connecting to %s\n", hostspec) conn, err := net.Dial("tcp", hostspec) if err != nil { fmt.Println(err.Error()) return } randomdata := make([]byte, 1024) _, err = rand.Read(randomdata) if err != nil { fmt.Println(err.Error()) return } buffer := make([]byte, 64) conn.Write(randomdata) _, err = conn.Read(buffer) if err != nil { fmt.Println(err.Error()) return } v, err := crypto.SchnorrVerify(suite, pk, randomdata, buffer) if err != nil { fmt.Println(err.Error()) return } if v == true { fmt.Println("Signature verified OK") } else { fmt.Println("Signature verify FAILED") } return }
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 }
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()) }
func TestSchnorrGenerateKeyset(t *testing.T) { // again, if I had more time and was publishing // this, I'd be calculating some known values // outside this code // and checking generation produced what it // should. suite := ed25519.NewAES128SHA256Ed25519(true) _, err := SchnorrGenerateKeypair(suite) if err != nil { t.Error("Keypair generation failed") } }
func TestLoadSaveKeys(t *testing.T) { suite := ed25519.NewAES128SHA256Ed25519(true) keypair, err := SchnorrGenerateKeypair(suite) if err != nil { t.Error("Keypair generation failed") } pk := SchnorrExtractPubkey(keypair) err = SchnorrSaveKeypair("/tmp/gotests.pri", suite, keypair) if err != nil { t.Error("Failed to write file") } err = SchnorrSavePubkey("/tmp/gotests.pub", suite, pk) if err != nil { t.Error("Failed to write file") } keypair_loaded, err := SchnorrLoadKeypair("/tmp/gotests.pri", suite) if err != nil { t.Error("Failed to load keypair") } pk_loaded, err := SchnorrLoadPubkey("/tmp/gotests.pub", suite) message := []byte("This is a test") wrongmessage := []byte("Clearly this shouldn't work") sig, err := SchnorrSign(suite, keypair_loaded, message) if err != nil { t.Error("Signature Generation failed") } v1, e1 := SchnorrVerify(suite, pk_loaded, message, sig) if e1 != nil { t.Error("Error during Verification") } if v1 == false { t.Error("Verification of signature failed") } v2, e2 := SchnorrVerify(suite, pk_loaded, wrongmessage, sig) if e2 != nil { t.Error("Error during Verification") } if v2 == true { t.Error("Verification of signature succeeded for bad message") } }
func GetSuite(suite string) abstract.Suite { var s abstract.Suite switch { case suite == "nist256": s = nist.NewAES128SHA256P256() case suite == "nist512": s = nist.NewAES128SHA256QR512() case suite == "ed25519": s = ed25519.NewAES128SHA256Ed25519(true) default: s = nist.NewAES128SHA256P256() } return s }
func TestSchnorrSignature(t *testing.T) { suite := ed25519.NewAES128SHA256Ed25519(true) // for good measure, do a few. // in proper code we'd not just rely // on random generation, we'd also have // some known test vectors. for i := 0; i < 100; i++ { kv, err := SchnorrGenerateKeypair(suite) if err != nil { t.Error("Keypair generation failed") } pk := SchnorrExtractPubkey(kv) message := []byte("This is a test") wrongmessage := []byte("Clearly this shouldn't work") sig, err := SchnorrSign(suite, kv, message) if err != nil { t.Error("Signature Generation failed") } v1, e1 := SchnorrVerify(suite, pk, message, sig) if e1 != nil { t.Error("Error during Verification") } if v1 == false { t.Error("Verification of signature failed") } v2, e2 := SchnorrVerify(suite, pk, wrongmessage, sig) if e2 != nil { t.Error("Error during Verification") } if v2 == true { t.Error("Verification of signature succeeded for bad message") } } }
func TestShuffle(T *testing.T) { amount := 6 servers := 3 suite := ed25519.NewAES128SHA256Ed25519(true) sks, pks := make([]*elgamal.PriKey, servers), make([]*elgamal.PubKey, servers) // Generate keys for the shuffle servers for i := 0; i < servers; i++ { sks[i], pks[i] = elgamal.GenerateKeyPair(suite) } // Generate random plaintexts, encrypt them all to the sum of all server public keys sumpks := elgamal.SumKeys(pks) points, ciphers := make([]abstract.Point, amount), make([]*elgamal.CipherText, amount) for i := 0; i < amount; i++ { points[i], _ = suite.Point().Pick(nil, suite.Cipher(nil)) ciphers[i] = sumpks.Encrypt(points[i]) } var shuffle *VerifiableShuffle var err error for i := 0; i < servers; i++ { shuffle, err = ShuffleDecrypt(suite, ciphers, pks, sks[i], "nonce", i) if err != nil { T.Fatalf("Failed to create proof: %v", err) } if err = shuffle.Verify(ciphers, pks, "nonce", i); err != nil { T.Fatal("Shuffle verification failed: ", err) } // These are the ones that should be shuffled by the next server ciphers = shuffle.Decrypted } for i := 0; i < amount; i++ { T.Log(str(points[i]), str(shuffle.Decrypted[i].C2)) } }
func TestPartialBlindSignatureScheme(t *testing.T) { // I tried suite := ed25519.NewAES128SHA256Ed25519(true) but got null pointer derefs suite := ed25519.NewAES128SHA256Ed25519(true) privKey, _ := SchnorrGenerateKeypair(suite) pubKey := SchnorrExtractPubkey(privKey) // now "agree" some information. For our purposes just fish // some bytes out of /dev/urandom info := make([]byte, 16) _, err := rand.Read(info) if err != nil { t.Error(err.Error()) } badinfo := make([]byte, 16) _, err = rand.Read(info) if err != nil { t.Error(err.Error()) } // likewise let's sign a random message. message := make([]byte, 16) _, err = rand.Read(message) if err != nil { t.Error(err.Error()) } // now the first step from pg277 signerParams, err := NewPrivateParams(suite, info) if err != nil { t.Error(err.Error()) } // "send" these to the user. userPublicParams := signerParams.DerivePubParams() // now the user does their thing. challenge, userPrivateParams, err := ClientGenerateChallenge(suite, userPublicParams, pubKey, info, message) if err != nil { t.Error(err.Error()) } // and now we compute a response on the server side. response := ServerGenerateResponse(suite, challenge, signerParams, privKey) // finally, we can sign the message and check it verifies. sig, worked := ClientSignBlindly(suite, userPrivateParams, response, pubKey, message) //fmt.Println(blindSignature) if worked != true { t.Error("Signature scheme did not return true.") } // now verify this worked fine. result, err := VerifyBlindSignature(suite, pubKey, sig, info, message) if err != nil { t.Error(err.Error()) } if result != true { t.Error("VerifyBlindSignature failed with valid info - this should work.") } // and now try again with the wrong information to prove // that any change in this information fails to generate the correct // signature. result, err = VerifyBlindSignature(suite, pubKey, sig, badinfo, message) if err != nil { t.Error(err.Error()) } if result != false { t.Error("VerifyBlindSignature succeeded with bad info - this should fail.") } }
/* Does excactly what it sounds like - creates and saves a schnorr public/private keypair. Much like ssh-keygen, we append .pub to the public key. Unlike ssh-keygen we append .pri to the private key also. */ func runKeyGen(kpath string) { suite := ed25519.NewAES128SHA256Ed25519(true) KeyGen(suite, kpath) }
/* 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 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 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 }
package main import ( "os" "github.com/codegangsta/cli" "github.com/dedis/cothority/lib/cliutils" "github.com/dedis/cothority/lib/conode" "github.com/dedis/cothority/lib/dbg" "github.com/dedis/crypto/abstract" "github.com/dedis/crypto/edwards/ed25519" ) // Which suite to use var suite abstract.Suite = ed25519.NewAES128SHA256Ed25519(false) var suiteStr string = suite.String() // where to write the key file .priv + .pub var defaultKeyFile string = "key" // Returns the name of the file for the private key func namePriv(key string) string { return key + ".priv" } // Returns the name of the file for the public key func namePub(key string) string { return key + ".pub" } // config file by default
package crypto import ( "github.com/dedis/crypto/abstract" "github.com/dedis/crypto/edwards/ed25519" "github.com/dedis/crypto/random" ) // The default suite for use in all elliptic curve-crypto var Suite = ed25519.NewAES128SHA256Ed25519(true) // The second generator hat-g in the Verdict hash-based construction var Generator = Hash([]byte("The second generator hat-g in the Verdict hash-based construction")) var hash = Suite.Hash() // Hash data onto a curve by first computing the SHA256 hash of the data, and then deterministically embedding // the result onto the curve using abstract.Point().Pick and a cipher initialized with a constant key. func Hash(data []byte) abstract.Point { hash.Reset() hash.Write(data) h := hash.Sum(nil) // Initialize the cipher always with this same key, so that it always returns the same when called with // the same arguments cipher := Suite.Cipher([]byte{42}) // The Pick method uses at most 29 bytes of its first argument, generating an extra byte using the cipher, so // three of the bytes of the SHA256 is thrown away. This is unavoidable. p, _ := Suite.Point().Pick(h, cipher) return p }