aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/tangerine-network/mcl/sample/vote.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/tangerine-network/mcl/sample/vote.cpp')
-rw-r--r--vendor/github.com/tangerine-network/mcl/sample/vote.cpp206
1 files changed, 206 insertions, 0 deletions
diff --git a/vendor/github.com/tangerine-network/mcl/sample/vote.cpp b/vendor/github.com/tangerine-network/mcl/sample/vote.cpp
new file mode 100644
index 000000000..88137187c
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/sample/vote.cpp
@@ -0,0 +1,206 @@
+/*
+ vote sample tool
+ Copyright (c) 2014, National Institute of Advanced Industrial
+ Science and Technology All rights reserved.
+ This source file is subject to BSD 3-Clause license.
+
+ modifyed for mcl by herumi
+*/
+#include <iostream>
+#include <fstream>
+#include <cybozu/random_generator.hpp>
+#include <cybozu/option.hpp>
+#include <cybozu/itoa.hpp>
+#include <mcl/fp.hpp>
+#include <mcl/ec.hpp>
+#include <mcl/elgamal.hpp>
+#include <mcl/ecparam.hpp>
+
+typedef mcl::FpT<> Fp;
+typedef mcl::FpT<mcl::ZnTag> Zn; // use ZnTag because Zn is different class with Fp
+typedef mcl::EcT<Fp> Ec;
+typedef mcl::ElgamalT<Ec, Zn> Elgamal;
+
+cybozu::RandomGenerator rg;
+
+const std::string pubFile = "vote_pub.txt";
+const std::string prvFile = "vote_prv.txt";
+const std::string resultFile = "vote_ret.txt";
+
+std::string GetSheetName(size_t n)
+{
+ return std::string("vote_") + cybozu::itoa(n) + ".txt";
+}
+
+struct Param {
+ std::string mode;
+ std::string voteList;
+ Param(int argc, const char *const argv[])
+ {
+ cybozu::Option opt;
+ opt.appendOpt(&voteList, "11001100", "l", ": list of voters for vote mode(eg. 11001100)");
+ opt.appendHelp("h", ": put this message");
+ opt.appendParam(&mode, "mode", ": init/vote/count/open");
+ if (!opt.parse(argc, argv)) {
+ opt.usage();
+ exit(1);
+ }
+ printf("mode=%s\n", mode.c_str());
+ if (mode == "vote") {
+ printf("voters=%s\n", voteList.c_str());
+ size_t pos = voteList.find_first_not_of("01");
+ if (pos != std::string::npos) {
+ printf("bad char %c\n", voteList[pos]);
+ exit(1);
+ }
+ }
+ }
+};
+
+void SysInit()
+{
+ const mcl::EcParam& para = mcl::ecparam::secp192k1;
+ Zn::init(para.n);
+ Fp::init(para.p);
+ Ec::init(para.a, para.b);
+}
+
+template<class T>
+bool Load(T& t, const std::string& name, bool doThrow = true)
+{
+ std::ifstream ifs(name.c_str(), std::ios::binary);
+ if (!ifs) {
+ if (doThrow) throw cybozu::Exception("Load:can't read") << name;
+ return false;
+ }
+ if (ifs >> t) return true;
+ if (doThrow) throw cybozu::Exception("Load:bad data") << name;
+ return false;
+}
+
+template<class T>
+void Save(const std::string& name, const T& t)
+{
+ std::ofstream ofs(name.c_str(), std::ios::binary);
+ ofs << t;
+}
+
+void Init()
+{
+ const mcl::EcParam& para = mcl::ecparam::secp192k1;
+ const Fp x0(para.gx);
+ const Fp y0(para.gy);
+ const Ec P(x0, y0);
+ const size_t bitSize = para.bitSize;
+
+ Elgamal::PrivateKey prv;
+ prv.init(P, bitSize, rg);
+ const Elgamal::PublicKey& pub = prv.getPublicKey();
+ printf("make privateKey=%s, publicKey=%s\n", prvFile.c_str(), pubFile.c_str());
+ Save(prvFile, prv);
+ Save(pubFile, pub);
+}
+
+struct CipherWithZkp {
+ Elgamal::CipherText c;
+ Elgamal::Zkp zkp;
+ bool verify(const Elgamal::PublicKey& pub) const
+ {
+ return pub.verify(c, zkp);
+ }
+};
+
+inline std::ostream& operator<<(std::ostream& os, const CipherWithZkp& self)
+{
+ return os << self.c << std::endl << self.zkp;
+}
+inline std::istream& operator>>(std::istream& is, CipherWithZkp& self)
+{
+ return is >> self.c >> self.zkp;
+}
+
+void Vote(const std::string& voteList)
+{
+ Elgamal::PublicKey pub;
+ Load(pub, pubFile);
+ puts("shuffle");
+ std::vector<size_t> idxTbl(voteList.size());
+ for (size_t i = 0; i < idxTbl.size(); i++) {
+ idxTbl[i] = i;
+ }
+ cybozu::shuffle(idxTbl, rg);
+ puts("each voter votes");
+ for (size_t i = 0; i < voteList.size(); i++) {
+ CipherWithZkp c;
+ pub.encWithZkp(c.c, c.zkp, voteList[i] - '0', rg);
+ const std::string sheetName = GetSheetName(idxTbl[i]);
+ printf("make %s\n", sheetName.c_str());
+ Save(sheetName, c);
+ }
+}
+
+void Count()
+{
+ Elgamal::PublicKey pub;
+ Load(pub, pubFile);
+ Elgamal::CipherText result;
+ puts("aggregate votes");
+ for (size_t i = 0; ; i++) {
+ const std::string sheetName = GetSheetName(i);
+ CipherWithZkp c;
+ if (!Load(c, sheetName, false)) break;
+ if (!c.verify(pub)) throw cybozu::Exception("bad cipher text") << i;
+ printf("add %s\n", sheetName.c_str());
+ result.add(c.c);
+ }
+ printf("create result file : %s\n", resultFile.c_str());
+ Save(resultFile, result);
+}
+
+void Open()
+{
+ Elgamal::PrivateKey prv;
+ Load(prv, prvFile);
+ Elgamal::CipherText c;
+ Load(c, resultFile);
+ Zn n;
+ prv.dec(n, c);
+ std::cout << "result of vote count " << n << std::endl;
+#if 0
+ puts("open real value");
+ for (size_t i = 0; ; i++) {
+ Elgamal::CipherText c;
+ const std::string sheetName = GetSheetName(i);
+ if (!Load(c, sheetName, false)) break;
+ Zn n;
+ prv.dec(n, c);
+ std::cout << sheetName << " " << n << std::endl;
+ }
+#endif
+}
+
+int main(int argc, char *argv[])
+ try
+{
+ const Param p(argc, argv);
+ SysInit();
+ if (p.mode == "init") {
+ Init();
+ } else
+ if (p.mode == "vote") {
+ Vote(p.voteList);
+ } else
+ if (p.mode == "count") {
+ Count();
+ } else
+ if (p.mode == "open") {
+ Open();
+ } else
+ {
+ printf("bad mode=%s\n", p.mode.c_str());
+ return 1;
+ }
+} catch (std::exception& e) {
+ printf("ERR %s\n", e.what());
+}
+