diff --git a/libi2pd/Ed25519.cpp b/libi2pd/Ed25519.cpp index 2c64c475..4e631291 100644 --- a/libi2pd/Ed25519.cpp +++ b/libi2pd/Ed25519.cpp @@ -491,6 +491,21 @@ namespace crypto } #endif + void Ed25519::BlindPublicKey (const uint8_t * pub, const uint8_t * seed, uint8_t * blinded) + { + BN_CTX * ctx = BN_CTX_new (); + // calculate alpha = seed mod l + BIGNUM * alpha = DecodeBN<64> (seed); // pub is in Little Endian + BN_mod (alpha, alpha, l, ctx); // % l + uint8_t priv[32]; + EncodeBN (alpha, priv, 32); // back to Little Endian + BN_free (alpha); + // A' = BLIND_PUBKEY(A, alpha) = A + DERIVE_PUBLIC(alpha) + auto A1 = Sum (DecodePublicKey (pub, ctx), MulB (priv, ctx), ctx); // pub + B*alpha + EncodePublicKey (A1, blinded, ctx); + BN_CTX_free (ctx); + } + void Ed25519::ExpandPrivateKey (const uint8_t * key, uint8_t * expandedKey) { SHA512 (key, EDDSA25519_PRIVATE_KEY_LENGTH, expandedKey); diff --git a/libi2pd/Ed25519.h b/libi2pd/Ed25519.h index 48b3a665..18f749ea 100644 --- a/libi2pd/Ed25519.h +++ b/libi2pd/Ed25519.h @@ -80,6 +80,7 @@ namespace crypto 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 bool Verify (const EDDSAPoint& publicKey, const uint8_t * digest, const uint8_t * signature) const; void Sign (const uint8_t * expandedPrivateKey, const uint8_t * publicKeyEncoded, const uint8_t * buf, size_t len, uint8_t * signature) const; diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index 63b09337..24578988 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -3,6 +3,7 @@ #include #include "I2PEndian.h" #include "Crypto.h" +#include "Ed25519.h" #include "Log.h" #include "Timestamp.h" #include "NetDb.hpp" @@ -532,6 +533,16 @@ namespace data HMAC(EVP_sha256(), prk, 32, out, 41, out + 32, &len); } + void LeaseSet2::BlindPublicKey (std::shared_ptr identity, const char * date, SigningKeyType blindedKeyType, uint8_t * blindedKey) + { + uint16_t stA = htobe16 (identity->GetSigningKeyType ()), stA1 = htobe16 (blindedKeyType); + uint8_t salt[32], seed[64]; + //seed = HKDF(H("I2PGenerateAlpha", keydata), datestring || secret, "i2pblinding1", 64) + H ("I2PGenerateAlpha", { {identity->GetSigningPublicKeyBuffer (), identity->GetSigningPublicKeyLen ()}, {(const uint8_t *)&stA, 2}, {(const uint8_t *)&stA1, 2} }, salt); + HKDF (salt, { (const uint8_t *)date, 8 }, "i2pblinding1", seed); + i2p::crypto::GetEd25519 ()->BlindPublicKey (identity->GetSigningPublicKeyBuffer (), seed, blindedKey); + } + void LeaseSet2::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const { auto encryptor = m_Encryptor; // TODO: atomic diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index 84988a65..985517d9 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -155,8 +155,9 @@ namespace data uint64_t ExtractTimestamp (const uint8_t * buf, size_t len) const; // for encrypted LS - void H (const std::string& p, const std::vector >& bufs, uint8_t * hash); - void HKDF (const uint8_t * salt, const std::pair& ikm, const std::string& info, uint8_t * out); // salt - 32, out - 64, info <= 32 + static void H (const std::string& p, const std::vector >& bufs, uint8_t * hash); + static void HKDF (const uint8_t * salt, const std::pair& ikm, const std::string& info, uint8_t * out); // salt - 32, out - 64, info <= 32 + static void BlindPublicKey (std::shared_ptr identity, const char * date, SigningKeyType blindedKeyType, uint8_t * blindedKey); // blinded key 32 bytes, date is 8 chars "YYYYMMDD" private: