From 1fa3ba8b42af81fb76dfeba65b3375143fc3483e Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 7 Feb 2019 16:04:31 -0500 Subject: [PATCH] read offline info --- libi2pd/Identity.cpp | 58 +++++++++++++++++++++++++++++++++++++++++--- libi2pd/Identity.h | 11 ++++++--- 2 files changed, 63 insertions(+), 6 deletions(-) diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index 02658ecc..4170fd5a 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -455,11 +455,49 @@ namespace data memcpy (m_PrivateKey, buf + ret, 256); // private key always 256 ret += 256; size_t signingPrivateKeySize = m_Public->GetSigningPrivateKeyLen (); - if(signingPrivateKeySize + ret > len) return 0; // overflow + if(signingPrivateKeySize + ret > len || signingPrivateKeySize > 128) return 0; // overflow memcpy (m_SigningPrivateKey, buf + ret, signingPrivateKeySize); ret += signingPrivateKeySize; m_Signer = nullptr; - CreateSigner (); + // check if signing private key is all zeros + bool allzeros = true; + for (size_t i = 0; i < signingPrivateKeySize; i++) + if (m_SigningPrivateKey[i]) + { + allzeros = false; + break; + } + if (allzeros) + { + // offline information + const uint8_t * offlineInfo = buf + ret; + ret += 4; // expires timestamp + SigningKeyType keyType = bufbe16toh (buf + ret); ret += 2; // key type + std::unique_ptr transientVerifier (IdentityEx::CreateVerifier (keyType)); + if (!transientVerifier) return 0; + auto keyLen = transientVerifier->GetPublicKeyLen (); + if (keyLen + ret > len) return 0; + transientVerifier->SetPublicKey (buf + ret); ret += keyLen; + if (m_Public->GetSignatureLen () + ret > len) return 0; + if (!m_Public->Verify (offlineInfo, keyLen + 6, buf + ret)) + { + LogPrint (eLogError, "Identity: offline signature verification failed"); + return 0; + } + ret += m_Public->GetSignatureLen (); + // copy offline signature + size_t offlineInfoLen = buf + ret - offlineInfo; + m_OfflineSignature.resize (offlineInfoLen); + memcpy (m_OfflineSignature.data (), offlineInfo, offlineInfoLen); + // override signing private key + signingPrivateKeySize = transientVerifier->GetPrivateKeyLen (); + if (signingPrivateKeySize + ret > len || signingPrivateKeySize > 128) return 0; + memcpy (m_SigningPrivateKey, buf + ret, signingPrivateKeySize); + ret += signingPrivateKeySize; + CreateSigner (keyType); + } + else + CreateSigner (m_Public->GetSigningKeyType ()); return ret; } @@ -472,6 +510,7 @@ namespace data if(ret + signingPrivateKeySize > len) return 0; // overflow memcpy (buf + ret, m_SigningPrivateKey, signingPrivateKeySize); ret += signingPrivateKeySize; + // TODO: implement offline info return ret; } @@ -505,9 +544,17 @@ namespace data } void PrivateKeys::CreateSigner () const + { + if (IsOfflineSignature ()) + CreateSigner (bufbe16toh (m_OfflineSignature.data () + 4)); // key type + else + CreateSigner (m_Public->GetSigningKeyType ()); + } + + void PrivateKeys::CreateSigner (SigningKeyType keyType) const { if (m_Signer) return; - switch (m_Public->GetSigningKeyType ()) + switch (keyType) { case SIGNING_KEY_TYPE_DSA_SHA1: m_Signer.reset (new i2p::crypto::DSASigner (m_SigningPrivateKey, m_Public->GetStandardIdentity ().signingKey)); @@ -540,6 +587,11 @@ namespace data } } + size_t PrivateKeys::GetSignatureLen () const + { + return m_Public->GetSignatureLen (); + } + uint8_t * PrivateKeys::GetPadding() { if(m_Public->GetSigningKeyType () == SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519) diff --git a/libi2pd/Identity.h b/libi2pd/Identity.h index 2a91ef48..1c04916d 100644 --- a/libi2pd/Identity.h +++ b/libi2pd/Identity.h @@ -6,6 +6,7 @@ #include #include #include +#include #include "Base.h" #include "Signature.h" #include "CryptoKey.h" @@ -142,8 +143,10 @@ namespace data std::shared_ptr GetPublic () const { return m_Public; }; const uint8_t * GetPrivateKey () const { return m_PrivateKey; }; const uint8_t * GetSigningPrivateKey () const { return m_SigningPrivateKey; }; - uint8_t * GetPadding(); - void RecalculateIdentHash(uint8_t * buf=nullptr) { m_Public->RecalculateIdentHash(buf); } + size_t GetSignatureLen () const; // might not match identity + bool IsOfflineSignature () const { return m_OfflineSignature.size () > 0; }; + uint8_t * GetPadding(); + void RecalculateIdentHash(uint8_t * buf=nullptr) { m_Public->RecalculateIdentHash(buf); } void Sign (const uint8_t * buf, int len, uint8_t * signature) const; size_t GetFullLen () const { return m_Public->GetFullLen () + 256 + m_Public->GetSigningPrivateKeyLen (); }; @@ -162,13 +165,15 @@ namespace data private: void CreateSigner () const; + void CreateSigner (SigningKeyType keyType) const; private: std::shared_ptr m_Public; uint8_t m_PrivateKey[256]; - uint8_t m_SigningPrivateKey[1024]; // assume private key doesn't exceed 1024 bytes + uint8_t m_SigningPrivateKey[128]; // assume private key doesn't exceed 128 bytes mutable std::unique_ptr m_Signer; + std::vector m_OfflineSignature; // non zero length, if applicable }; // kademlia