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 }