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