Browse Source

removed own implementation of x25519

pull/2121/head
orignal 3 weeks ago
parent
commit
0d09a8be00
  1. 36
      libi2pd/Crypto.cpp
  2. 6
      libi2pd/Crypto.h
  3. 82
      libi2pd/Ed25519.cpp
  4. 12
      libi2pd/Ed25519.h
  5. 7
      tests/CMakeLists.txt
  6. 5
      tests/Makefile
  7. 38
      tests/test-x25519.cpp

36
libi2pd/Crypto.cpp

@ -240,17 +240,12 @@ namespace crypto
// x25519 // x25519
X25519Keys::X25519Keys () X25519Keys::X25519Keys ()
{ {
#if OPENSSL_X25519
m_Ctx = EVP_PKEY_CTX_new_id (NID_X25519, NULL); m_Ctx = EVP_PKEY_CTX_new_id (NID_X25519, NULL);
m_Pkey = nullptr; m_Pkey = nullptr;
#else
m_Ctx = BN_CTX_new ();
#endif
} }
X25519Keys::X25519Keys (const uint8_t * priv, const uint8_t * pub) X25519Keys::X25519Keys (const uint8_t * priv, const uint8_t * pub)
{ {
#if OPENSSL_X25519
m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_X25519, NULL, priv, 32); m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_X25519, NULL, priv, 32);
m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL); m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL);
if (pub) if (pub)
@ -260,29 +255,16 @@ namespace crypto
size_t len = 32; size_t len = 32;
EVP_PKEY_get_raw_public_key (m_Pkey, m_PublicKey, &len); EVP_PKEY_get_raw_public_key (m_Pkey, m_PublicKey, &len);
} }
#else
m_Ctx = BN_CTX_new ();
memcpy (m_PrivateKey, priv, 32);
if (pub)
memcpy (m_PublicKey, pub, 32);
else
GetEd25519 ()->ScalarMulB (m_PrivateKey, m_PublicKey, m_Ctx);
#endif
} }
X25519Keys::~X25519Keys () X25519Keys::~X25519Keys ()
{ {
#if OPENSSL_X25519
EVP_PKEY_CTX_free (m_Ctx); EVP_PKEY_CTX_free (m_Ctx);
if (m_Pkey) EVP_PKEY_free (m_Pkey); if (m_Pkey) EVP_PKEY_free (m_Pkey);
#else
BN_CTX_free (m_Ctx);
#endif
} }
void X25519Keys::GenerateKeys () void X25519Keys::GenerateKeys ()
{ {
#if OPENSSL_X25519
if (m_Pkey) if (m_Pkey)
{ {
EVP_PKEY_free (m_Pkey); EVP_PKEY_free (m_Pkey);
@ -294,16 +276,11 @@ namespace crypto
m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL); // TODO: do we really need to re-create m_Ctx? m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL); // TODO: do we really need to re-create m_Ctx?
size_t len = 32; size_t len = 32;
EVP_PKEY_get_raw_public_key (m_Pkey, m_PublicKey, &len); EVP_PKEY_get_raw_public_key (m_Pkey, m_PublicKey, &len);
#else
RAND_bytes (m_PrivateKey, 32);
GetEd25519 ()->ScalarMulB (m_PrivateKey, m_PublicKey, m_Ctx);
#endif
} }
bool X25519Keys::Agree (const uint8_t * pub, uint8_t * shared) bool X25519Keys::Agree (const uint8_t * pub, uint8_t * shared)
{ {
if (!pub || (pub[31] & 0x80)) return false; // not x25519 key if (!pub || (pub[31] & 0x80)) return false; // not x25519 key
#if OPENSSL_X25519
EVP_PKEY_derive_init (m_Ctx); EVP_PKEY_derive_init (m_Ctx);
auto pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_X25519, NULL, pub, 32); auto pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_X25519, NULL, pub, 32);
if (!pkey) return false; if (!pkey) return false;
@ -311,25 +288,17 @@ namespace crypto
size_t len = 32; size_t len = 32;
EVP_PKEY_derive (m_Ctx, shared, &len); EVP_PKEY_derive (m_Ctx, shared, &len);
EVP_PKEY_free (pkey); EVP_PKEY_free (pkey);
#else
GetEd25519 ()->ScalarMul (pub, m_PrivateKey, shared, m_Ctx);
#endif
return true; return true;
} }
void X25519Keys::GetPrivateKey (uint8_t * priv) const void X25519Keys::GetPrivateKey (uint8_t * priv) const
{ {
#if OPENSSL_X25519
size_t len = 32; size_t len = 32;
EVP_PKEY_get_raw_private_key (m_Pkey, priv, &len); EVP_PKEY_get_raw_private_key (m_Pkey, priv, &len);
#else
memcpy (priv, m_PrivateKey, 32);
#endif
} }
void X25519Keys::SetPrivateKey (const uint8_t * priv, bool calculatePublic) void X25519Keys::SetPrivateKey (const uint8_t * priv, bool calculatePublic)
{ {
#if OPENSSL_X25519
if (m_Ctx) EVP_PKEY_CTX_free (m_Ctx); if (m_Ctx) EVP_PKEY_CTX_free (m_Ctx);
if (m_Pkey) EVP_PKEY_free (m_Pkey); if (m_Pkey) EVP_PKEY_free (m_Pkey);
m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_X25519, NULL, priv, 32); m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_X25519, NULL, priv, 32);
@ -339,11 +308,6 @@ namespace crypto
size_t len = 32; size_t len = 32;
EVP_PKEY_get_raw_public_key (m_Pkey, m_PublicKey, &len); EVP_PKEY_get_raw_public_key (m_Pkey, m_PublicKey, &len);
} }
#else
memcpy (m_PrivateKey, priv, 32);
if (calculatePublic)
GetEd25519 ()->ScalarMulB (m_PrivateKey, m_PublicKey, m_Ctx);
#endif
} }
// ElGamal // ElGamal

