github.com/platonnetwork/platon-go@v0.7.6/cases/tool/win/bls_win/include/mcl/ecdsa.hpp (about)

     1  #pragma once
     2  /**
     3  	@file
     4  	@brief ECDSA
     5  	@author MITSUNARI Shigeo(@herumi)
     6  	@license modified new BSD license
     7  	http://opensource.org/licenses/BSD-3-Clause
     8  */
     9  #include <mcl/fp.hpp>
    10  #include <mcl/ec.hpp>
    11  #include <mcl/ecparam.hpp>
    12  #include <mcl/window_method.hpp>
    13  
    14  namespace mcl { namespace ecdsa {
    15  
    16  namespace local {
    17  
    18  #ifndef MCLSHE_WIN_SIZE
    19  	#define MCLSHE_WIN_SIZE 10
    20  #endif
    21  static const size_t winSize = MCLSHE_WIN_SIZE;
    22  
    23  struct FpTag;
    24  struct ZnTag;
    25  
    26  } // mcl::ecdsa::local
    27  
    28  typedef mcl::FpT<local::FpTag, 256> Fp;
    29  typedef mcl::FpT<local::ZnTag, 256> Zn;
    30  typedef mcl::EcT<Fp> Ec;
    31  
    32  namespace local {
    33  
    34  struct Param {
    35  	mcl::EcParam ecParam;
    36  	Ec P;
    37  	mcl::fp::WindowMethod<Ec> Pbase;
    38  };
    39  
    40  inline Param& getParam()
    41  {
    42  	static Param p;
    43  	return p;
    44  }
    45  
    46  inline void be32toZn(Zn& x, const mcl::fp::Unit *buf)
    47  {
    48  	const size_t n = 32;
    49  	const unsigned char *p = (const unsigned char*)buf;
    50  	unsigned char be[n];
    51  	for (size_t i = 0; i < n; i++) {
    52  		be[i] = p[n - 1 - i];
    53  	}
    54  	x.setArrayMaskMod(be, n);
    55  }
    56  
    57  /*
    58  	y = x mod n
    59  */
    60  inline void FpToZn(Zn& y, const Fp& x)
    61  {
    62  	fp::Block b;
    63  	x.getBlock(b);
    64  	y.setArrayMaskMod(b.p, b.n);
    65  }
    66  
    67  inline void setHashOf(Zn& x, const void *msg, size_t msgSize)
    68  {
    69  	mcl::fp::Unit xBuf[256 / 8 / sizeof(mcl::fp::Unit)];
    70  	uint32_t hashSize = mcl::fp::sha256(xBuf, sizeof(xBuf), msg, (uint32_t)msgSize);
    71  	assert(hashSize == sizeof(xBuf));
    72  	(void)hashSize;
    73  	be32toZn(x, xBuf);
    74  }
    75  
    76  } // mcl::ecdsa::local
    77  
    78  const local::Param& param = local::getParam();
    79  
    80  inline void init(bool *pb)
    81  {
    82  	const mcl::EcParam& ecParam = mcl::ecparam::secp256k1;
    83  	Zn::init(pb, ecParam.n);
    84  	if (!*pb) return;
    85  	Fp::init(pb, ecParam.p);
    86  	if (!*pb) return;
    87  	Ec::init(pb, ecParam.a, ecParam.b);
    88  	if (!*pb) return;
    89  	Zn::setIoMode(16);
    90  	Fp::setIoMode(16);
    91  	Ec::setIoMode(mcl::IoEcAffine);
    92  	local::Param& p = local::getParam();
    93  	p.ecParam = ecParam;
    94  	Fp x, y;
    95  	x.setStr(pb, ecParam.gx);
    96  	if (!*pb) return;
    97  	y.setStr(pb, ecParam.gy);
    98  	if (!*pb) return;
    99  	p.P.set(pb, x, y);
   100  	if (!*pb) return;
   101  	p.Pbase.init(pb, p.P, ecParam.bitSize, local::winSize);
   102  }
   103  
   104  #ifndef CYBOZU_DONT_USE_EXCEPTION
   105  inline void init()
   106  {
   107  	bool b;
   108  	init(&b);
   109  	if (!b) throw cybozu::Exception("ecdsa:init");
   110  }
   111  #endif
   112  
   113  typedef Zn SecretKey;
   114  typedef Ec PublicKey;
   115  
   116  struct PrecomputedPublicKey {
   117  	mcl::fp::WindowMethod<Ec> pubBase_;
   118  	void init(bool *pb, const PublicKey& pub)
   119  	{
   120  		pubBase_.init(pb, pub, param.ecParam.bitSize, local::winSize);
   121  	}
   122  #ifndef CYBOZU_DONT_USE_EXCEPTION
   123  	void init(const PublicKey& pub)
   124  	{
   125  		bool b;
   126  		init(&b, pub);
   127  		if (!b) throw cybozu::Exception("ecdsa:PrecomputedPublicKey:init");
   128  	}
   129  #endif
   130  };
   131  
   132  inline void getPublicKey(PublicKey& pub, const SecretKey& sec)
   133  {
   134  	Ec::mul(pub, param.P, sec);
   135  	pub.normalize();
   136  }
   137  
   138  struct Signature : public mcl::fp::Serializable<Signature> {
   139  	Zn r, s;
   140  	template<class InputStream>
   141  	void load(bool *pb, InputStream& is, int ioMode = IoSerialize)
   142  	{
   143  		r.load(pb, is, ioMode); if (!*pb) return;
   144  		s.load(pb, is, ioMode);
   145  	}
   146  	template<class OutputStream>
   147  	void save(bool *pb, OutputStream& os, int ioMode = IoSerialize) const
   148  	{
   149  		const char sep = *fp::getIoSeparator(ioMode);
   150  		r.save(pb, os, ioMode); if (!*pb) return;
   151  		if (sep) {
   152  			cybozu::writeChar(pb, os, sep);
   153  			if (!*pb) return;
   154  		}
   155  		s.save(pb, os, ioMode);
   156  	}
   157  #ifndef CYBOZU_DONT_USE_EXCEPTION
   158  	template<class InputStream>
   159  	void load(InputStream& is, int ioMode = IoSerialize)
   160  	{
   161  		bool b;
   162  		load(&b, is, ioMode);
   163  		if (!b) throw cybozu::Exception("ecdsa:Signature:load");
   164  	}
   165  	template<class OutputStream>
   166  	void save(OutputStream& os, int ioMode = IoSerialize) const
   167  	{
   168  		bool b;
   169  		save(&b, os, ioMode);
   170  		if (!b) throw cybozu::Exception("ecdsa:Signature:save");
   171  	}
   172  #endif
   173  #ifndef CYBOZU_DONT_USE_STRING
   174  	friend std::istream& operator>>(std::istream& is, Signature& self)
   175  	{
   176  		self.load(is, fp::detectIoMode(Ec::getIoMode(), is));
   177  		return is;
   178  	}
   179  	friend std::ostream& operator<<(std::ostream& os, const Signature& self)
   180  	{
   181  		self.save(os, fp::detectIoMode(Ec::getIoMode(), os));
   182  		return os;
   183  	}
   184  #endif
   185  };
   186  
   187  inline void sign(Signature& sig, const SecretKey& sec, const void *msg, size_t msgSize)
   188  {
   189  	Zn& r = sig.r;
   190  	Zn& s = sig.s;
   191  	Zn z, k;
   192  	local::setHashOf(z, msg, msgSize);
   193  	Ec Q;
   194  	for (;;) {
   195  		k.setByCSPRNG();
   196  		param.Pbase.mul(Q, k);
   197  		if (Q.isZero()) continue;
   198  		Q.normalize();
   199  		local::FpToZn(r, Q.x);
   200  		if (r.isZero()) continue;
   201  		Zn::mul(s, r, sec);
   202  		s += z;
   203  		if (s.isZero()) continue;
   204  		s /= k;
   205  		return;
   206  	}
   207  }
   208  
   209  namespace local {
   210  
   211  inline void mulDispatch(Ec& Q, const PublicKey& pub, const Zn& y)
   212  {
   213  	Ec::mul(Q, pub, y);
   214  }
   215  
   216  inline void mulDispatch(Ec& Q, const PrecomputedPublicKey& ppub, const Zn& y)
   217  {
   218  	ppub.pubBase_.mul(Q, y);
   219  }
   220  
   221  template<class Pub>
   222  inline bool verify(const Signature& sig, const Pub& pub, const void *msg, size_t msgSize)
   223  {
   224  	const Zn& r = sig.r;
   225  	const Zn& s = sig.s;
   226  	if (r.isZero() || s.isZero()) return false;
   227  	Zn z, w, u1, u2;
   228  	local::setHashOf(z, msg, msgSize);
   229  	Zn::inv(w, s);
   230  	Zn::mul(u1, z, w);
   231  	Zn::mul(u2, r, w);
   232  	Ec Q1, Q2;
   233  	param.Pbase.mul(Q1, u1);
   234  //	Ec::mul(Q2, pub, u2);
   235  	local::mulDispatch(Q2, pub, u2);
   236  	Q1 += Q2;
   237  	if (Q1.isZero()) return false;
   238  	Q1.normalize();
   239  	Zn x;
   240  	local::FpToZn(x, Q1.x);
   241  	return r == x;
   242  }
   243  
   244  } // mcl::ecdsa::local
   245  
   246  inline bool verify(const Signature& sig, const PublicKey& pub, const void *msg, size_t msgSize)
   247  {
   248  	return local::verify(sig, pub, msg, msgSize);
   249  }
   250  
   251  inline bool verify(const Signature& sig, const PrecomputedPublicKey& ppub, const void *msg, size_t msgSize)
   252  {
   253  	return local::verify(sig, ppub, msg, msgSize);
   254  }
   255  
   256  } } // mcl::ecdsa
   257