test of ecdsa runs well

dev
MITSUNARI Shigeo 7 years ago
parent c4489ae8c2
commit e1b875e386
  1. 4
      Makefile
  2. 209
      include/mcl/ecdsa.hpp
  3. 69
      test/ecdsa_test.cpp

@ -3,7 +3,7 @@ LIB_DIR=lib
OBJ_DIR=obj
EXE_DIR=bin
SRC_SRC=fp.cpp bn_c256.cpp bn_c384.cpp bn_c512.cpp she_c256.cpp
TEST_SRC=fp_test.cpp ec_test.cpp fp_util_test.cpp window_method_test.cpp elgamal_test.cpp fp_tower_test.cpp gmp_test.cpp bn_test.cpp bn384_test.cpp glv_test.cpp paillier_test.cpp she_test.cpp vint_test.cpp bn512_test.cpp
TEST_SRC=fp_test.cpp ec_test.cpp fp_util_test.cpp window_method_test.cpp elgamal_test.cpp fp_tower_test.cpp gmp_test.cpp bn_test.cpp bn384_test.cpp glv_test.cpp paillier_test.cpp she_test.cpp vint_test.cpp bn512_test.cpp ecdsa_test.cpp
TEST_SRC+=bn_c256_test.cpp bn_c384_test.cpp bn_c512_test.cpp she_c256_test.cpp she_c384_test.cpp
TEST_SRC+=aggregate_sig_test.cpp
TEST_SRC+=bls12_test.cpp
@ -279,4 +279,4 @@ install: lib/libmcl.a lib/libmcl$(SHARE_BASENAME_SUF).$(LIB_SUF)
# don't remove these files automatically
.SECONDARY: $(addprefix $(OBJ_DIR)/, $(ALL_SRC:.cpp=.o))

@ -0,0 +1,209 @@
#pragma once
/**
@file
@brief ECDSA
@author MITSUNARI Shigeo(@herumi)
@license modified new BSD license
http://opensource.org/licenses/BSD-3-Clause
*/
#include <mcl/fp.hpp>
#include <mcl/ec.hpp>
#include <mcl/ecparam.hpp>
#include <mcl/window_method.hpp>
namespace mcl { namespace ecdsa {
namespace local {
#ifndef MCLSHE_WIN_SIZE
#define MCLSHE_WIN_SIZE 10
#endif
static const size_t winSize = MCLSHE_WIN_SIZE;
struct FpTag;
struct ZnTag;
} // mcl::ecdsa::local
typedef mcl::FpT<local::FpTag, 256> Fp;
typedef mcl::FpT<local::ZnTag, 256> Zn;
typedef mcl::EcT<Fp> Ec;
namespace local {
struct Param {
mcl::EcParam ecParam;
Ec P;
mcl::fp::WindowMethod<Ec> Pbase;
};
inline Param& getParam()
{
static Param p;
return p;
}
inline void be32toZn(Zn& x, const mcl::fp::Unit *buf)
{
const size_t n = 32;
const unsigned char *p = (const unsigned char*)buf;
unsigned char be[n];
for (size_t i = 0; i < n; i++) {
be[i] = p[n - 1 - i];
}
x.setArrayMaskMod(be, n);
}
/*
y = x mod n
*/
inline void FpToZn(Zn& y, const Fp& x)
{
fp::Block b;
x.getBlock(b);
y.setArrayMaskMod(b.p, b.n);
}
inline void setHashOf(Zn& x, const void *msg, size_t msgSize)
{
mcl::fp::Unit xBuf[256 / 8 / sizeof(mcl::fp::Unit)];
uint32_t hashSize = mcl::fp::sha256(xBuf, sizeof(xBuf), msg, msgSize);
assert(hashSize == sizeof(xBuf));
(void)hashSize;
be32toZn(x, xBuf);
}
} // mcl::ecdsa::local
const local::Param& param = local::getParam();
inline void init()
{
const mcl::EcParam& ecParam = mcl::ecparam::secp256k1;
Zn::init(ecParam.n);
Fp::init(ecParam.p);
Ec::init(ecParam.a, ecParam.b);
Zn::setIoMode(16);
Fp::setIoMode(16);
Ec::setIoMode(mcl::IoEcAffine);
local::Param& p = local::getParam();
p.ecParam = ecParam;
p.P.set(Fp(ecParam.gx), Fp(ecParam.gy));
p.Pbase.init(p.P, ecParam.bitSize, local::winSize);
}
typedef Zn SecretKey;
typedef Ec PublicKey;
struct PrecomputedPublicKey {
mcl::fp::WindowMethod<Ec> pubBase_;
void init(const PublicKey& pub)
{
pubBase_.init(pub, param.ecParam.bitSize, local::winSize);
}
};
inline void getPublicKey(PublicKey& pub, const SecretKey& sec)
{
Ec::mul(pub, param.P, sec);
}
struct Signature : public mcl::fp::Serializable<Signature> {
Zn r, s;
template<class InputStream>
void load(InputStream& is, int ioMode = IoSerialize)
{
r.load(is, ioMode);
s.load(is, ioMode);
}
template<class OutputStream>
void save(OutputStream& os, int ioMode = IoSerialize) const
{
const char sep = *fp::getIoSeparator(ioMode);
r.save(os, ioMode);
if (sep) cybozu::writeChar(os, sep);
s.save(os, ioMode);
}
friend std::istream& operator>>(std::istream& is, Signature& self)
{
self.load(is, fp::detectIoMode(Ec::getIoMode(), is));
return is;
}
friend std::ostream& operator<<(std::ostream& os, const Signature& self)
{
self.save(os, fp::detectIoMode(Ec::getIoMode(), os));
return os;
}
};
inline bool sign(Signature& sig, const SecretKey& sec, const void *msg, size_t msgSize)
{
Zn& r = sig.r;
Zn& s = sig.s;
Zn z, k;
local::setHashOf(z, msg, msgSize);
Ec Q;
for (;;) {
k.setByCSPRNG();
param.Pbase.mul(Q, k);
if (Q.isZero()) continue;
Q.normalize();
local::FpToZn(r, Q.x);
if (r.isZero()) continue;
Zn::mul(s, r, sec);
s += z;
if (s.isZero()) continue;
s /= k;
return true;
}
}
namespace local {
inline void mulDispatch(Ec& Q, const PublicKey& pub, const Zn& y)
{
Ec::mul(Q, pub, y);
}
inline void mulDispatch(Ec& Q, const PrecomputedPublicKey& ppub, const Zn& y)
{
ppub.pubBase_.mul(Q, y);
}
template<class Pub>
inline bool verify(const Signature& sig, const Pub& pub, const void *msg, size_t msgSize)
{
const Zn& r = sig.r;
const Zn& s = sig.s;
if (r.isZero() || s.isZero()) return false;
Zn z, w, u1, u2;
local::setHashOf(z, msg, msgSize);
Zn::inv(w, s);
Zn::mul(u1, z, w);
Zn::mul(u2, r, w);
Ec Q1, Q2;
param.Pbase.mul(Q1, u1);
// Ec::mul(Q2, pub, u2);
local::mulDispatch(Q2, pub, u2);
Q1 += Q2;
if (Q1.isZero()) return false;
Q1.normalize();
Zn x;
local::FpToZn(x, Q1.x);
return r == x;
}
} // mcl::ecdsa::local
inline bool verify(const Signature& sig, const PublicKey& pub, const void *msg, size_t msgSize)
{
return local::verify(sig, pub, msg, msgSize);
}
inline bool verify(const Signature& sig, const PrecomputedPublicKey& ppub, const void *msg, size_t msgSize)
{
return local::verify(sig, ppub, msg, msgSize);
}
} } // mcl::ecdsa

@ -0,0 +1,69 @@
#define PUT(x) std::cout << #x "=" << x << std::endl;
#include <stdlib.h>
#include <stdio.h>
void put(const void *buf, size_t bufSize)
{
const unsigned char* p = (const unsigned char*)buf;
for (size_t i = 0; i < bufSize; i++) {
printf("%02x", p[i]);
}
printf("\n");
}
#include <mcl/ecdsa.hpp>
#include <cybozu/test.hpp>
#include <cybozu/benchmark.hpp>
using namespace mcl::ecdsa;
CYBOZU_TEST_AUTO(ecdsa)
{
init();
SecretKey sec;
PublicKey pub;
sec.setByCSPRNG();
getPublicKey(pub, sec);
Signature sig;
const std::string msg = "hello";
CYBOZU_TEST_ASSERT(sign(sig, sec, msg.c_str(), msg.size()));
CYBOZU_TEST_ASSERT(verify(sig, pub, msg.c_str(), msg.size()));
sig.s += 1;
CYBOZU_TEST_ASSERT(!verify(sig, pub, msg.c_str(), msg.size()));
}
CYBOZU_TEST_AUTO(value)
{
const std::string msg = "hello";
const char *secStr = "83ecb3984a4f9ff03e84d5f9c0d7f888a81833643047acc58eb6431e01d9bac8";
const char *pubxStr = "653bd02ba1367e5d4cd695b6f857d1cd90d4d8d42bc155d85377b7d2d0ed2e71";
const char *pubyStr = "04e8f5da403ab78decec1f19e2396739ea544e2b14159beb5091b30b418b813a";
const char *sigStr = "a598a8030da6d86c6bc7f2f5144ea549d28211ea58faa70ebf4c1e665c1fe9b5de5d79a2ba44e311d04fdca263639283965780bce9169822be9cc81756e95a24";
SecretKey sec;
sec.setStr(secStr, 16);
CYBOZU_TEST_EQUAL(sec.getStr(16), secStr);
PublicKey pub;
getPublicKey(pub, sec);
pub.normalize();
Ec t(Fp(pubxStr, 16), Fp(pubyStr, 16));
CYBOZU_TEST_EQUAL(pub, t);
Signature sig;
sig.r.setStr(std::string(sigStr, 64), 16);
sig.s.setStr(std::string(sigStr + 64, 64), 16);
PUT(sig);
CYBOZU_TEST_ASSERT(verify(sig, pub, msg.c_str(), msg.size()));
}
CYBOZU_TEST_AUTO(bench)
{
const std::string msg = "hello";
SecretKey sec;
PublicKey pub;
PrecomputedPublicKey ppub;
sec.setByCSPRNG();
getPublicKey(pub, sec);
ppub.init(pub);
Signature sig;
CYBOZU_BENCH_C("sign", 1000, sign, sig, sec, msg.c_str(), msg.size());
CYBOZU_BENCH_C("pub.verify ", 1000, verify, sig, pub, msg.c_str(), msg.size());
CYBOZU_BENCH_C("ppub.verify", 1000, verify, sig, ppub, msg.c_str(), msg.size());
}
Loading…
Cancel
Save