6
libi2pd/Crypto.h

@ -31,7 +31,6 @@
#if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1 #if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1
# define OPENSSL_HKDF 1 # define OPENSSL_HKDF 1
# define OPENSSL_EDDSA 1 # define OPENSSL_EDDSA 1
# define OPENSSL_X25519 1
# if (!defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER != 0x030000000)) // 3.0.0, regression in SipHash, not implemented in LibreSSL # if (!defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER != 0x030000000)) // 3.0.0, regression in SipHash, not implemented in LibreSSL
# define OPENSSL_SIPHASH 1 # define OPENSSL_SIPHASH 1
# endif # endif
@ -70,13 +69,8 @@ namespace crypto
private: private:
uint8_t m_PublicKey[32]; uint8_t m_PublicKey[32];
#if OPENSSL_X25519
EVP_PKEY_CTX * m_Ctx; EVP_PKEY_CTX * m_Ctx;
EVP_PKEY * m_Pkey; EVP_PKEY * m_Pkey;
#else
BN_CTX * m_Ctx;
uint8_t m_PrivateKey[32];
#endif
bool m_IsElligatorIneligible = false; // true if definitely ineligible bool m_IsElligatorIneligible = false; // true if definitely ineligible
}; };

82
libi2pd/Ed25519.cpp

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2023, The PurpleI2P Project * Copyright (c) 2013-2024, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -457,86 +457,6 @@ namespace crypto
} }
} }
#if !OPENSSL_X25519
BIGNUM * Ed25519::ScalarMul (const BIGNUM * u, const BIGNUM * k, BN_CTX * ctx) const
{
BN_CTX_start (ctx);
auto x1 = BN_CTX_get (ctx); BN_copy (x1, u);
auto x2 = BN_CTX_get (ctx); BN_one (x2);
auto z2 = BN_CTX_get (ctx); BN_zero (z2);
auto x3 = BN_CTX_get (ctx); BN_copy (x3, u);
auto z3 = BN_CTX_get (ctx); BN_one (z3);
auto c121666 = BN_CTX_get (ctx); BN_set_word (c121666, 121666);
auto tmp0 = BN_CTX_get (ctx); auto tmp1 = BN_CTX_get (ctx);
unsigned int swap = 0;
auto bits = BN_num_bits (k);
while(bits)
{
--bits;
auto k_t = BN_is_bit_set(k, bits) ? 1 : 0;
swap ^= k_t;
if (swap)
{
std::swap (x2, x3);
std::swap (z2, z3);
}
swap = k_t;
BN_mod_sub(tmp0, x3, z3, q, ctx);
BN_mod_sub(tmp1, x2, z2, q, ctx);
BN_mod_add(x2, x2, z2, q, ctx);
BN_mod_add(z2, x3, z3, q, ctx);
BN_mod_mul(z3, tmp0, x2, q, ctx);
BN_mod_mul(z2, z2, tmp1, q, ctx);
BN_mod_sqr(tmp0, tmp1, q, ctx);
BN_mod_sqr(tmp1, x2, q, ctx);
BN_mod_add(x3, z3, z2, q, ctx);
BN_mod_sub(z2, z3, z2, q, ctx);
BN_mod_mul(x2, tmp1, tmp0, q, ctx);
BN_mod_sub(tmp1, tmp1, tmp0, q, ctx);
BN_mod_sqr(z2, z2, q, ctx);
BN_mod_mul(z3, tmp1, c121666, q, ctx);
BN_mod_sqr(x3, x3, q, ctx);
BN_mod_add(tmp0, tmp0, z3, q, ctx);
BN_mod_mul(z3, x1, z2, q, ctx);
BN_mod_mul(z2, tmp1, tmp0, q, ctx);
}
if (swap)
{
std::swap (x2, x3);
std::swap (z2, z3);
}
BN_mod_inverse (z2, z2, q, ctx);
BIGNUM * res = BN_new (); // not from ctx
BN_mod_mul(res, x2, z2, q, ctx);
BN_CTX_end (ctx);
return res;
}
void Ed25519::ScalarMul (const uint8_t * p, const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const
{
BIGNUM * p1 = DecodeBN<32> (p);
uint8_t k[32];
memcpy (k, e, 32);
k[0] &= 248; k[31] &= 127; k[31] |= 64;
BIGNUM * n = DecodeBN<32> (k);
BIGNUM * q1 = ScalarMul (p1, n, ctx);
EncodeBN (q1, buf, 32);
BN_free (p1); BN_free (n); BN_free (q1);
}
void Ed25519::ScalarMulB (const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const
{
BIGNUM *p1 = BN_new (); BN_set_word (p1, 9);
uint8_t k[32];
memcpy (k, e, 32);
k[0] &= 248; k[31] &= 127; k[31] |= 64;
BIGNUM * n = DecodeBN<32> (k);
BIGNUM * q1 = ScalarMul (p1, n, ctx);
EncodeBN (q1, buf, 32);
BN_free (p1); BN_free (n); BN_free (q1);
}
#endif
void Ed25519::BlindPublicKey (const uint8_t * pub, const uint8_t * seed, uint8_t * blinded) void Ed25519::BlindPublicKey (const uint8_t * pub, const uint8_t * seed, uint8_t * blinded)
{ {
BN_CTX * ctx = BN_CTX_new (); BN_CTX * ctx = BN_CTX_new ();

12
libi2pd/Ed25519.h

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2020, The PurpleI2P Project * Copyright (c) 2013-2024, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -84,10 +84,7 @@ namespace crypto
EDDSAPoint GeneratePublicKey (const uint8_t * expandedPrivateKey, BN_CTX * ctx) const; EDDSAPoint GeneratePublicKey (const uint8_t * expandedPrivateKey, BN_CTX * ctx) const;
EDDSAPoint DecodePublicKey (const uint8_t * buf, BN_CTX * ctx) const; EDDSAPoint DecodePublicKey (const uint8_t * buf, BN_CTX * ctx) const;
void EncodePublicKey (const EDDSAPoint& publicKey, uint8_t * buf, BN_CTX * ctx) const; void EncodePublicKey (const EDDSAPoint& publicKey, uint8_t * buf, BN_CTX * ctx) const;
#if !OPENSSL_X25519
void ScalarMul (const uint8_t * p, const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const; // p is point, e is number for x25519
void ScalarMulB (const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const;
#endif
void BlindPublicKey (const uint8_t * pub, const uint8_t * seed, uint8_t * blinded); // for encrypted LeaseSet2, pub - 32, seed - 64, blinded - 32 void BlindPublicKey (const uint8_t * pub, const uint8_t * seed, uint8_t * blinded); // for encrypted LeaseSet2, pub - 32, seed - 64, blinded - 32
void BlindPrivateKey (const uint8_t * priv, const uint8_t * seed, uint8_t * blindedPriv, uint8_t * blindedPub); // for encrypted LeaseSet2, pub - 32, seed - 64, blinded - 32 void BlindPrivateKey (const uint8_t * priv, const uint8_t * seed, uint8_t * blindedPriv, uint8_t * blindedPub); // for encrypted LeaseSet2, pub - 32, seed - 64, blinded - 32
@ -115,11 +112,6 @@ namespace crypto
BIGNUM * DecodeBN (const uint8_t * buf) const; BIGNUM * DecodeBN (const uint8_t * buf) const;
void EncodeBN (const BIGNUM * bn, uint8_t * buf, size_t len) const; void EncodeBN (const BIGNUM * bn, uint8_t * buf, size_t len) const;
#if !OPENSSL_X25519
// for x25519
BIGNUM * ScalarMul (const BIGNUM * p, const BIGNUM * e, BN_CTX * ctx) const;
#endif
private: private:
BIGNUM * q, * l, * d, * I; BIGNUM * q, * l, * d, * I;

7
tests/CMakeLists.txt

@ -49,10 +49,6 @@ set(test-gost-sig_SRCS
test-gost-sig.cpp test-gost-sig.cpp
) )
set(test-x25519_SRCS
test-x25519.cpp
)
set(test-aeadchacha20poly1305_SRCS set(test-aeadchacha20poly1305_SRCS
test-aeadchacha20poly1305.cpp test-aeadchacha20poly1305.cpp
) )
@ -77,7 +73,6 @@ add_executable(test-http-url ${test-http-url_SRCS})
add_executable(test-base-64 ${test-base-64_SRCS}) add_executable(test-base-64 ${test-base-64_SRCS})
add_executable(test-gost ${test-gost_SRCS}) add_executable(test-gost ${test-gost_SRCS})
add_executable(test-gost-sig ${test-gost-sig_SRCS}) add_executable(test-gost-sig ${test-gost-sig_SRCS})
add_executable(test-x25519 ${test-x25519_SRCS})
add_executable(test-aeadchacha20poly1305 ${test-aeadchacha20poly1305_SRCS}) add_executable(test-aeadchacha20poly1305 ${test-aeadchacha20poly1305_SRCS})
add_executable(test-blinding ${test-blinding_SRCS}) add_executable(test-blinding ${test-blinding_SRCS})
add_executable(test-elligator ${test-elligator_SRCS}) add_executable(test-elligator ${test-elligator_SRCS})
@ -102,7 +97,6 @@ target_link_libraries(test-http-url ${LIBS})
target_link_libraries(test-base-64 ${LIBS}) target_link_libraries(test-base-64 ${LIBS})
target_link_libraries(test-gost ${LIBS}) target_link_libraries(test-gost ${LIBS})
target_link_libraries(test-gost-sig ${LIBS}) target_link_libraries(test-gost-sig ${LIBS})
target_link_libraries(test-x25519 ${LIBS})
target_link_libraries(test-aeadchacha20poly1305 ${LIBS}) target_link_libraries(test-aeadchacha20poly1305 ${LIBS})
target_link_libraries(test-blinding ${LIBS}) target_link_libraries(test-blinding ${LIBS})
target_link_libraries(test-elligator ${LIBS}) target_link_libraries(test-elligator ${LIBS})
@ -116,7 +110,6 @@ add_test(test-http-url ${TEST_PATH}/test-http-url)
add_test(test-base-64 ${TEST_PATH}/test-base-64) add_test(test-base-64 ${TEST_PATH}/test-base-64)
add_test(test-gost ${TEST_PATH}/test-gost) add_test(test-gost ${TEST_PATH}/test-gost)
add_test(test-gost-sig ${TEST_PATH}/test-gost-sig) add_test(test-gost-sig ${TEST_PATH}/test-gost-sig)
add_test(test-x25519 ${TEST_PATH}/test-x25519)
add_test(test-aeadchacha20poly1305 ${TEST_PATH}/test-aeadchacha20poly1305) add_test(test-aeadchacha20poly1305 ${TEST_PATH}/test-aeadchacha20poly1305)
add_test(test-blinding ${TEST_PATH}/test-blinding) add_test(test-blinding ${TEST_PATH}/test-blinding)
add_test(test-elligator ${TEST_PATH}/test-elligator) add_test(test-elligator ${TEST_PATH}/test-elligator)

5
tests/Makefile

@ -7,7 +7,7 @@ LIBI2PD = ../libi2pd.a
TESTS = \ TESTS = \
test-http-merge_chunked test-http-req test-http-res test-http-url test-http-url_decode \ test-http-merge_chunked test-http-req test-http-res test-http-url test-http-url_decode \
test-gost test-gost-sig test-base-64 test-x25519 test-aeadchacha20poly1305 test-blinding \ test-gost test-gost-sig test-base-64 test-aeadchacha20poly1305 test-blinding \
test-elligator test-eddsa test-elligator test-eddsa
ifneq (, $(findstring mingw, $(SYS))$(findstring windows-gnu, $(SYS))$(findstring cygwin, $(SYS))) ifneq (, $(findstring mingw, $(SYS))$(findstring windows-gnu, $(SYS))$(findstring cygwin, $(SYS)))
@ -44,9 +44,6 @@ test-gost: test-gost.cpp $(LIBI2PD)
test-gost-sig: test-gost-sig.cpp $(LIBI2PD) test-gost-sig: test-gost-sig.cpp $(LIBI2PD)
$(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
test-x25519: test-x25519.cpp $(LIBI2PD)
$(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
test-aeadchacha20poly1305: test-aeadchacha20poly1305.cpp $(LIBI2PD) test-aeadchacha20poly1305: test-aeadchacha20poly1305.cpp $(LIBI2PD)
$(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)

38
tests/test-x25519.cpp

@ -1,38 +0,0 @@
#include <cassert>
#include <inttypes.h>
#include <string.h>
#include "Ed25519.h"
const uint8_t k[32] =
{
0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d, 0x3b, 0x16, 0x15,
0x4b, 0x82, 0x46, 0x5e, 0xdd, 0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc,
0x5a, 0x18, 0x50, 0x6a, 0x22, 0x44, 0xba, 0x44, 0x9a, 0xc4
};
const uint8_t u[32] =
{
0xe6, 0xdb, 0x68, 0x67, 0x58, 0x30, 0x30, 0xdb, 0x35, 0x94, 0xc1,
0xa4, 0x24, 0xb1, 0x5f, 0x7c, 0x72, 0x66, 0x24, 0xec, 0x26, 0xb3,
0x35, 0x3b, 0x10, 0xa9, 0x03, 0xa6, 0xd0, 0xab, 0x1c, 0x4c
};
uint8_t p[32] =
{
0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90, 0x8e, 0x94, 0xea,
0x4d, 0xf2, 0x8d, 0x08, 0x4f, 0x32, 0xec, 0xcf, 0x03, 0x49, 0x1c,
0x71, 0xf7, 0x54, 0xb4, 0x07, 0x55, 0x77, 0xa2, 0x85, 0x52
};
int main ()
{
#if !OPENSSL_X25519
// we test it for openssl < 1.1.0
uint8_t buf[32];
BN_CTX * ctx = BN_CTX_new ();
i2p::crypto::GetEd25519 ()->ScalarMul (u, k, buf, ctx);
BN_CTX_free (ctx);
assert(memcmp (buf, p, 32) == 0);
#endif
}
Loading…
Cancel
Save