mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-04-28 11:47:48 +02:00
cumulative update from bitbucket
This commit is contained in:
parent
73d4025256
commit
62cf83921b
76 changed files with 2408 additions and 2272 deletions
398
Signature.cpp
398
Signature.cpp
|
@ -1,6 +1,4 @@
|
|||
#include <memory>
|
||||
#include <cryptopp/integer.h>
|
||||
#include <cryptopp/eccrypto.h>
|
||||
#include "Log.h"
|
||||
#include "Signature.h"
|
||||
|
||||
|
@ -14,82 +12,360 @@ namespace crypto
|
|||
|
||||
Ed25519 ()
|
||||
{
|
||||
q = CryptoPP::Integer::Power2 (255) - CryptoPP::Integer (19); // 2^255-19
|
||||
l = CryptoPP::Integer::Power2 (252) + CryptoPP::Integer ("27742317777372353535851937790883648493");
|
||||
BN_CTX * ctx = BN_CTX_new ();
|
||||
BIGNUM * two = BN_new (), * tmp = BN_new ();
|
||||
BN_set_word (two, 2);
|
||||
|
||||
q = BN_new ();
|
||||
// 2^255-19
|
||||
BN_set_word (tmp, 255);
|
||||
BN_exp (q, two, tmp, ctx);
|
||||
BN_sub_word (q, 19);
|
||||
// q_2 = q-2
|
||||
q_2 = BN_dup (q);
|
||||
BN_sub_word (q_2, 2);
|
||||
|
||||
l = BN_new ();
|
||||
// 2^252 + 27742317777372353535851937790883648493
|
||||
d = CryptoPP::Integer (-121665) * CryptoPP::Integer (121666).InverseMod (q); // -121665/121666
|
||||
I = a_exp_b_mod_c (CryptoPP::Integer::Two (), (q - CryptoPP::Integer::One ()).DividedBy (4), q);
|
||||
B = DecodePoint (CryptoPP::Integer (4)*CryptoPP::Integer (5).InverseMod (q));
|
||||
BN_set_word (tmp, 252);
|
||||
BN_exp (l, two, tmp, ctx);
|
||||
two_252_2 = BN_dup (l);
|
||||
BN_dec2bn (&tmp, "27742317777372353535851937790883648493");
|
||||
BN_add (l, l, tmp);
|
||||
BN_sub_word (two_252_2, 2); // 2^252 - 2
|
||||
|
||||
// -121665*inv(121666)
|
||||
d = BN_new ();
|
||||
BN_set_word (tmp, 121666);
|
||||
Inv (tmp, ctx);
|
||||
BN_set_word (d, 121665);
|
||||
BN_set_negative (d, -1);
|
||||
BN_mul (d, d, tmp, ctx);
|
||||
|
||||
// 2^((q-1)/4)
|
||||
I = BN_new ();
|
||||
BN_free (tmp);
|
||||
tmp = BN_dup (q);
|
||||
BN_sub_word (tmp, 1);
|
||||
BN_div_word (tmp, 4);
|
||||
BN_mod_exp (I, two, tmp, q, ctx);
|
||||
|
||||
// 4*inv(5)
|
||||
BIGNUM * By = BN_new ();
|
||||
BN_set_word (By, 5);
|
||||
Inv (By, ctx);
|
||||
BN_mul_word (By, 4);
|
||||
BIGNUM * Bx = RecoverX (By, ctx);
|
||||
BN_mod (Bx, Bx, q, ctx); // % q
|
||||
BN_mod (By, By, q, ctx); // % q
|
||||
B = {Bx, By};
|
||||
|
||||
BN_free (two);
|
||||
BN_free (tmp);
|
||||
|
||||
// precalculate Bi
|
||||
Bi[0] = { BN_dup (Bx), BN_dup (By) };
|
||||
for (int i = 1; i < 256; i++)
|
||||
Bi[i] = Double (Bi[i-1], ctx);
|
||||
|
||||
BN_CTX_free (ctx);
|
||||
}
|
||||
|
||||
CryptoPP::ECP::Point DecodePublicKey (const uint8_t * key) const
|
||||
~Ed25519 ()
|
||||
{
|
||||
return DecodePoint (CryptoPP::Integer (key, 32));
|
||||
BN_free (q);
|
||||
BN_free (l);
|
||||
BN_free (d);
|
||||
BN_free (I);
|
||||
BN_free (q_2);
|
||||
BN_free (two_252_2);
|
||||
}
|
||||
|
||||
CryptoPP::ECP::Point GeneratePublicKey (const uint8_t * privateKey) const
|
||||
|
||||
EDDSAPoint GeneratePublicKey (const uint8_t * expandedPrivateKey, BN_CTX * ctx) const
|
||||
{
|
||||
return Mul (B, CryptoPP::Integer (privateKey, 32));
|
||||
return MulB (expandedPrivateKey, ctx); // left half of expanded key, considered as Little Endian
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
CryptoPP::ECP::Point Sum (const CryptoPP::ECP::Point& p1, const CryptoPP::ECP::Point& p2) const
|
||||
EDDSAPoint DecodePublicKey (const uint8_t * buf, BN_CTX * ctx) const
|
||||
{
|
||||
CryptoPP::Integer m = d*p1.x*p2.x*p1.y*p2.y,
|
||||
x = a_times_b_mod_c (p1.x*p2.y + p2.x*p1.y, (CryptoPP::Integer::One() + m).InverseMod (q), q),
|
||||
y = a_times_b_mod_c (p1.y*p2.y + p1.x*p2.x, (CryptoPP::Integer::One() - m).InverseMod (q), q);
|
||||
return CryptoPP::ECP::Point {x, y};
|
||||
return DecodePoint (buf, ctx);
|
||||
}
|
||||
|
||||
CryptoPP::ECP::Point Mul (const CryptoPP::ECP::Point& p, const CryptoPP::Integer& e) const
|
||||
void EncodePublicKey (const EDDSAPoint& publicKey, uint8_t * buf) const
|
||||
{
|
||||
CryptoPP::ECP::Point res {0, 1};
|
||||
if (!e.IsZero ())
|
||||
EncodePoint (publicKey, buf);
|
||||
}
|
||||
|
||||
bool Verify (const EDDSAPoint& publicKey, const uint8_t * digest, const uint8_t * signature, BN_CTX * ctx) const
|
||||
{
|
||||
BIGNUM * h = DecodeBN (digest, 64);
|
||||
// signature 0..31 - R, 32..63 - S
|
||||
bool passed = MulB (signature + EDDSA25519_SIGNATURE_LENGTH/2, ctx) /*S*/ ==
|
||||
Sum (DecodePoint (signature, ctx) /*R*/, Mul (publicKey, h, ctx), ctx);
|
||||
BN_free (h);
|
||||
if (!passed)
|
||||
LogPrint (eLogError, "25519 signature verification failed");
|
||||
return passed;
|
||||
}
|
||||
|
||||
void Sign (const uint8_t * expandedPrivateKey, const uint8_t * publicKeyEncoded, const uint8_t * buf, size_t len,
|
||||
uint8_t * signature, BN_CTX * bnCtx) const
|
||||
{
|
||||
// calculate r
|
||||
SHA512_CTX ctx;
|
||||
SHA512_Init (&ctx);
|
||||
SHA512_Update (&ctx, expandedPrivateKey + EDDSA25519_PRIVATE_KEY_LENGTH, EDDSA25519_PRIVATE_KEY_LENGTH); // right half of expanded key
|
||||
SHA512_Update (&ctx, buf, len); // data
|
||||
uint8_t digest[64];
|
||||
SHA512_Final (digest, &ctx);
|
||||
BIGNUM * r = DecodeBN (digest, 32); // DecodeBN (digest, 64); // for test vectors
|
||||
// calculate R
|
||||
uint8_t R[EDDSA25519_SIGNATURE_LENGTH/2]; // we must use separate buffer because signature might be inside buf
|
||||
EncodePoint (MulB (digest, bnCtx), R); // EncodePoint (Mul (B, r, bnCtx), R); // for test vectors
|
||||
// calculate S
|
||||
SHA512_Init (&ctx);
|
||||
SHA512_Update (&ctx, R, EDDSA25519_SIGNATURE_LENGTH/2); // R
|
||||
SHA512_Update (&ctx, publicKeyEncoded, EDDSA25519_PUBLIC_KEY_LENGTH); // public key
|
||||
SHA512_Update (&ctx, buf, len); // data
|
||||
SHA512_Final (digest, &ctx);
|
||||
BIGNUM * s = DecodeBN (digest, 64);
|
||||
// S = (r + s*a) % l
|
||||
BIGNUM * a = DecodeBN (expandedPrivateKey, EDDSA25519_PRIVATE_KEY_LENGTH); // left half of expanded key
|
||||
BN_mul (s, s, a, bnCtx);
|
||||
BN_add (s, s, r);
|
||||
BN_mod (s, s, l, bnCtx); // % l
|
||||
memcpy (signature, R, EDDSA25519_SIGNATURE_LENGTH/2);
|
||||
EncodeBN (s, signature + EDDSA25519_SIGNATURE_LENGTH/2, EDDSA25519_SIGNATURE_LENGTH/2); // S
|
||||
BN_free (r); BN_free (s); BN_free (a);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
EDDSAPoint Sum (const EDDSAPoint& p1, const EDDSAPoint& p2, BN_CTX * ctx) const
|
||||
{
|
||||
BIGNUM * xx = BN_new (), * yy = BN_new ();
|
||||
// m = d*p1.x*p2.x*p1.y*p2.y
|
||||
BN_mul (xx, p1.x, p2.x, ctx);
|
||||
BN_mul (yy, p1.y, p2.y, ctx);
|
||||
BIGNUM * m = BN_dup (d);
|
||||
BN_mul (m, m, xx, ctx);
|
||||
BN_mul (m, m, yy, ctx);
|
||||
// x = (p1.x*p2.y + p2.x*p1.y)*inv(1 + m)
|
||||
// y = (p1.y*p2.y + p1.x*p2.x)*inv(1 - m)
|
||||
|
||||
// use one inversion instead two
|
||||
// m1 = 1-m
|
||||
BIGNUM * m1 = BN_new ();
|
||||
BN_one (m1);
|
||||
BN_sub (m1, m1, m);
|
||||
// m = m+1
|
||||
BN_add_word (m, 1);
|
||||
// y = (p1.y*p2.y + p1.x*p2.x)*m
|
||||
BIGNUM * y = BN_new ();
|
||||
BN_add (y, xx, yy);
|
||||
BN_mod_mul (y, y, m, q, ctx);
|
||||
// x = (p1.x*p2.y + p2.x*p1.y)*m1
|
||||
BIGNUM * x = BN_new ();
|
||||
BN_mul (yy, p1.x, p2.y, ctx);
|
||||
BN_mul (xx, p2.x, p1.y, ctx);
|
||||
BN_add (x, xx, yy);
|
||||
BN_mod_mul (x, x, m1, q, ctx);
|
||||
// denominator m = m*m1
|
||||
BN_mod_mul (m, m, m1, q, ctx);
|
||||
Inv (m, ctx);
|
||||
BN_mod_mul (x, x, m, q, ctx); // x = x/m
|
||||
BN_mod_mul (y, y, m, q, ctx); // y = y/m
|
||||
|
||||
BN_free (xx);BN_free (yy); BN_free (m); BN_free (m1);
|
||||
return EDDSAPoint {x, y};
|
||||
}
|
||||
|
||||
EDDSAPoint Double (const EDDSAPoint& p, BN_CTX * ctx) const
|
||||
{
|
||||
BIGNUM * pxy = BN_new ();
|
||||
BN_mul (pxy, p.x, p.y, ctx);
|
||||
// m = d*(p.x*p.y)^2
|
||||
BIGNUM * m = BN_new ();
|
||||
BN_sqr (m, pxy, ctx);
|
||||
BN_mul (m, m, d, ctx);
|
||||
// x = (2*p.x*p.y)*inv(1 + m)
|
||||
// y = (p.x^2 + p.y^2)*inv(1 - m)
|
||||
|
||||
// use one inversion instead two
|
||||
// m1 = 1-m
|
||||
BIGNUM * m1 = BN_new ();
|
||||
BN_one (m1);
|
||||
BN_sub (m1, m1, m);
|
||||
// m = m+1
|
||||
BN_add_word (m, 1);
|
||||
// x = 2*p.x*p.y*m1
|
||||
BN_mul_word (pxy, 2);
|
||||
BIGNUM * x = BN_new ();
|
||||
BN_mod_mul (x, pxy, m1, q, ctx);
|
||||
// y = (p.x^2 + p.y^2)*m
|
||||
BIGNUM * y = BN_new ();
|
||||
BN_sqr (pxy, p.x, ctx);
|
||||
BN_sqr (y, p.y, ctx);
|
||||
BN_add (pxy, pxy, y);
|
||||
BN_mod_mul (y, pxy, m, q, ctx);
|
||||
// denominator m = m*m1
|
||||
BN_mod_mul (m, m, m1, q, ctx);
|
||||
Inv (m, ctx);
|
||||
BN_mod_mul (x, x, m, q, ctx); // x = x/m
|
||||
BN_mod_mul (y, y, m, q, ctx); // y = y/m
|
||||
|
||||
BN_free (pxy); BN_free (m); BN_free (m1);
|
||||
return EDDSAPoint {x, y};
|
||||
}
|
||||
|
||||
EDDSAPoint Mul (const EDDSAPoint& p, const BIGNUM * e, BN_CTX * ctx) const
|
||||
{
|
||||
BIGNUM * zero = BN_new (), * one = BN_new ();
|
||||
BN_zero (zero); BN_one (one);
|
||||
EDDSAPoint res {zero, one};
|
||||
if (!BN_is_zero (e))
|
||||
{
|
||||
auto bitCount = e.BitCount ();
|
||||
int bitCount = BN_num_bits (e);
|
||||
for (int i = bitCount - 1; i >= 0; i--)
|
||||
{
|
||||
res = Sum (res, res);
|
||||
if (e.GetBit (i)) res = Sum (res, p);
|
||||
res = Double (res, ctx);
|
||||
if (BN_is_bit_set (e, i)) res = Sum (res, p, ctx);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool IsOnCurve (const CryptoPP::ECP::Point& p) const
|
||||
|
||||
EDDSAPoint MulB (const uint8_t * e, BN_CTX * ctx) const // B*e. e is 32 bytes Little Endian
|
||||
{
|
||||
auto x2 = p.x.Squared(), y2 = p.y.Squared ();
|
||||
return (y2 - x2 - CryptoPP::Integer::One() - d*x2*y2).Modulo (q).IsZero ();
|
||||
BIGNUM * zero = BN_new (), * one = BN_new ();
|
||||
BN_zero (zero); BN_one (one);
|
||||
EDDSAPoint res {zero, one};
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
for (int j = 0; j < 8; j++)
|
||||
if (e[i] & (1 << j)) // from lowest to highest bit
|
||||
res = Sum (res, Bi[i*8 + j], ctx);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void Inv (BIGNUM * x, BN_CTX * ctx) const
|
||||
{
|
||||
BN_mod_exp (x, x, q_2, q, ctx);
|
||||
}
|
||||
|
||||
bool IsOnCurve (const EDDSAPoint& p, BN_CTX * ctx) const
|
||||
{
|
||||
BIGNUM * x2 = BN_new ();
|
||||
BN_sqr (x2, p.x, ctx); // x^2
|
||||
BIGNUM * y2 = BN_new ();
|
||||
BN_sqr (y2, p.y, ctx); // y^2
|
||||
// y^2 - x^2 - 1 - d*x^2*y^2
|
||||
BIGNUM * tmp = BN_new ();
|
||||
BN_mul (tmp, d, x2, ctx);
|
||||
BN_mul (tmp, tmp, y2, ctx);
|
||||
BN_sub (tmp, y2, tmp);
|
||||
BN_sub (tmp, tmp, x2);
|
||||
BN_sub_word (tmp, 1);
|
||||
BN_mod (tmp, tmp, q, ctx); // % q
|
||||
bool ret = BN_is_zero (tmp);
|
||||
BN_free (x2);
|
||||
BN_free (y2);
|
||||
BN_free (tmp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
CryptoPP::Integer RecoverX (const CryptoPP::Integer& y) const
|
||||
BIGNUM * RecoverX (const BIGNUM * y, BN_CTX * ctx) const
|
||||
{
|
||||
auto y2 = y.Squared ();
|
||||
auto xx = (y2 - CryptoPP::Integer::One())*(d*y2 + CryptoPP::Integer::One()).InverseMod (q);
|
||||
auto x = a_exp_b_mod_c (xx, (q + CryptoPP::Integer (3)).DividedBy (8), q);
|
||||
if (!(x.Squared () - xx).Modulo (q).IsZero ())
|
||||
x = a_times_b_mod_c (x, I, q);
|
||||
if (x.IsOdd ()) x = q - x;
|
||||
BIGNUM * y2 = BN_new ();
|
||||
BN_sqr (y2, y, ctx); // y^2
|
||||
// xx = (y^2 -1)*inv(d*y^2 +1)
|
||||
BIGNUM * xx = BN_new ();
|
||||
BN_mul (xx, d, y2, ctx);
|
||||
BN_add_word (xx, 1);
|
||||
Inv (xx, ctx);
|
||||
BN_sub_word (y2, 1);
|
||||
BN_mul (xx, y2, xx, ctx);
|
||||
// x = srqt(xx) = xx^(2^252-2)
|
||||
BIGNUM * x = BN_new ();
|
||||
BN_mod_exp (x, xx, two_252_2, q, ctx);
|
||||
// check (x^2 -xx) % q
|
||||
BN_sqr (y2, x, ctx);
|
||||
BN_mod_sub (y2, y2, xx, q, ctx);
|
||||
if (!BN_is_zero (y2))
|
||||
BN_mod_mul (x, x, I, q, ctx);
|
||||
if (BN_is_odd (x))
|
||||
BN_sub (x, q, x);
|
||||
BN_free (y2);
|
||||
BN_free (xx);
|
||||
return x;
|
||||
}
|
||||
|
||||
CryptoPP::ECP::Point DecodePoint (const CryptoPP::Integer& y) const
|
||||
EDDSAPoint DecodePoint (const uint8_t * buf, BN_CTX * ctx) const
|
||||
{
|
||||
auto x = RecoverX (y);
|
||||
CryptoPP::ECP::Point p {x, y};
|
||||
if (!IsOnCurve (p))
|
||||
// buf is 32 bytes Little Endian, convert it to Big Endian
|
||||
uint8_t buf1[EDDSA25519_PUBLIC_KEY_LENGTH];
|
||||
for (size_t i = 0; i < EDDSA25519_PUBLIC_KEY_LENGTH/2; i++) // invert bytes
|
||||
{
|
||||
LogPrint (eLogError, "Decoded point is not on 25519");
|
||||
return CryptoPP::ECP::Point {0, 1};
|
||||
buf1[i] = buf[EDDSA25519_PUBLIC_KEY_LENGTH -1 - i];
|
||||
buf1[EDDSA25519_PUBLIC_KEY_LENGTH -1 - i] = buf[i];
|
||||
}
|
||||
bool isHighestBitSet = buf1[0] & 0x80;
|
||||
if (isHighestBitSet)
|
||||
buf1[0] &= 0x7f; // clear highest bit
|
||||
BIGNUM * y = BN_new ();
|
||||
BN_bin2bn (buf1, EDDSA25519_PUBLIC_KEY_LENGTH, y);
|
||||
auto x = RecoverX (y, ctx);
|
||||
if (BN_is_bit_set (x, 0) != isHighestBitSet)
|
||||
BN_sub (x, q, x); // x = q - x
|
||||
EDDSAPoint p {x, y};
|
||||
if (!IsOnCurve (p, ctx))
|
||||
LogPrint (eLogError, "Decoded point is not on 25519");
|
||||
return p;
|
||||
}
|
||||
|
||||
void EncodePoint (const EDDSAPoint& p, uint8_t * buf) const
|
||||
{
|
||||
EncodeBN (p.y, buf,EDDSA25519_PUBLIC_KEY_LENGTH);
|
||||
if (BN_is_bit_set (p.x, 0)) // highest bit
|
||||
buf[EDDSA25519_PUBLIC_KEY_LENGTH - 1] |= 0x80; // set highest bit
|
||||
}
|
||||
|
||||
BIGNUM * DecodeBN (const uint8_t * buf, size_t len) const
|
||||
{
|
||||
// buf is Little Endian convert it to Big Endian
|
||||
uint8_t buf1[len];
|
||||
for (size_t i = 0; i < len/2; i++) // invert bytes
|
||||
{
|
||||
buf1[i] = buf[len -1 - i];
|
||||
buf1[len -1 - i] = buf[i];
|
||||
}
|
||||
BIGNUM * res = BN_new ();
|
||||
BN_bin2bn (buf1, len, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
void EncodeBN (const BIGNUM * bn, uint8_t * buf, size_t len) const
|
||||
{
|
||||
bn2buf (bn, buf, len);
|
||||
// To Little Endian
|
||||
for (size_t i = 0; i < len/2; i++) // invert bytes
|
||||
{
|
||||
uint8_t tmp = buf[i];
|
||||
buf[i] = buf[len -1 - i];
|
||||
buf[len -1 - i] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
CryptoPP::Integer q, l, d, I;
|
||||
CryptoPP::ECP::Point B; // base point
|
||||
|
||||
BIGNUM * q, * l, * d, * I;
|
||||
EDDSAPoint B; // base point
|
||||
// transient values
|
||||
BIGNUM * q_2; // q-2
|
||||
BIGNUM * two_252_2; // 2^252-2
|
||||
EDDSAPoint Bi[256]; // m_Bi[i] = 2^i*B for i-th bit
|
||||
};
|
||||
|
||||
static std::unique_ptr<Ed25519> g_Ed25519;
|
||||
|
@ -98,22 +374,44 @@ namespace crypto
|
|||
if (!g_Ed25519)
|
||||
g_Ed25519.reset (new Ed25519 ());
|
||||
return g_Ed25519;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
EDDSA25519Verifier::EDDSA25519Verifier (const uint8_t * signingKey):
|
||||
m_PublicKey (GetEd25519 ()->DecodePublicKey (signingKey))
|
||||
EDDSA25519Verifier::EDDSA25519Verifier (const uint8_t * signingKey):
|
||||
m_Ctx (BN_CTX_new ()),
|
||||
m_PublicKey (GetEd25519 ()->DecodePublicKey (signingKey, m_Ctx))
|
||||
{
|
||||
memcpy (m_PublicKeyEncoded, signingKey, EDDSA25519_PUBLIC_KEY_LENGTH);
|
||||
}
|
||||
|
||||
bool EDDSA25519Verifier::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const
|
||||
{
|
||||
return true; // TODO:
|
||||
SHA512_CTX ctx;
|
||||
SHA512_Init (&ctx);
|
||||
SHA512_Update (&ctx, signature, EDDSA25519_SIGNATURE_LENGTH/2); // R
|
||||
SHA512_Update (&ctx, m_PublicKeyEncoded, EDDSA25519_PUBLIC_KEY_LENGTH); // public key
|
||||
SHA512_Update (&ctx, buf, len); // data
|
||||
uint8_t digest[64];
|
||||
SHA512_Final (digest, &ctx);
|
||||
return GetEd25519 ()->Verify (m_PublicKey, digest, signature, m_Ctx);
|
||||
}
|
||||
|
||||
void EDDSA25519Signer::Sign (CryptoPP::RandomNumberGenerator& rnd, const uint8_t * buf, int len, uint8_t * signature) const
|
||||
EDDSA25519Signer::EDDSA25519Signer (const uint8_t * signingPrivateKey):
|
||||
m_Ctx (BN_CTX_new ())
|
||||
{
|
||||
// expand key
|
||||
SHA512 (signingPrivateKey, EDDSA25519_PRIVATE_KEY_LENGTH, m_ExpandedPrivateKey);
|
||||
m_ExpandedPrivateKey[0] &= 0xF8; // drop last 3 bits
|
||||
m_ExpandedPrivateKey[EDDSA25519_PRIVATE_KEY_LENGTH - 1] &= 0x1F; // drop first 3 bits
|
||||
m_ExpandedPrivateKey[EDDSA25519_PRIVATE_KEY_LENGTH - 1] |= 0x40; // set second bit
|
||||
// generate and encode public key
|
||||
auto publicKey = GetEd25519 ()->GeneratePublicKey (m_ExpandedPrivateKey, m_Ctx);
|
||||
GetEd25519 ()->EncodePublicKey (publicKey, m_PublicKeyEncoded);
|
||||
}
|
||||
|
||||
void EDDSA25519Signer::Sign (const uint8_t * buf, int len, uint8_t * signature) const
|
||||
{
|
||||
// TODO
|
||||
GetEd25519 ()->Sign (m_ExpandedPrivateKey, m_PublicKeyEncoded, buf, len, signature, m_Ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue