From b7f17d4cb1567286452baa62a25533d37a8eb7ae Mon Sep 17 00:00:00 2001
From: orignal <i2porignal@yandex.ru>
Date: Fri, 6 Sep 2019 11:02:19 -0400
Subject: [PATCH] client auth flag for B33 address

---
 daemon/HTTPServer.cpp   |  2 +-
 libi2pd/Blinding.cpp    | 18 ++++++++++++++----
 libi2pd/Blinding.h      |  3 ++-
 libi2pd/Destination.cpp | 35 ++++++++++++++++++++++-------------
 libi2pd/Destination.h   |  7 ++++---
 5 files changed, 43 insertions(+), 22 deletions(-)

diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp
index 38b53ff3..7dc6a9d2 100644
--- a/daemon/HTTPServer.cpp
+++ b/daemon/HTTPServer.cpp
@@ -356,7 +356,7 @@ namespace http {
 		s << dest->GetIdentity ()->ToBase64 () << "</textarea><br>\r\n<br>\r\n";
 		if (dest->IsEncryptedLeaseSet ())
 		{
-			i2p::data::BlindedPublicKey blinded (dest->GetIdentity ());
+			i2p::data::BlindedPublicKey blinded (dest->GetIdentity (), dest->IsPerClientAuth ());
 			s << "<div class='slide'><label for='slide-b33'><b>Encrypted B33 address:</b></label>\r\n<input type='checkbox' id='slide-b33'/>\r\n<p class='content'>\r\n";
 			s << blinded.ToB33 () << ".b32.i2p<br>\r\n";
 			s << "</p>\r\n</div>\r\n";
diff --git a/libi2pd/Blinding.cpp b/libi2pd/Blinding.cpp
index e51c0fcc..6bf11c9e 100644
--- a/libi2pd/Blinding.cpp
+++ b/libi2pd/Blinding.cpp
@@ -124,8 +124,14 @@ namespace data
 		return publicKeyLength;
 	}
 
+//----------------------------------------------------------
 
-	BlindedPublicKey::BlindedPublicKey (std::shared_ptr<const IdentityEx> identity)
+	const uint8_t B33_TWO_BYTES_SIGTYPE_FLAG = 0x01;
+	const uint8_t B33_PER_SECRET_FLAG = 0x02; // not used for now	
+	const uint8_t B33_PER_CLIENT_AUTH_FLAG = 0x04;
+
+	BlindedPublicKey::BlindedPublicKey (std::shared_ptr<const IdentityEx> identity, bool clientAuth):
+		m_IsClientAuth (clientAuth)
 	{
 		if (!identity) return;
 		auto len = identity->GetSigningPublicKeyLen ();
@@ -147,9 +153,9 @@ namespace data
 		uint32_t checksum = crc32 (0, addr + 3, l - 3); 
 		// checksum is Little Endian
 		addr[0] ^= checksum; addr[1] ^= (checksum >> 8); addr[2] ^= (checksum >> 16);  
-		uint8_t flag = addr[0];
+		uint8_t flags = addr[0];
 		size_t offset = 1;	
-		if (flag & 0x01) // two bytes signatures
+		if (flags & B33_TWO_BYTES_SIGTYPE_FLAG) // two bytes signatures
 		{
 			m_SigType = bufbe16toh (addr + offset); offset += 2;
 			m_BlindedSigType = bufbe16toh (addr + offset); offset += 2;
@@ -159,6 +165,8 @@ namespace data
 			m_SigType = addr[offset]; offset++;
 			m_BlindedSigType = addr[offset]; offset++;
 		}
+		m_IsClientAuth = flags & B33_PER_CLIENT_AUTH_FLAG;
+
 		std::unique_ptr<i2p::crypto::Verifier> blindedVerifier (i2p::data::IdentityEx::CreateVerifier (m_SigType));
 		if (blindedVerifier)
 		{
@@ -179,7 +187,9 @@ namespace data
 	{
 		if (m_PublicKey.size () > 32) return ""; // assume 25519
 		uint8_t addr[35]; char str[60]; // TODO: define actual length
-		addr[0] = 0; // flags
+		uint8_t flags = 0;
+		if (m_IsClientAuth) flags |= B33_PER_CLIENT_AUTH_FLAG;		
+		addr[0] = flags; // flags
 		addr[1] = m_SigType; // sig type
 		addr[2] = m_BlindedSigType; // blinded sig type
 		memcpy (addr + 3, m_PublicKey.data (), m_PublicKey.size ());
diff --git a/libi2pd/Blinding.h b/libi2pd/Blinding.h
index 9a3fe633..9d274fd0 100644
--- a/libi2pd/Blinding.h
+++ b/libi2pd/Blinding.h
@@ -14,7 +14,7 @@ namespace data
 	{
 		public:
 
-			BlindedPublicKey (std::shared_ptr<const IdentityEx> identity);
+			BlindedPublicKey (std::shared_ptr<const IdentityEx> identity, bool clientAuth = false);
 			BlindedPublicKey (const std::string& b33); // from b33 without .b32.i2p			
 			std::string ToB33 () const;
 
@@ -38,6 +38,7 @@ namespace data
 
 			std::vector<uint8_t> m_PublicKey;
 			i2p::data::SigningKeyType m_SigType, m_BlindedSigType;
+			bool m_IsClientAuth = false;
 	};
 }
 }
diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp
index 34ff374f..ca60f0fb 100644
--- a/libi2pd/Destination.cpp
+++ b/libi2pd/Destination.cpp
@@ -17,7 +17,7 @@ namespace client
 		m_IsRunning (false), m_Thread (nullptr), m_IsPublic (isPublic),
 		m_PublishReplyToken (0), m_LastSubmissionTime (0), m_PublishConfirmationTimer (m_Service),
 		m_PublishVerificationTimer (m_Service), m_PublishDelayTimer (m_Service), m_CleanupTimer (m_Service),
-		m_LeaseSetType (DEFAULT_LEASESET_TYPE)
+		m_LeaseSetType (DEFAULT_LEASESET_TYPE), m_AuthType (i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_NONE)
 	{
 		int inLen   = DEFAULT_INBOUND_TUNNEL_LENGTH;
 		int inQty   = DEFAULT_INBOUND_TUNNELS_QUANTITY;
@@ -70,6 +70,19 @@ namespace client
 				it = params->find (I2CP_PARAM_LEASESET_TYPE);
 				if (it != params->end ())
 					m_LeaseSetType = std::stoi(it->second);
+				if (m_LeaseSetType == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
+				{
+					// authentication for encrypted LeaseSet
+					it = params->find (I2CP_PARAM_LEASESET_AUTH_TYPE);
+					if (it != params->end ())
+					{
+						auto authType = std::stoi (it->second);
+						if (authType >= i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_NONE && authType <= i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_PSK)
+							m_AuthType = authType;
+						else
+							LogPrint (eLogError, "Destination: Unknown auth type ", authType);
+					}
+				}
 				it = params->find (I2CP_PARAM_LEASESET_PRIV_KEY);
 				if (it != params->end ())
 				{
@@ -846,7 +859,7 @@ namespace client
 	ClientDestination::ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map<std::string, std::string> * params):
 		LeaseSetDestination (isPublic, params), m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY),
 		m_DatagramDestination (nullptr), m_RefCounter (0),
-		m_ReadyChecker(GetService()), m_AuthType (i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_NONE)
+		m_ReadyChecker(GetService())
 	{
 		if (keys.IsOfflineSignature () && GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET)
 			SetLeaseSetType (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2); // offline keys can be published with LS2 only
@@ -880,25 +893,21 @@ namespace client
 				if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
 				{
 					// authentication for encrypted LeaseSet
-					it = params->find (I2CP_PARAM_LEASESET_AUTH_TYPE);
-					m_AuthType = std::stoi (it->second);
-					if (m_AuthType > 0)
+					auto authType = GetAuthType ();
+					if (authType > 0)
 					{
 						m_AuthKeys = std::make_shared<std::vector<i2p::data::AuthPublicKey> >();
-						if (m_AuthType == i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_DH)
+						if (authType == i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_DH)
 							ReadAuthKey (I2CP_PARAM_LEASESET_CLIENT_DH, params);	
-						else if (m_AuthType == i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_PSK)
+						else if (authType == i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_PSK)
 							ReadAuthKey (I2CP_PARAM_LEASESET_CLIENT_PSK, params);	
 						else
-						{
-							LogPrint (eLogError, "Destination: Unexpected auth type ", m_AuthType);
-							m_AuthType = 0;
-						}
+							LogPrint (eLogError, "Destination: Unexpected auth type ", authType);
 						if (m_AuthKeys->size ())
 							LogPrint (eLogInfo, "Destination: ", m_AuthKeys->size (), " auth keys read");
 						else
 						{
-							LogPrint (eLogError, "Destination: No auth keys read for auth type ", m_AuthType);
+							LogPrint (eLogError, "Destination: No auth keys read for auth type ", authType);
 							m_AuthKeys = nullptr;	
 						}
 					}
@@ -1184,7 +1193,7 @@ namespace client
 			auto ls2 = std::make_shared<i2p::data::LocalLeaseSet2> (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2,
 				m_Keys, m_EncryptionKeyType, keyLen, m_EncryptionPublicKey, tunnels, IsPublic (), isPublishedEncrypted);
 			if (isPublishedEncrypted) // encrypt if type 5
-				ls2 = std::make_shared<i2p::data::LocalEncryptedLeaseSet2> (ls2, m_Keys, m_AuthType, m_AuthKeys);
+				ls2 = std::make_shared<i2p::data::LocalEncryptedLeaseSet2> (ls2, m_Keys, GetAuthType (), m_AuthKeys);
 			leaseSet = ls2;
 		}
 		SetLeaseSet (leaseSet);
diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h
index 148a6101..a32d3ed1 100644
--- a/libi2pd/Destination.h
+++ b/libi2pd/Destination.h
@@ -134,6 +134,7 @@ namespace client
 			void SetLeaseSet (std::shared_ptr<const i2p::data::LocalLeaseSet> newLeaseSet);
 			int GetLeaseSetType () const { return m_LeaseSetType; };
 			void SetLeaseSetType (int leaseSetType) { m_LeaseSetType = leaseSetType; };
+			int GetAuthType () const { return m_AuthType; };
 			bool IsPublic () const { return m_IsPublic; };
 			virtual void CleanupDestination () {}; // additional clean up in derived classes
 			// I2CP
@@ -179,7 +180,7 @@ namespace client
 			boost::asio::deadline_timer m_PublishConfirmationTimer, m_PublishVerificationTimer,
 				m_PublishDelayTimer, m_CleanupTimer;
 			std::string m_Nickname;
-			int m_LeaseSetType;
+			int m_LeaseSetType, m_AuthType;
 			std::unique_ptr<i2p::data::Tag<32> > m_LeaseSetPrivKey; // non-null if presented
 
 		public:
@@ -188,6 +189,7 @@ namespace client
 			int GetNumRemoteLeaseSets () const { return m_RemoteLeaseSets.size (); };
 			const decltype(m_RemoteLeaseSets)& GetLeaseSets () const { return m_RemoteLeaseSets; };
 			bool IsEncryptedLeaseSet () const { return m_LeaseSetType == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2; };
+			bool IsPerClientAuth () const { return m_AuthType > 0; };
 	};
 
 	class ClientDestination: public LeaseSetDestination
@@ -270,8 +272,7 @@ namespace client
 
 			boost::asio::deadline_timer m_ReadyChecker;
 
-			int m_AuthType;
-			std::shared_ptr<std::vector<i2p::data::AuthPublicKey> > m_AuthKeys;  
+			std::shared_ptr<std::vector<i2p::data::AuthPublicKey> > m_AuthKeys; // we don't need them for I2CP  
 
 		public: