/ libi2pd / Blinding.cpp
Blinding.cpp
  1  /*
  2  * Copyright (c) 2013-2025, The PurpleI2P Project
  3  *
  4  * This file is part of Purple i2pd project and licensed under BSD3
  5  *
  6  * See full license text in LICENSE file at top of project tree
  7  */
  8  
  9  #include <cstdint>
 10  #include <zlib.h> // for crc32
 11  #include <openssl/sha.h>
 12  #include <openssl/hmac.h>
 13  #include <openssl/ec.h>
 14  #include <openssl/evp.h>
 15  #include <openssl/bn.h>
 16  #include "Base.h"
 17  #include "Crypto.h"
 18  #include "Log.h"
 19  #include "Timestamp.h"
 20  #include "I2PEndian.h"
 21  #include "Ed25519.h"
 22  #include "Signature.h"
 23  #include "Blinding.h"
 24  
 25  namespace i2p
 26  {
 27  namespace data
 28  {
 29  	static EC_POINT * BlindPublicKeyECDSA (const EC_GROUP * group, const EC_POINT * pub, const uint8_t * seed)
 30  	{
 31  		BN_CTX * ctx = BN_CTX_new ();
 32  		BN_CTX_start (ctx);
 33  		BIGNUM * q = BN_CTX_get (ctx);
 34  		EC_GROUP_get_order (group, q, ctx);
 35  		// calculate alpha = seed mod q
 36  		BIGNUM * alpha = BN_CTX_get (ctx);
 37  		BN_bin2bn (seed, 64, alpha); // seed is in BigEndian
 38  		BN_mod (alpha, alpha, q, ctx); // % q
 39  		// A' = BLIND_PUBKEY(A, alpha) = A + DERIVE_PUBLIC(alpha)
 40  		auto p = EC_POINT_new (group);
 41  		EC_POINT_mul (group, p, alpha, nullptr, nullptr, ctx); // B*alpha
 42  		EC_POINT_add (group, p, pub, p, ctx); // pub + B*alpha
 43  		BN_CTX_end (ctx);
 44  		BN_CTX_free (ctx);
 45  		return p;
 46  	}
 47  
 48  	static void BlindPrivateKeyECDSA (const EC_GROUP * group, const BIGNUM * priv, const uint8_t * seed, BIGNUM * blindedPriv)
 49  	{
 50  		BN_CTX * ctx = BN_CTX_new ();
 51  		BN_CTX_start (ctx);
 52  		BIGNUM * q = BN_CTX_get (ctx);
 53  		EC_GROUP_get_order (group, q, ctx);
 54  		// calculate alpha = seed mod q
 55  		BIGNUM * alpha = BN_CTX_get (ctx);
 56  		BN_bin2bn (seed, 64, alpha); // seed is in BigEndian
 57  		BN_mod (alpha, alpha, q, ctx); // % q
 58  		BN_add (alpha, alpha, priv); // alpha = alpha + priv
 59  		// a' = BLIND_PRIVKEY(a, alpha) = (a + alpha) mod q
 60  		BN_mod (blindedPriv, alpha, q, ctx); // % q
 61  		BN_CTX_end (ctx);
 62  		BN_CTX_free (ctx);
 63  	}
 64  
 65  	static void BlindEncodedPublicKeyECDSA (size_t publicKeyLen, const EC_GROUP * group, const uint8_t * pub, const uint8_t * seed, uint8_t * blindedPub)
 66  	{
 67  		BIGNUM * x = BN_bin2bn (pub, publicKeyLen/2, NULL);
 68  		BIGNUM * y = BN_bin2bn (pub + publicKeyLen/2, publicKeyLen/2, NULL);
 69  		EC_POINT * p = EC_POINT_new (group);
 70  		EC_POINT_set_affine_coordinates (group, p, x, y, NULL);
 71  		EC_POINT * p1 = BlindPublicKeyECDSA (group, p, seed);
 72  		EC_POINT_free (p);
 73  		EC_POINT_get_affine_coordinates (group, p1, x, y, NULL);
 74  		EC_POINT_free (p1);
 75  		i2p::crypto::bn2buf (x, blindedPub, publicKeyLen/2);
 76  		i2p::crypto::bn2buf (y, blindedPub + publicKeyLen/2, publicKeyLen/2);
 77  		BN_free (x); BN_free (y);
 78  	}
 79  
 80  	static void BlindEncodedPrivateKeyECDSA (size_t publicKeyLen, const EC_GROUP * group, const uint8_t * priv, const uint8_t * seed, uint8_t * blindedPriv, uint8_t * blindedPub)
 81  	{
 82  		BIGNUM * a = BN_bin2bn (priv, publicKeyLen/2, NULL);
 83  		BIGNUM * a1 = BN_new ();
 84  		BlindPrivateKeyECDSA (group, a, seed, a1);
 85  		BN_free (a);
 86  		i2p::crypto::bn2buf (a1, blindedPriv, publicKeyLen/2);
 87  		auto p = EC_POINT_new (group);
 88  		BN_CTX * ctx = BN_CTX_new ();
 89  		EC_POINT_mul (group, p, a1, nullptr, nullptr, ctx); // B*a1
 90  		BN_CTX_free (ctx);
 91  		BN_free (a1);
 92  		BIGNUM * x = BN_new(), * y = BN_new();
 93  		EC_POINT_get_affine_coordinates (group, p, x, y, NULL);
 94  		EC_POINT_free (p);
 95  		i2p::crypto::bn2buf (x, blindedPub, publicKeyLen/2);
 96  		i2p::crypto::bn2buf (y, blindedPub + publicKeyLen/2, publicKeyLen/2);
 97  		BN_free (x); BN_free (y);
 98  	}
 99  
100  	template<typename Fn, typename...Args>
101  	static size_t BlindECDSA (i2p::data::SigningKeyType sigType, const uint8_t * key, const uint8_t * seed, Fn blind, Args&&...args)
102  	// blind is BlindEncodedPublicKeyECDSA or BlindEncodedPrivateKeyECDSA
103  	{
104  		size_t publicKeyLength = 0;
105  		EC_GROUP * group = nullptr;
106  		switch (sigType)
107  		{
108  			case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256:
109  			{
110  				publicKeyLength = i2p::crypto::ECDSAP256_KEY_LENGTH;
111  				group = EC_GROUP_new_by_curve_name (NID_X9_62_prime256v1);
112  				break;
113  			}
114  			case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA384_P384:
115  			{
116  				publicKeyLength = i2p::crypto::ECDSAP384_KEY_LENGTH;
117  				group = EC_GROUP_new_by_curve_name (NID_secp384r1);
118  				break;
119  			}
120  			case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA512_P521:
121  			{
122  				publicKeyLength = i2p::crypto::ECDSAP521_KEY_LENGTH;
123  				group = EC_GROUP_new_by_curve_name (NID_secp521r1);
124  				break;
125  			}
126  			default:
127  				LogPrint (eLogError, "Blinding: Signature type ", (int)sigType, " is not ECDSA");
128  		}
129  		if (group)
130  		{
131  			blind (publicKeyLength, group, key, seed, std::forward<Args>(args)...);
132  			EC_GROUP_free (group);
133  		}
134  		return publicKeyLength;
135  	}
136  
137  //----------------------------------------------------------
138  
139  	const uint8_t B33_TWO_BYTES_SIGTYPE_FLAG = 0x01;
140  	// const uint8_t B33_PER_SECRET_FLAG = 0x02; // not used for now
141  	const uint8_t B33_PER_CLIENT_AUTH_FLAG = 0x04;
142  
143  	BlindedPublicKey::BlindedPublicKey (std::shared_ptr<const IdentityEx> identity, bool clientAuth):
144  		m_IsClientAuth (clientAuth)
145  	{
146  		if (!identity) return;
147  		auto len = identity->GetSigningPublicKeyLen ();
148  		m_PublicKey.resize (len);
149  		memcpy (m_PublicKey.data (), identity->GetSigningPublicKeyBuffer (), len);
150  		m_SigType = identity->GetSigningKeyType ();
151  		if (m_SigType == i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519)
152  			m_BlindedSigType = i2p::data::SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519; // 7 -> 11
153  		else
154  			m_BlindedSigType = m_SigType;
155  	}
156  
157  	BlindedPublicKey::BlindedPublicKey (std::string_view b33):
158  		m_SigType (0) // 0 means invalid, we can't blind DSA, set it later
159  	{
160  		uint8_t addr[40]; // TODO: define length from b33
161  		size_t l = i2p::data::Base32ToByteStream (b33, addr, 40);
162  		if (l < 32)
163  		{
164  			LogPrint (eLogError, "Blinding: Malformed b33 ", b33);
165  			return;
166  		}
167  		uint32_t checksum = crc32 (0, addr + 3, l - 3);
168  		// checksum is Little Endian
169  		addr[0] ^= checksum; addr[1] ^= (checksum >> 8); addr[2] ^= (checksum >> 16);
170  		uint8_t flags = addr[0];
171  		size_t offset = 1;
172  		if (flags & B33_TWO_BYTES_SIGTYPE_FLAG) // two bytes signatures
173  		{
174  			m_SigType = bufbe16toh (addr + offset); offset += 2;
175  			m_BlindedSigType = bufbe16toh (addr + offset); offset += 2;
176  		}
177  		else // one byte sig
178  		{
179  			m_SigType = addr[offset]; offset++;
180  			m_BlindedSigType = addr[offset]; offset++;
181  		}
182  		m_IsClientAuth = flags & B33_PER_CLIENT_AUTH_FLAG;
183  
184  		std::unique_ptr<i2p::crypto::Verifier> blindedVerifier (i2p::data::IdentityEx::CreateVerifier (m_SigType));
185  		if (blindedVerifier)
186  		{
187  			auto len = blindedVerifier->GetPublicKeyLen ();
188  			if (offset + len <= l)
189  			{
190  				m_PublicKey.resize (len);
191  				memcpy (m_PublicKey.data (), addr + offset, len);
192  			}
193  			else
194  				LogPrint (eLogError, "Blinding: Public key in b33 address is too short for signature type ", (int)m_SigType);
195  		}
196  		else
197  			LogPrint (eLogError, "Blinding: Unknown signature type ", (int)m_SigType, " in b33");
198  	}
199  
200  	std::string BlindedPublicKey::ToB33 () const
201  	{
202  		if (m_PublicKey.size () > 32) return ""; // assume 25519
203  		uint8_t addr[35];
204  		uint8_t flags = 0;
205  		if (m_IsClientAuth) flags |= B33_PER_CLIENT_AUTH_FLAG;
206  		addr[0] = flags; // flags
207  		addr[1] = m_SigType; // sig type
208  		addr[2] = m_BlindedSigType; // blinded sig type
209  		memcpy (addr + 3, m_PublicKey.data (), m_PublicKey.size ());
210  		uint32_t checksum = crc32 (0, addr + 3, m_PublicKey.size ());
211  		// checksum is Little Endian
212  		addr[0] ^= checksum; addr[1] ^= (checksum >> 8); addr[2] ^= (checksum >> 16);
213  		return ByteStreamToBase32 (addr, m_PublicKey.size () + 3);
214  	}
215  
216  	void BlindedPublicKey::GetCredential (uint8_t * credential) const
217  	{
218  		// A = destination's signing public key
219  		// stA = signature type of A, 2 bytes big endian
220  		uint16_t stA = htobe16 (GetSigType ());
221  		// stA1 = signature type of blinded A, 2 bytes big endian
222  		uint16_t stA1 = htobe16 (GetBlindedSigType ());
223  		// credential = H("credential", A || stA || stA1)
224  		H ("credential", { {GetPublicKey (), GetPublicKeyLen ()}, {(const uint8_t *)&stA, 2}, {(const uint8_t *)&stA1, 2} }, credential);
225  	}
226  
227  	void BlindedPublicKey::GetSubcredential (const uint8_t * blinded, size_t len, uint8_t * subcredential) const
228  	{
229  		uint8_t credential[32];
230  		GetCredential (credential);
231  		// subcredential = H("subcredential", credential || blindedPublicKey)
232  		H ("subcredential", { {credential, 32}, {blinded, len} }, subcredential);
233  	}
234  
235  	void BlindedPublicKey::GenerateAlpha (const char * date, uint8_t * seed) const
236  	{
237  		uint16_t stA = htobe16 (GetSigType ()), stA1 = htobe16 (GetBlindedSigType ());
238  		uint8_t salt[32];
239  		//seed = HKDF(H("I2PGenerateAlpha", keydata), datestring || secret, "i2pblinding1", 64)
240  		H ("I2PGenerateAlpha", { {GetPublicKey (), GetPublicKeyLen ()}, {(const uint8_t *)&stA, 2}, {(const uint8_t *)&stA1, 2} }, salt);
241  		i2p::crypto::HKDF (salt, (const uint8_t *)date, 8, "i2pblinding1", seed);
242  	}
243  
244  	size_t BlindedPublicKey::GetBlindedKey (const char * date, uint8_t * blindedKey) const
245  	{
246  		uint8_t seed[64];
247  		GenerateAlpha (date, seed);
248  
249  		size_t publicKeyLength = 0;
250  		switch (m_SigType)
251  		{
252  			case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256:
253  			case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA384_P384:
254  			case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA512_P521:
255  				publicKeyLength = BlindECDSA (m_SigType, GetPublicKey (), seed, BlindEncodedPublicKeyECDSA, blindedKey);
256  			break;
257  			case i2p::data::SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
258  			case i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
259  				i2p::crypto::GetEd25519 ()->BlindPublicKey (GetPublicKey (), seed, blindedKey);
260  				publicKeyLength = i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH;
261  			break;
262  			default:
263  				LogPrint (eLogError, "Blinding: Can't blind signature type ", (int)m_SigType);
264  		}
265  		return publicKeyLength;
266  	}
267  
268  	size_t BlindedPublicKey::BlindPrivateKey (const uint8_t * priv, const char * date, uint8_t * blindedPriv, uint8_t * blindedPub) const
269  	{
270  		uint8_t seed[64];
271  		GenerateAlpha (date, seed);
272  		size_t publicKeyLength = 0;
273  		switch (m_SigType)
274  		{
275  			case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256:
276  			case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA384_P384:
277  			case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA512_P521:
278  				publicKeyLength = BlindECDSA (m_SigType, priv, seed, BlindEncodedPrivateKeyECDSA, blindedPriv, blindedPub);
279  			break;
280  			case i2p::data::SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
281  				i2p::crypto::GetEd25519 ()->BlindPrivateKey (priv, seed, blindedPriv, blindedPub);
282  				publicKeyLength = i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH;
283  			break;
284  			case i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
285  			{
286  				uint8_t exp[64];
287  				i2p::crypto::Ed25519::ExpandPrivateKey (priv, exp);
288  				i2p::crypto::GetEd25519 ()->BlindPrivateKey (exp, seed, blindedPriv, blindedPub);
289  				publicKeyLength = i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH;
290  				break;
291  			}
292  			default:
293  				LogPrint (eLogError, "Blinding: Can't blind signature type ", (int)m_SigType);
294  		}
295  		return publicKeyLength;
296  	}
297  
298  	void BlindedPublicKey::H (const std::string& p, const std::vector<std::pair<const uint8_t *, size_t> >& bufs, uint8_t * hash) const
299  	{
300  		EVP_MD_CTX *ctx = EVP_MD_CTX_new ();
301  
302  		EVP_DigestInit_ex(ctx, EVP_sha256 (), NULL);
303  		EVP_DigestUpdate (ctx, p.c_str (), p.length ());
304  		for (const auto& it: bufs)
305  			EVP_DigestUpdate (ctx, it.first, it.second);
306  		EVP_DigestFinal_ex (ctx, (uint8_t * )hash, nullptr);
307  		EVP_MD_CTX_free (ctx);
308  	}
309  
310  	i2p::data::IdentHash BlindedPublicKey::GetStoreHash (const char * date) const
311  	{
312  		i2p::data::IdentHash hash;
313  		uint8_t blinded[128];
314  		size_t publicKeyLength = 0;
315  		if (date)
316  			publicKeyLength = GetBlindedKey (date, blinded);
317  		else
318  		{
319  			char currentDate[9];
320  			i2p::util::GetCurrentDate (currentDate);
321  			publicKeyLength = GetBlindedKey (currentDate, blinded);
322  		}
323  		if (publicKeyLength)
324  		{
325  			auto stA1 = htobe16 (m_BlindedSigType);
326  			EVP_MD_CTX *ctx = EVP_MD_CTX_new ();
327  			EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
328  			EVP_DigestUpdate (ctx, (const uint8_t *)&stA1, 2);
329  			EVP_DigestUpdate (ctx, blinded, publicKeyLength);
330  			EVP_DigestFinal_ex (ctx, (uint8_t * )hash, nullptr);
331  			EVP_MD_CTX_free(ctx);
332  		}
333  		else
334  			LogPrint (eLogError, "Blinding: Blinded key type ", (int)m_BlindedSigType, " is not supported");
335  		return hash;
336  	}
337  
338  }
339  }