Debugged Get requests and Push Token Issuance

This commit is contained in:
kl3mta3
2025-03-16 21:38:09 -05:00
parent 8fa16d4468
commit cfe43e29e8
17 changed files with 846 additions and 673 deletions

View File

@@ -76,9 +76,6 @@ namespace SPHERE.Blockchain
[JsonPropertyName("LastUpdateTime")]
public required DateTime LastUpdateTime { get; set; } = new(); // Time stamp of last Update to the block by validated user.
[JsonPropertyName("EncryptionAlgorithm")]
public required string EncryptionAlgorithm { get; set; } = ""; // Algorithm used for encryption (e.g. AES256, RSA2048, ECDsa)
[JsonPropertyName("KeyUsagePolicies")]
public required string? KeyUsagePolicies { get; set; } // Policies for key usage
@@ -100,7 +97,7 @@ namespace SPHERE.Blockchain
// Calculates the hash for the block
public string CalculateBlockHash()
{
string input = $"{BlockId}{PreviousHash}{BlockCreationTime}{EncryptionAlgorithm}{KeyUsagePolicies}";
string input = $"{BlockId}{PreviousHash}{BlockCreationTime}{KeyUsagePolicies}";
using var sha256 = SHA256.Create();
byte[] inputBytes = Encoding.UTF8.GetBytes(input);
byte[] hashBytes = sha256.ComputeHash(inputBytes);
@@ -128,41 +125,45 @@ namespace SPHERE.Blockchain
// Creating a Contact Block
public static Block CreateContactBlock(Node node, string nodeId, string previousHash, string encryptedContactData, EncryptionAlgorithm encryptionAlgorithm)
public static Block CreateContactBlock(Node node, string previousHash, Contact contact)
{
//Check to see if Keys exist.
PrivateKeyManager PrivateKeyManager = new();
DateTime creationTime = DateTime.Now;
byte[] LSK = node.KeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.LocalSymmetricKey);
if (LSK == null || LSK.Length == 0)
{
SystemLogger.Log($"Debug-CreateContactBlock: LocalSymmetricKey is null or empty");
return null;
}
byte[] encryptedContactData = Contact.BuildEncryptedContact(contact, LSK);
var header = new BlockHeader
{
BlockId = BlockHeader.GenerateBlockID(),
BlockId = contact.MetaData.ContactID,
BlockType = BlockType.Contact.ToString(),
BlockVersion = "1.0",
PreviousHash = previousHash,
BlockCreationTime = creationTime,
LastUpdateTime = creationTime,
EncryptionAlgorithm = encryptionAlgorithm.ToString(),
KeyUsagePolicies = "MESSAGE_ENCRYPTION_ONLY",
PublicSignatureKey = PrivateKeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicPersonalSignatureKey),
PublicEncryptionKey = PrivateKeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicPersonalEncryptionKey),
CreatorNodeId = nodeId,
PublicSignatureKey = node.KeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicPersonalSignatureKey),
PublicEncryptionKey = node.KeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicPersonalEncryptionKey),
CreatorNodeId = node.Peer.NodeId,
};
// Serialize and store contact data
string serializedContactData = JsonSerializer.Serialize(encryptedContactData);
header.BlockHash = header.CalculateBlockHash();
return new Block
Block block = new Block
{
Header = header,
EncryptedContact = serializedContactData,
EncryptedLocalSymmetricKey = PrivateKeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.EncryptedLocalSymmetricKey),
EncryptedContact = Convert.ToBase64String(encryptedContactData),
EncryptedLocalSymmetricKey = node.KeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.EncryptedLocalSymmetricKey),
};
return block;
}
// Checks if a block is a contact block
@@ -186,7 +187,6 @@ namespace SPHERE.Blockchain
PreviousHash = previousHash,
BlockCreationTime = creationTime,
LastUpdateTime = creationTime,
EncryptionAlgorithm = encryptionAlgorithm.ToString(),
KeyUsagePolicies = "MESSAGE_ENCRYPTION_ONLY",
PublicSignatureKey =PrivateKeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicPersonalSignatureKey),
PublicEncryptionKey =PrivateKeyManager.UseKeyInStorageContainer(node,KeyGenerator.KeyType.PublicPersonalEncryptionKey),
@@ -227,7 +227,6 @@ namespace SPHERE.Blockchain
PreviousHash = previousHash,
BlockCreationTime = creationTime,
LastUpdateTime = creationTime,
EncryptionAlgorithm = encryptionAlgorithm.ToString(),
KeyUsagePolicies = "MESSAGE_ENCRYPTION_ONLY",
PublicSignatureKey =PrivateKeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicPersonalSignatureKey),
PublicEncryptionKey =PrivateKeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicPersonalEncryptionKey),

View File

@@ -1,22 +1,25 @@
using SPHERE.Configure;
using SPHERE.Security;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text.Json;
namespace SPHERE.Blockchain
{
public class Contact
{
public ContactMetaData MetaData { get; set; } // Contacts needed MetaData.
public ContactKeys Keys { get; set; } // Contacts needed Encryption keys.
public EncryptedKeyParts KeySignatureParts { get; set; } // Contacts Private key is encrypted and stored in parts with noise
public EncryptedKeyParts KeyEncryptionParts { get; set; } // Contacts Private key is encrypted and stored in parts with noise
public List<(byte[], byte[])> AuthenticationData = new(); // Hashes user for User Authentication and VAlidation for Password reset and recovery.
public required ContactMetaData MetaData { get; set; } // Contacts needed MetaData.
public required ContactKeys Keys { get; set; } // Contacts needed Encryption keys.
public required EncryptedKeyParts KeySignatureParts { get; set; } // Contacts Private key is encrypted and stored in parts with noise
public required EncryptedKeyParts KeyEncryptionParts { get; set; } // Contacts Private key is encrypted and stored in parts with noise
public required List<(byte[], byte[])> AuthenticationData = new(); // Hashes user for User Authentication and VAlidation for Password reset and recovery.
/// <summary>
/// !!!
/// To Create a contact and Generate Pairs of needed Private Keys, A password is needed to be passed in. This is a string meeting Requirements. (Needs Upper, Lower, Number, Symbol, and to be between 8-64 characters.)
/// User Password.CreatePasswordFromString(string password) to generate a password from a string or Password.GenerateRandomPassword(int length) defaults to 16char.
/// <param name="displayName"></param>
/// <param name="alias"></param>
/// <param name="name"></param>
/// <param name="blockId"></param>
/// <param name="avatarURL"></param>
@@ -25,60 +28,81 @@ namespace SPHERE.Blockchain
/// !!!
/// <returns></returns>
/// </summary>
public static Contact CreateNewContact(Node node, string displayName, string name, string blockId, string? avatarURL, string? description, Password privateKeyPassword)
public static Contact CreateNewContact(Node node, string contactId, string alias, string name, Password privateKeyPassword, string pin)
{
PrivateKeyManager PrivateKeyManager = new();
PrivateKeyManager privateKeyManager = node.KeyManager;
//Generate the set or Key Pairs needed (Signature and Communication pair)
KeyGenerator.GeneratePersonalKeyPairSets(privateKeyPassword);
KeyGenerator.GeneratePersonalKeyPairSets(node);
var semiPublicKey = KeyGenerator.GenerateSymmetricKey();
PrivateKeyManager.SetPrivatePersonalKey(semiPublicKey, KeyGenerator.KeyType.SemiPublicKey);
privateKeyManager.SetPrivatePersonalKey(node, semiPublicKey, KeyGenerator.KeyType.SemiPublicKey);
//used to encrypt the contact
var localSymmetricKey = KeyGenerator.GenerateSymmetricKey();
PrivateKeyManager.SetPrivatePersonalKey(localSymmetricKey, KeyGenerator.KeyType.LocalSymmetricKey);
privateKeyManager.SetPrivatePersonalKey(node, localSymmetricKey, KeyGenerator.KeyType.LocalSymmetricKey);
//the LocalSymmetricKey is Encrypted with the SemiPublicKey and attached to the block so only approved people with the semiPublicKey can decrypt the EncryptedLocalSymetricKey and then decrypt the contact.
var encryptedLocalSymmetricKey = Encryption.EncryptLocalSymmetricKey(localSymmetricKey, semiPublicKey);
PrivateKeyManager.SetPrivatePersonalKey(encryptedLocalSymmetricKey, KeyGenerator.KeyType.EncryptedLocalSymmetricKey);
privateKeyManager.SetPrivatePersonalKey(node, encryptedLocalSymmetricKey, KeyGenerator.KeyType.EncryptedLocalSymmetricKey);
ContactKeys keys = new ContactKeys
{
PublicPersonalEncryptionKey = PrivateKeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicPersonalEncryptionKey),
PublicPersonalSignatureKey = PrivateKeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicPersonalSignatureKey),
PublicPersonalEncryptionKey = privateKeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicPersonalEncryptionKey),
PublicPersonalSignatureKey = privateKeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicPersonalSignatureKey),
SemiPublicKey = semiPublicKey,
LocalSymmetricKey = localSymmetricKey
EncryptedLocalSymmetricKey = encryptedLocalSymmetricKey
};
ContactMetaData metaData = new ContactMetaData
{
DisplayName = displayName,
DisplayName = alias,
Name = name,
AvatarURLHash = avatarURL,
Description = description,
ContactID = contactId,
ContactVersion="V1.0"
};
EncryptedKeyParts encryptedSignatureKeyParts = node.KeyManager.EncryptPersonalKeyParts(node.KeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PrivatePersonalSignatureKey), privateKeyPassword.ToString(), pin);
EncryptedKeyParts encryptedEncryptionKeyParts = node.KeyManager.EncryptPersonalKeyParts(node.KeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PrivatePersonalEncryptionKey), privateKeyPassword.ToString(), pin);
Contact contact = new Contact
{
MetaData = metaData,
Keys = keys,
KeySignatureParts = encryptedSignatureKeyParts,
KeyEncryptionParts = encryptedEncryptionKeyParts,
AuthenticationData = CredentialManager.GenerateStoredHashes(privateKeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicPersonalSignatureKey), privateKeyPassword.ToString(), pin, contactId),
};
return contact;
}
public static byte[] BuildEncryptedContact(Contact contact)
public static byte[] BuildEncryptedContact(Contact contact, byte[] localSymmetricKey)
{
var encryptedContact = Encryption.EncryptWithSymmetric(contact, contact.Keys.LocalSymmetricKey);
// Encrypt the serialized data
byte[] encryptedContact = Encryption.EncryptContactWithSymmetric(contact, localSymmetricKey);
return encryptedContact;
}
public static Contact DecryptAndBuildContact(string encryptedContact, byte[] localSymmetricKey)
{
// Decode the Base64 data directly
//byte[] decryptedBytes = Encryption.DecryptContactWithSymmetricKey(encryptedContact, localSymmetricKey);
// Deserialize the Contact object
Contact contact = Encryption.DecryptContactWithSymmetricKey(encryptedContact, localSymmetricKey); ;
return contact;
}
/// <summary>
/// The contact is intended to be the core of a block. It will be encrypted with a Local Symmetric Key before it is placed on the block.
/// The purpose is to allow for users to control their data, but also gain the security and decentralization of a p2p DHT.
@@ -101,9 +125,10 @@ namespace SPHERE.Blockchain
///
public class ContactMetaData()
{
public string DisplayName { get; set; } // User's display name
public string Name { get; set; } // Users Name
public string ContactVersion { get; set; } // Contact versions would allow for deserialization of different contact styles as the platform evolves.
public required string DisplayName { get; set; } // User's display name
public required string Name { get; set; } // Users Name
public required string ContactID { get; set; } // Contacts User ID (BLOCK ID)
public required string ContactVersion { get; set; } // Contact versions would allow for deserialization of different contact styles as the platform evolves.
public string? HashedSSN { get; set; } // Users can provide a salted Hash of their SSN and this can be used later by applications to comparir it against the a hash of the ssn and key provided by the user. (Optional)
public string? HashedCardNumber { get; set; } // Users can provide a salted Hash of their Card Number, this will by used by verification server when provided the cc and key by the user, if it can verify the hash it creates a 1 way payment tunnel from there to the merchants account. the merchant never sees the data (optional)
public string? HashedAccountNumber { get; set; } // Users can provide a salted Hash of their Recount, this will by used by verification server when provided the account number and key by the user, if it can verify the hash it creates a 1 way payment tunnel from there to the merchants account.(optional)
@@ -117,10 +142,10 @@ namespace SPHERE.Blockchain
public class ContactKeys()
{
public byte[] SemiPublicKey { get; set; } // Semi-public key
public byte[] LocalSymmetricKey { get; set; } // Unencrypted Local Symmetric code used to encrypt the Contact.
public byte[] PublicPersonalEncryptionKey { get; set; } // Personal Communication key for encrypting messages only the user can decrypt
public byte[] PublicPersonalSignatureKey { get; set; } // Used to verify signatures created with the PrivateSignatureKey
public required byte[] SemiPublicKey { get; set; } // Semi-public key
public required byte[] EncryptedLocalSymmetricKey { get; set; } // Unencrypted Local Symmetric code used to encrypt the Contact.
public required byte[] PublicPersonalEncryptionKey { get; set; } // Personal Communication key for encrypting messages only the user can decrypt
public required byte[] PublicPersonalSignatureKey { get; set; } // Used to verify signatures created with the PrivateSignatureKey
}
}

View File

@@ -102,7 +102,7 @@ namespace SPHERE.Blockchain
//create a node.
Node node = new Node();
string nodeId = GenerateKademliaId();
//Create a client for the node using STUN.
try
{
@@ -153,9 +153,27 @@ namespace SPHERE.Blockchain
try
{
// Load DHT state (internal locking already handled by LoadState)
if (File.Exists(DHT.GetAppDataPath("DHT")))
if (File.Exists(DHT.GetAppDataPath(node, "ContactDHT")))
{
node.ContactDHT.LoadState();
node.ContactDHT.LoadState(node,"ContactDHT");
}
else
{
SystemLogger.Log("DHT state file not found. Starting with a fresh state.");
}
if (File.Exists(DHT.GetAppDataPath(node, "TransactionDHT")))
{
node.TransactionDHT.LoadState(node, "TransactionDHT");
}
else
{
SystemLogger.Log("DHT state file not found. Starting with a fresh state.");
}
if (File.Exists(DHT.GetAppDataPath(node, "ReputationDHT")))
{
node.ReputationDHT.LoadState(node, "ReputationDHT");
}
else
{
@@ -174,9 +192,9 @@ namespace SPHERE.Blockchain
try
{
// Load RoutingTable state (internal locking already handled by LoadState)
if (File.Exists(DHT.GetAppDataPath("RT")))
if (File.Exists(DHT.GetAppDataPath(node, "RT")))
{
node.RoutingTable.LoadRoutingTable();
node.RoutingTable.LoadRoutingTable(node, "RT");
}
else
{
@@ -190,29 +208,23 @@ namespace SPHERE.Blockchain
{
SystemLogger.Log($"Error loading RoutingTable state: {ex.Message}");
SystemLogger.Log("Starting with a fresh state.");
node.RoutingTable = new RoutingTable(); // Reinitialize
node.RoutingTable = new RoutingTable();
}
node.RoutingTable.node = node;
return node;
}
//This is used to Create the Node and Listener or Load one if it exists.
public static Node CreateNodeWithClientListenerUsingSTUN(NodeType nodeType)
public static Node CreateNodeUsingSTUN(NodeType nodeType)
{
//create a node.
SystemLogger.Log($"Debug-CreateNodeWithClientUsingSTUN: Creating Node with STUN");
Node node = new Node();
node.Peer.NodeId = Node.GenerateKademliaId();
node.KeyManager = new();
node.KeyManager.SetNodeEncryptionFilePath(node);
//Create a client get listeners using STUN.
Client client = new Client();
// Thread-safe key generation
lock (stateLock)
node.Client = new Client();
try
{
try
{
@@ -225,78 +237,129 @@ namespace SPHERE.Blockchain
Console.WriteLine($"Error-CreateTestNodeWithFakeSTUNAsync: Generating Key pairs. Reason: {ex.Message}");
throw;
}
}
client.StartClientListenerWithSTUNSync(node, client);
node.Client = client;
try
{
// Initialize PeerHeader
Peer peer = new Peer
var stun = new STUN();
var (PublicIP, PublicPort) = stun.GetPublicEndpoint();
SystemLogger.Log($"Debug-CreateNodeWithClientUsingSTUN: STUN Returned an IP of: {PublicIP}.");
SystemLogger.Log($"Debug-CreateNodeWithClientUsingSTUN: STUN Returned a Port of: {PublicPort}.");
string testModeEnv = Environment.GetEnvironmentVariable("SPHERE_TEST_MODE");
SystemLogger.Log($"Debug-CreateNodeWithClientUsingSTUN: Test mode: {testModeEnv}.");
node.Client.clientIP = node.Client.GetLocalIPAddress();
if (testModeEnv!="true")
{
Node_Type = nodeType,
NodeIP = client.clientIP.ToString(),
NodePort = client.clientListenerPort,
PreviousNodesHash = DefaultPreviousHash, // Placeholder value
PublicSignatureKey = node.KeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicNodeSignatureKey),
PublicEncryptKey = node.KeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicNodeEncryptionKey),
};
node.Client.clientIP = PublicIP;
}
node.Client.clientListenerPort = PublicPort;
try
{
Console.WriteLine("Initializing Peer Header...");
Peer peer = new Peer
{
Node_Type = nodeType,
NodeId = node.Peer.NodeId,
NodeIP = node.Client.clientIP.ToString(),
NodePort = PublicPort,
PreviousNodesHash = Node.DefaultPreviousHash,
PublicSignatureKey = node.KeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicNodeSignatureKey),
PublicEncryptKey = node.KeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicNodeEncryptionKey),
};
node.Peer = peer;
SystemLogger.Log($"Debug-CreateNodeWithClientUsingSTUN: Node Client IP of: {node.Client.clientIP.ToString()}.");
SystemLogger.Log($"Debug-CreateNodeWithClientUsingSTUN: Node Client Port of: {node.Client.clientListenerPort}.");
SystemLogger.Log($"Debug-CreateNodeWithClientUsingSTUN: Peer IP of: {node.Peer.NodeIP}.");
SystemLogger.Log($"Debug-CreateNodeWithClientUsingSTUN: Peer Port of: {node.Peer.NodePort}.");
}
catch (Exception ex)
{
Console.WriteLine($"Error Creating Peer Header: {ex.Message}");
throw;
}
try
{
// Load DHT state (internal locking already handled by LoadState)
if (File.Exists(DHT.GetAppDataPath(node, "ContactDHT")))
{
node.ContactDHT.LoadState(node, "ContactDHT");
}
else
{
SystemLogger.Log("ContactDHT state file not found. Starting with a fresh state.");
node.ContactDHT = new DHT();
}
if (File.Exists(DHT.GetAppDataPath(node, "ReputationDHT")))
{
node.ReputationDHT.LoadState(node, "ReputationDHT");
}
else
{
SystemLogger.Log("ReputationDHT state file not found. Starting with a fresh state.");
node.ReputationDHT = new DHT();
}
if (File.Exists(DHT.GetAppDataPath(node, "TransactionDHT")))
{
node.TransactionDHT.LoadState(node, "TransactionDHT");
}
else
{
SystemLogger.Log("TransactionDHT state file not found. Starting with a fresh state.");
node.TransactionDHT = new DHT();
}
}
catch (Exception ex)
{
SystemLogger.Log($"Error loading DHT state: {ex.Message}");
}
try
{
// Load RoutingTable state (internal locking already handled by LoadState)
if (File.Exists(DHT.GetAppDataPath(node, "RT")))
{
node.RoutingTable.LoadRoutingTable(node, "RT");
}
else
{
SystemLogger.Log("Routing Table state file not found. Starting with a fresh state.");
node.RoutingTable = new RoutingTable();
}
}
catch (Exception ex)
{
SystemLogger.Log($"Error loading RoutingTable state: {ex.Message}");
}
if (node != null)
{
SystemLogger.Log($"Debug-CreateNodeWithClientUsingSTUN: Node is build returning Node.");
node.Client.StartClientListenerAsync(node);
return node;
}
else
{
SystemLogger.Log($"Debug-CreateNodeWithClientUsingSTUN: Node was returned null.");
return null;
}
// Assign header to node
node.Peer = peer;
}
catch (Exception ex)
{
SystemLogger.Log($"Error retrieving or creating keys: {ex.Message}");
Console.WriteLine($"Error CreatingNodeWithClientUsingStun: EndFail{ex.Message}");
throw;
}
// Initialize DHT
node.ContactDHT = new DHT();
try
{
// Load DHT state (internal locking already handled by LoadState)
if (File.Exists(DHT.GetAppDataPath("DHT")))
{
node.ContactDHT.LoadState();
}
else
{
SystemLogger.Log("DHT state file not found. Starting with a fresh state.");
}
}
catch (Exception ex)
{
SystemLogger.Log($"Error loading DHT state: {ex.Message}");
SystemLogger.Log("Starting with a fresh state.");
node.ContactDHT = new DHT(); // Reinitialize
}
try
{
// Load RoutingTable state (internal locking already handled by LoadState)
if (File.Exists(DHT.GetAppDataPath("RT")))
{
node.RoutingTable.LoadRoutingTable();
}
else
{
SystemLogger.Log("Routing Table state file not found. Starting with a fresh state.");
}
}
catch (Exception ex)
{
SystemLogger.Log($"Error loading RoutingTable state: {ex.Message}");
SystemLogger.Log("Starting with a fresh state.");
node.RoutingTable = new RoutingTable(); // Reinitialize
}
return node;
}
//Once the Node has a Routing Table it can get the Previous Hash and update the Previous Hash
@@ -382,7 +445,7 @@ namespace SPHERE.Blockchain
//Generate Node and Block Id's
internal static string GenerateKademliaId()
{
byte[] randomBytes = new byte[32]; // 256 bits = 32 bytes
byte[] randomBytes = new byte[32];
// Use the modern RandomNumberGenerator.Fill method
System.Security.Cryptography.RandomNumberGenerator.Fill(randomBytes);

View File

@@ -143,11 +143,12 @@ namespace SPHERE.Blockchain
}
}
public static string GetAppDataPath(string fileName)
public static string GetAppDataPath(Node node, string fileName)
{
string appDataDir;
string firstSix = node.Peer.NodeId.Length >= 6 ? node.Peer.NodeId.Substring(0, 6) : node.Peer.NodeId;
appDataDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
return Path.Combine(appDataDir, $"{AppIdentifier.GetOrCreateServiceName()}{fileName}.state");
return Path.Combine(appDataDir, $"{AppIdentifier.GetOrCreateServiceName()}{firstSix}{fileName}.state");
}
/// <summary>
@@ -206,23 +207,18 @@ namespace SPHERE.Blockchain
return false;
}
// Optionally validate encryption algorithm, signature, or other policies
if (block.Header.EncryptionAlgorithm != "AES256" && block.Header.EncryptionAlgorithm != "RSA2048")
{
SystemLogger.Log($"Unsupported encryption algorithm: {block.Header.EncryptionAlgorithm}");
return false;
}
return true;
}
public void SaveState()
public void SaveState(Node node, string _filePast)
{
lock (stateLock) // Ensure thread safety
{
try
{
string filePath = GetAppDataPath("DHT");
// SaveContactDHT
string filePath = GetAppDataPath(node, _filePast);
// Ensure the directory exists
string directoryPath = Path.GetDirectoryName(filePath);
@@ -256,13 +252,13 @@ namespace SPHERE.Blockchain
}
// Load DHT state from a file
public void LoadState()
public void LoadState(Node node, string _filePath)
{
lock (stateLock) // Ensure thread safety
{
try
{
string filePath = GetAppDataPath("DHT");
string filePath = GetAppDataPath(node, _filePath);
if (!File.Exists(filePath))
{

View File

@@ -102,7 +102,7 @@ namespace SPHERE.Blockchain
Packet responsePacket = Packet.PacketBuilder.BuildPacket(responseHeader, JsonSerializer.Serialize(block));
Packet responsePacket = Packet.PacketBuilder.BuildPacket(node, responseHeader, JsonSerializer.Serialize(block));
byte[] serializedResponse = Packet.PacketBuilder.SerializePacket(responsePacket);
// Encrypt with the requester's public key
@@ -192,7 +192,7 @@ namespace SPHERE.Blockchain
15
);
Packet requestPacket = Packet.PacketBuilder.BuildPacket(header, blockType.ToString());
Packet requestPacket = Packet.PacketBuilder.BuildPacket(node, header, blockType.ToString());
byte[] serializedPacket = Packet.PacketBuilder.SerializePacket(requestPacket);
// Encrypt the packet with the peer's public key

View File

@@ -233,13 +233,13 @@ public class RoutingTable
}
}
public void SaveRoutingTable()
public void SaveRoutingTable(Node node, string _filePath)
{
lock (_lock)
{
try
{
string filePath = DHT.GetAppDataPath("RT");
string filePath = DHT.GetAppDataPath(node, _filePath);
string directoryPath = Path.GetDirectoryName(filePath);
if (!Directory.Exists(directoryPath))
@@ -280,13 +280,13 @@ public class RoutingTable
}
}
public void LoadRoutingTable()
public void LoadRoutingTable(Node node, string _filePath)
{
lock (_lock)
{
try
{
string filePath = DHT.GetAppDataPath("RT");
string filePath = DHT.GetAppDataPath(node, _filePath);
if (!File.Exists(filePath))
{

View File

@@ -56,12 +56,12 @@ namespace SPHERE.Networking
node.Peer.Node_Type.ToString(),
node.Peer.PublicSignatureKey,
node.Peer.PublicEncryptKey,
node.Client.clientListenerPort,
node.Client.clientIP.ToString(),
node.Peer.NodePort,
node.Peer.NodeIP,
25
);
Packet packet = Packet.PacketBuilder.BuildPacket(header, Packet.PacketBuilder.PacketType.BootstrapRequest.ToString());
Packet packet = Packet.PacketBuilder.BuildPacket(node, header, Packet.PacketBuilder.PacketType.BootstrapRequest.ToString());
SystemLogger.Log($"Debug-SendBootstrapRequest: Packet built with NodeId: {node.Peer.NodeId}, IP: {node.Client.clientIP}, Port: {node.Client.clientListenerPort}");
// Serialize the packet into a byte array
@@ -374,7 +374,7 @@ namespace SPHERE.Networking
var SerializedPayload = JsonSerializer.Serialize<BootstrapResponsePayload>(responsePayload);
Packet responsePacket = Packet.PacketBuilder.BuildPacket(header, SerializedPayload);
Packet responsePacket = Packet.PacketBuilder.BuildPacket(node, header, SerializedPayload);
byte[] serializedPacket = Packet.PacketBuilder.SerializePacket(responsePacket);

View File

@@ -15,6 +15,8 @@ using System;
using System.Security.Cryptography;
using System.Text.Json;
using static SPHERE.Networking.Packet;
using System.Reflection.PortableExecutable;
using System.IO;
namespace SPHERE.Networking
@@ -67,6 +69,7 @@ namespace SPHERE.Networking
{ PacketBuilder.PacketType.Ping, (node, packet) => node.NetworkManager.PongPeerAsync(node, packet) },
{ PacketBuilder.PacketType.Pong, (node, packet) => node.NetworkManager.ProcessPongAsync(node, packet) },
{ PacketBuilder.PacketType.GetRequest, (node, packet) => node.NetworkManager.RespondToGetRequest(node, packet) },
{ PacketBuilder.PacketType.GetResponse, (node, packet) => node.NetworkManager.ProcessGetResponse(node, packet) },
{ PacketBuilder.PacketType.BrodcastConnection, (node, packet) => node.NetworkManager.PeerListResponse(node, packet) },
{ PacketBuilder.PacketType.PeerUpdate, (node, packet) => node.Peer.ProcessPeerListResponse(node, packet) },
{ PacketBuilder.PacketType.SyncDHTRequest, (node, packet) => DHTManagement.ProcessSyncDHTRequest(node, packet) },
@@ -355,37 +358,38 @@ namespace SPHERE.Networking
}
public async Task StartClientListenerAsync(Node node, Client client)
public async Task StartClientListenerAsync(Node node)
{
try
{
// Ensure we have a valid listener port
if (client.clientListenerPort == 0)
{
client.clientListenerPort = FindAvailablePort();
}
client.Listener = new TcpListener(client.clientIP, client.clientListenerPort);
client.Listener.Start();
SystemLogger.Log($"Async server is listening on port {client.clientListenerPort}");
// Ensure we have a valid listener port
if (node.Client.clientListenerPort == 0)
{
SystemLogger.Log($"Error-StartClientListenerAsync: Port was 0.");
return;
}
node.Client.Listener = new TcpListener(node.Client.clientIP, node.Client.clientListenerPort);
node.Client.Listener.Start();
//SystemLogger.Log($"Async server is listening on port {node.Client.clientListenerPort}");
while (true)
{
try
{
client.client = await client.Listener.AcceptTcpClientAsync();
SystemLogger.Log($"Connection established with {client.client.Client.RemoteEndPoint}");
node.Client.client = await node.Client.Listener.AcceptTcpClientAsync();
//SystemLogger.Log($"Connection established with {node.Client.client.Client.RemoteEndPoint}");
_ = HandleClientAsync(node, client.client);
_ = HandleClientAsync(node, node.Client.client);
}
catch (Exception ex)
{
SystemLogger.Log($"Server error: {ex.Message}");
// SystemLogger.Log($"Server error: {ex.Message}");
}
}
}
catch (Exception ex)
{
SystemLogger.Log($"Error starting listener: {ex.Message}");
//SystemLogger.Log($"Error starting listener: {ex.Message}");
return;
}
}
@@ -400,11 +404,11 @@ namespace SPHERE.Networking
if (PublicIP == null || PublicPort == 0)
{
SystemLogger.Log("StartClientListenerWithSTUNAsync: Failed to retrieve public endpoint. Trying once more.");
//SystemLogger.Log("StartClientListenerWithSTUNAsync: Failed to retrieve public endpoint. Trying once more.");
var (PublicIP1, PublicPort1) = stun.GetPublicEndpoint();
if (PublicIP1 == null || PublicPort1 == 0)
{
SystemLogger.Log("StartClientListenerWithSTUNAsync: Failed to retrieve public endpoint again. Exiting.");
//SystemLogger.Log("StartClientListenerWithSTUNAsync: Failed to retrieve public endpoint again. Exiting.");
return;
}
@@ -443,9 +447,13 @@ namespace SPHERE.Networking
// Synchronous method to start the client listener using STUN
public void StartClientListenerWithSTUNSync(Node node, Client client)
{
SystemLogger.Log($"Debug-StartClientListenerWithSTUNSync: Starting Stun search");
try
{
// Step 1: Retrieve public IP and port using STUN
// Retrieve public IP and port using STUN
var stun = new STUN();
var (PublicIP, PublicPort) = stun.GetPublicEndpoint();
@@ -561,6 +569,7 @@ namespace SPHERE.Networking
}
finally
{
await client.GetStream().FlushAsync();
client.Close();
}
}
@@ -605,9 +614,35 @@ namespace SPHERE.Networking
try
{
string normalizedContent = "empty";
string packetHash = "";
//Store a Hash of the Packet Content to check and prevent processing duplicate packets.
string normalizedContent = JsonSerializer.Serialize(JsonSerializer.Deserialize<object>(packet.Content), new JsonSerializerOptions { WriteIndented = false });
string packetHash = ComputeHash(normalizedContent); // Hash only the static parts
try
{
var options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = false,
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
var contentObject = JsonSerializer.Deserialize<object>(packet.Content, options);
if (contentObject is string stringContent)
{
normalizedContent = stringContent;
}
else
{
normalizedContent = JsonSerializer.Serialize(contentObject, options);
}
}
catch(Exception ex)
{
// SystemLogger.Log($"Error-ProcessIncomingPacket: Error processing packet(Preventing Duplicates-normalizedContent serialization failed.): {ex.Message}");
}
packetHash = ComputeHash(normalizedContent);
if (node.seenPackets.ContainsKey(packetHash))
{
@@ -629,13 +664,38 @@ namespace SPHERE.Networking
try
{
byte[] sendersPublicSignatureKey = packet.Header.PublicSignatureKey;
SystemLogger.Log($"Debug-ProcessIncomingPacket: Sender Public Signature Key: {Convert.ToBase64String(sendersPublicSignatureKey)}.");
SystemLogger.Log($"Debug-ProcessIncomingPacket: Raw Signature Before Decoding: {packet.Signature}");
byte[] rawSignature = Convert.FromBase64String(packet.Signature);
SystemLogger.Log($"Debug-ProcessIncomingPacket: Raw Signature: {Convert.ToBase64String(rawSignature)}.");
bool isValidSignature = SignatureGenerator.VerifyByteArray(packetData, rawSignature, sendersPublicSignatureKey);
var modifiedHeader = new PacketHeader
{
NodeId = packet.Header.NodeId,
Node_Type = packet.Header.Node_Type,
IPAddress = packet.Header.IPAddress,
Port = packet.Header.Port,
PublicSignatureKey = packet.Header.PublicSignatureKey,
PublicEncryptKey = packet.Header.PublicEncryptKey,
Packet_Type = packet.Header.Packet_Type
};
var options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = false,
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
string serializedHeader = JsonSerializer.Serialize(modifiedHeader, options);
byte[] headerBytes = Encoding.UTF8.GetBytes(serializedHeader);
byte[] contentBytes = Encoding.UTF8.GetBytes(packet.Content);
int totalLength = headerBytes.Length + contentBytes.Length;
byte[] combinedBytes = new byte[totalLength];
Buffer.BlockCopy(headerBytes, 0, combinedBytes, 0, headerBytes.Length);
Buffer.BlockCopy(contentBytes, 0, combinedBytes, headerBytes.Length, contentBytes.Length);
byte[] sendersPublicSignatureKey = packet.Header.PublicSignatureKey;
byte[] rawSignature = Convert.FromBase64String(packet.Signature);
bool isValidSignature = SignatureGenerator.VerifyByteArray(combinedBytes, rawSignature, packet.Header.PublicSignatureKey);
if (!isValidSignature)
{
SystemLogger.Log("Error-ProcessIncomingPacket: Invalid Signature! Packet rejected.");
@@ -711,80 +771,7 @@ namespace SPHERE.Networking
SystemLogger.Log($"ProcessIncomingPacket: Unknown packet type: {packet.Header.Packet_Type}");
}
//switch (packetType)
//{
// case PacketBuilder.PacketType.BootstrapRequest:
// await Bootstrap.SendBootstrapResponse(node, packet);
// break;
// case PacketBuilder.PacketType.BootstrapResponse:
// await Bootstrap.ProcessBootstrapResponse(node, packet);
// break;
// case PacketBuilder.PacketType.Ping:
// await node.NetworkManager.PongPeerAsync(node, packet);
// break;
// case PacketBuilder.PacketType.Pong:
// await node.NetworkManager.ProcessPongAsync(node, packet);
// break;
// case PacketBuilder.PacketType.GetRequest:
// await node.NetworkManager.RespondToGetRequest(node, packet);
// break;
// case PacketBuilder.PacketType.BrodcastConnection:
// await node.NetworkManager.PeerListResponse(node, packet);
// break;
// case PacketBuilder.PacketType.PeerUpdate:
// await node.Peer.ProcessPeerListResponse(node, packet);
// break;
// case PacketBuilder.PacketType.SyncDHTRequest:
// await DHTManagement.ProcessSyncDHTRequest(node, packet);
// break;
// case PacketBuilder.PacketType.SyncDHTResponse:
// await DHTManagement.ProcessSyncDHTResponse(node, packet);
// break;
// case PacketBuilder.PacketType.PushTokenIssued:
// await NetworkManager.ProcessIssuedToken(node, packet);
// break;
// case PacketBuilder.PacketType.PingPal:
// await node.NetworkManager.RespondToPingPalAsync(node, packet);
// break;
// case PacketBuilder.PacketType.PongPal:
// await NetworkManager.PongPalProcess(node, packet);
// break;
// case PacketBuilder.PacketType.ReputationUpdate:
// await NetworkManager.ProcessReputationUpdate(node, packet);
// break;
// case PacketBuilder.PacketType.ReputationRequest:
// await node.NetworkManager.ReturnRequestedReputation(node, packet);
// break;
// case PacketBuilder.PacketType.ReputationResponse:
// await NetworkManager.ProcessReputationResponse(node, packet);
// break;
// case PacketBuilder.PacketType.PutRequest:
// await NetworkManager.VerifyAndBroadcastPutRequest(node, packet);
// break;
// case PacketBuilder.PacketType.PutResponse:
// await NetworkManager.ProcessIncomingVerifiedPutRequest(node, packet);
// break;
// default:
// SystemLogger.Log($"ProcessIncomingPacket:Unknown packet type: {packet.Header.Packet_Type}");
// break;
//}
}
catch (Exception ex)
{
@@ -792,6 +779,24 @@ namespace SPHERE.Networking
}
}
public IPAddress GetLocalIPAddress()
{
foreach (var netInterface in System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces())
{
var ipProps = netInterface.GetIPProperties();
foreach (var addr in ipProps.UnicastAddresses)
{
if (addr.Address.AddressFamily == AddressFamily.InterNetwork &&
!addr.Address.ToString().StartsWith("169.")) // Ignore APIPA addresses
{
return addr.Address;
}
}
}
return IPAddress.Parse("127.0.0.1"); // Fall back to loop back if no local IP is found
}
}
/// <summary>
/// The STUN server is used to get an IP and port that is open for listening for traffic without needing pinholes or port forwarding.
@@ -799,7 +804,7 @@ namespace SPHERE.Networking
///
/// The implementation here is limited and needs TURN to also be included for some situations. This as it sits is a basic prototyped temporary implementation.
///
/// Futureistlly every node should have the ability to act as a stun server or at least full Nodes. The app can use the provided ip and port for bootstrapping, to first send a STUN request.
/// Futuristically every node should have the ability to act as a stun server or at least full Nodes. The app can use the provided ip and port for bootstrapping, to first send a STUN request.
/// It will then get its IP and port back, set up its listener, then send its bootstrap request and wait to get its peers and the Chain or shards.
///
/// </summary>
@@ -826,6 +831,7 @@ namespace SPHERE.Networking
public (IPAddress PublicIP, int PublicPort) GetPublicEndpoint()
{
SystemLogger.Log($"Debug-GetPublicEndpoint: Getting Public Endpoint");
foreach (var server in stunServers)
{
try
@@ -918,10 +924,11 @@ namespace SPHERE.Networking
}
}
}
}
}

View File

@@ -20,13 +20,10 @@ namespace SPHERE.Networking
internal class NetworkManager
{
//-----Connection Calls-----\\
public async Task BroadcastConnectionToNetwork(Node node)
{
try
{
SystemLogger.Log("Debug-BrodcastConnectionToNetwork: Starting Broadcast Network Connection...");
@@ -47,7 +44,7 @@ namespace SPHERE.Networking
50
);
Packet packet = Packet.PacketBuilder.BuildPacket(header, Packet.PacketBuilder.PacketType.BrodcastConnection.ToString());
Packet packet = Packet.PacketBuilder.BuildPacket(node, header, Packet.PacketBuilder.PacketType.BrodcastConnection.ToString());
SystemLogger.Log($"Debug-BrodcastConnectionToNetwork: Packet built with NodeId: {node.Peer.NodeId}, IP: {node.Client.clientIP}, Port: {node.Client.clientListenerPort}");
// Serialize the packet into a byte array
@@ -686,7 +683,7 @@ namespace SPHERE.Networking
Packet responsePacket = Packet.PacketBuilder.BuildPacket(header, JsonSerializer.Serialize(peerList));
Packet responsePacket = Packet.PacketBuilder.BuildPacket(node, header, JsonSerializer.Serialize(peerList));
SystemLogger.Log("Debug-PeerListResponse: Serializing response payload...");
byte[] responseData = Packet.PacketBuilder.SerializePacket(responsePacket);
@@ -766,7 +763,7 @@ namespace SPHERE.Networking
1
);
var responsePacket = Packet.PacketBuilder.BuildPacket(responseHeader, JsonSerializer.Serialize(token));
var responsePacket = Packet.PacketBuilder.BuildPacket(node, responseHeader, JsonSerializer.Serialize(token));
byte[] serializedResponse = Packet.PacketBuilder.SerializePacket(responsePacket);
// Encrypt with the requester's public key
@@ -791,7 +788,7 @@ namespace SPHERE.Networking
{
if (packet == null || packet.Header == null || packet.Content == null)
{
SystemLogger.Log("Received an invalid PushTokenIssued packet.");
SystemLogger.Log($"Debug-ProcessIssuedToken: Received an invalid PushTokenIssued packet.");
return Task.CompletedTask;
}
@@ -799,7 +796,7 @@ namespace SPHERE.Networking
if (senderPeer == null)
{
SystemLogger.Log("Received an invalid PushTokenIssued packet.");
SystemLogger.Log($"Debug-ProcessIssuedToken: Received an invalid PushTokenIssued packet.");
return Task.CompletedTask;
}
@@ -808,7 +805,7 @@ namespace SPHERE.Networking
if (token == null || string.IsNullOrWhiteSpace(token.TokenId))
{
SystemLogger.Log("Received an empty or invalid PushTokenIssued payload.");
SystemLogger.Log($"Debug-ProcessIssuedToken: Received an empty or invalid PushTokenIssued payload.");
return Task.CompletedTask;
}
@@ -819,8 +816,10 @@ namespace SPHERE.Networking
}
catch (Exception ex)
{
SystemLogger.Log($"Error processing PushTokenIssued: {ex.Message}");
SystemLogger.Log($"Error-ProcessIssuedToken: processing PushTokenIssued: {ex.Message}");
}
SystemLogger.Log($"Debug-ProcessIssuedToken: Received an Issued Push Token.");
return Task.CompletedTask;
}
@@ -860,7 +859,7 @@ namespace SPHERE.Networking
throw new ArgumentException("Block ID cannot be null or empty.", nameof(blockId));
}
var existingBlock = node.ContactDHT.GetBlock(blockId);
Block existingBlock = node.ContactDHT.GetBlock(blockId);
if (existingBlock != null)
{
SystemLogger.Log("Block already exists locally.");
@@ -894,10 +893,11 @@ namespace SPHERE.Networking
node.Peer.PublicEncryptKey,
node.Client.clientListenerPort,
node.Client.clientIP.ToString(),
15 // TTL value
15
);
Packet requestPacket = Packet.PacketBuilder.BuildPacket(header, blockId);
Packet requestPacket = Packet.PacketBuilder.BuildPacket(node, header, blockId);
byte[] serializedPacket = Packet.PacketBuilder.SerializePacket(requestPacket);
@@ -944,7 +944,7 @@ namespace SPHERE.Networking
try
{
Peer senderPeer = Peer.CreatePeerFromPacket(packet);
if (packet == null || packet.Header == null)
{
SystemLogger.Log("Received an invalid GetRequest packet.");
@@ -959,45 +959,23 @@ namespace SPHERE.Networking
int newTTL = ttlValue - 1;
var requestedBlockIds = JsonSerializer.Deserialize<List<string>>(packet.Content);
string requestedBlockId = packet.Content;
SystemLogger.Log($"Received GetRequest for Block ID: {requestedBlockIds}");
SystemLogger.Log($"Received GetRequest for Block ID: {requestedBlockId}");
List<Block> requestedBlocks = new List<Block>();
List<string> notFoundBlocks = new List<string>();
Block block = node.ContactDHT.GetBlock(requestedBlockId);
// Check if we already have the requested block
foreach (var blockId in requestedBlockIds)
if (block != null)
{
Block block = node.ContactDHT.GetBlock(blockId);
if (block != null)
{
SystemLogger.Log($"Block {blockId} found locally. Adding to response list.");
requestedBlocks.Add(block);
}
else
{
SystemLogger.Log($"Block {blockId} not found locally. Adding to not found list.");
notFoundBlocks.Add(blockId);
}
}
if (requestedBlocks.Count > 0)
{
await node.NetworkManager.RetryAsync<bool>(async () =>
{
SystemLogger.Log($"Block {requestedBlockIds.Count} found locally. Sending GetResponse to requester...");
BlockResponsePayload payload = new BlockResponsePayload
{
Type = requestedBlocks[0].Header.BlockType,
Blocks = requestedBlocks
};
SystemLogger.Log($"Block {requestedBlockId} found locally. Sending GetResponse to requester...");
string serializedBlock = JsonSerializer.Serialize<Block>(block);
// Build GetResponse packet
var responseHeader = Packet.PacketBuilder.BuildPacketHeader(
@@ -1008,66 +986,75 @@ namespace SPHERE.Networking
node.Peer.PublicEncryptKey,
node.Client.clientListenerPort,
node.Client.clientIP.ToString(),
5 // TTL value for response
5
);
Packet responsePacket = Packet.PacketBuilder.BuildPacket(responseHeader, JsonSerializer.Serialize(payload));
Packet responsePacket = Packet.PacketBuilder.BuildPacket(node, responseHeader, serializedBlock);
byte[] serializedResponse = Packet.PacketBuilder.SerializePacket(responsePacket);
// Encrypt with the requester's public key
byte[] encryptedResponse = Encryption.EncryptPacketWithPublicKey(node, serializedResponse, packet.Header.PublicEncryptKey);
byte[] encryptedResponse = Encryption.EncryptPacketWithPublicKey(node, serializedResponse, senderPeer.PublicEncryptKey);
// Send the response to the requester
bool success = await Client.SendPacketToPeerAsync(node, packet.Header.IPAddress, int.Parse(packet.Header.Port), encryptedResponse);
if (success)
SystemLogger.Log($"Successfully sent GetResponse for {requestedBlockIds.Count} Blocks to {packet.Header.IPAddress}:{packet.Header.Port}");
SystemLogger.Log($"Successfully sent GetResponse for {requestedBlockId} Blocks to {packet.Header.IPAddress}:{packet.Header.Port}");
else
SystemLogger.Log($"Failed to send GetResponse for {requestedBlockIds} Blocks to {packet.Header.IPAddress}:{packet.Header.Port}");
SystemLogger.Log($"Failed to send GetResponse for {requestedBlockId} Blocks to {packet.Header.IPAddress}:{packet.Header.Port}");
return success;
});
}
// Block not found, rebroadcast the request to the closest peers
}
else
{
SystemLogger.Log($"Blocks not found locally. Rebroadcasting request to peers...");
bool success = false;
await node.NetworkManager.RetryAsync<bool>(async () =>
{
foreach (var Ids in notFoundBlocks)
{
// Get closest peers
List<Peer> closestPeers = node.RoutingTable.GetClosestPeers(Ids, 5);
if (closestPeers.Count == 0)
bool success = false;
if (newTTL >= 1)
{
await node.NetworkManager.RetryAsync<bool>(async () =>
{
SystemLogger.Log("No peers available to forward the request.");
continue;
}
packet.Header.TTL = newTTL.ToString();
byte[] serializedPacket = Packet.PacketBuilder.SerializePacket(packet);
var tasks = closestPeers.Select(async peer =>
{
SystemLogger.Log($"Forwarding GetRequest for Block {Ids} to {peer.NodeIP}:{peer.NodePort}");
try
// Get closest peers
List<Peer> closestPeers = node.RoutingTable.GetClosestPeers(block.Header.BlockId, 5);
if (closestPeers.Count == 0)
{
byte[] encryptedPacket = Encryption.EncryptPacketWithPublicKey(node, serializedPacket, peer.PublicEncryptKey);
success = await Client.SendPacketToPeerAsync(node, peer.NodeIP, peer.NodePort, encryptedPacket);
SystemLogger.Log("No peers available to forward the request.");
return false;
}
catch (Exception ex)
packet.Header.TTL = newTTL.ToString();
byte[] serializedPacket = Packet.PacketBuilder.SerializePacket(packet);
var tasks = closestPeers.Select(async peer =>
{
SystemLogger.Log($"Error forwarding GetRequest to {peer.NodeIP}:{peer.NodePort}: {ex.Message}");
}
SystemLogger.Log($"Forwarding GetRequest for Block {block.Header.BlockId} to {peer.NodeIP}:{peer.NodePort}");
try
{
byte[] encryptedPacket = Encryption.EncryptPacketWithPublicKey(node, serializedPacket, peer.PublicEncryptKey);
success = await Client.SendPacketToPeerAsync(node, peer.NodeIP, peer.NodePort, encryptedPacket);
}
catch (Exception ex)
{
SystemLogger.Log($"Error forwarding GetRequest to {peer.NodeIP}:{peer.NodePort}: {ex.Message}");
}
});
await Task.WhenAll(tasks);
return success;
});
await Task.WhenAll(tasks);
}
return success;
});
}
}
catch (Exception ex)
{
@@ -1083,57 +1070,49 @@ namespace SPHERE.Networking
try
{
if (packet == null || packet.Header == null || packet.Content == null)
Peer senderPeer = Peer.CreatePeerFromPacket(packet);
if (senderPeer == null)
{
SystemLogger.Log("Sender Peer is null.");
return;
}
if (packet == null || packet.Header == null || packet.Content == null)
{
SystemLogger.Log("Received an invalid GetResponse packet.");
return;
}
// Deserialize the payload
BlockResponsePayload payload = JsonSerializer.Deserialize<BlockResponsePayload>(packet.Content);
Block block = JsonSerializer.Deserialize<Block>(packet.Content);
if (payload == null || payload.Blocks == null || payload.Blocks.Count == 0)
if (block == null )
{
SystemLogger.Log("Received an empty or invalid GetResponse payload.");
//BroadcastReputationUpdate(node, senderPeer, Blockchain.Reputation.ReputationReason.GetTransactionFailed);
return;
}
// Process each block in the response
foreach (var block in payload.Blocks)
// Check if the block is already requested
if (!node.requestedBlocks.ContainsKey(block.Header.BlockId))
{
if (block == null || string.IsNullOrWhiteSpace(block.Header.BlockId))
{
SystemLogger.Log("Received an invalid block in GetResponse.");
continue;
}
// Check if the block is already requested
if (!node.requestedBlocks.ContainsKey(block.Header.BlockId))
{
SystemLogger.Log($"Block {block.Header.BlockId} was not requested. Ignoring.");
continue;
}
// Add the block to the DHT
node.ContactDHT.AddBlock(block);
// Remove the block from the requested list
node.requestedBlocks.TryRemove(block.Header.BlockId, out _);
SystemLogger.Log($"Successfully added block {block.Header.BlockId} to the DHT.");
SystemLogger.Log($"Block {block.Header.BlockId} was not requested. Ignoring.");
return;
}
// Add the block to the DHT
node.ContactDHT.AddBlock(block);
SystemLogger.Log($"Successfully added block {block.Header.BlockId} to the DHT.");
//Reward the sender with a Reputation Score and a Token
Peer senderPeer= Peer.CreatePeerFromPacket(packet);
TokenManager.PushToken token = node.TokenManager.CreatePushToken(node, senderPeer.NodeId);
await node.NetworkManager.SendTokenToPeer(node, senderPeer, token);
node.TokenManager.AddIssuedPushToken(token);
if (senderPeer != null)
{
TokenManager.PushToken token = node.TokenManager.CreatePushToken(node, senderPeer.NodeId);
await node.NetworkManager.SendTokenToPeer(node, senderPeer, token);
node.TokenManager.AddIssuedPushToken(token);
BroadcastReputationUpdate(node, senderPeer, Blockchain.Reputation.ReputationReason.GetContactFailed);
}
//BroadcastReputationUpdate(node, senderPeer, Blockchain.Reputation.ReputationReason.GetTransactionSuccessful);
}
catch (Exception ex)
{
@@ -1197,7 +1176,7 @@ namespace SPHERE.Networking
50 // TTL value
);
Packet putPacket = Packet.PacketBuilder.BuildPacket(header, JsonSerializer.Serialize(block));
Packet putPacket = Packet.PacketBuilder.BuildPacket(node, header, JsonSerializer.Serialize(block));
SystemLogger.Log($"Sending PutRequest to peerlist");
@@ -1279,7 +1258,7 @@ namespace SPHERE.Networking
};
Packet putPacket = Packet.PacketBuilder.BuildPacket(header, JsonSerializer.Serialize<PutRequestPayload>(payload));
Packet putPacket = Packet.PacketBuilder.BuildPacket(node, header, JsonSerializer.Serialize<PutRequestPayload>(payload));
SystemLogger.Log($"Error:-RequestPutWithToken: Sending PutRequest to peerlist");
@@ -1581,7 +1560,7 @@ namespace SPHERE.Networking
var serializedBlock = JsonSerializer.Serialize(block);
Packet responsePacket = Packet.PacketBuilder.BuildPacket(responseHeader, serializedBlock);
Packet responsePacket = Packet.PacketBuilder.BuildPacket(node, responseHeader, serializedBlock);
byte[] serializedResponse = Packet.PacketBuilder.SerializePacket(responsePacket);
// Encrypt with the requester's public key

View File

@@ -7,6 +7,9 @@ using System.Reflection.PortableExecutable;
using System.Text;
using System.Text.Json.Serialization;
using static SPHERE.Networking.Packet.PacketBuilder;
using SPHERE.Configure;
using SPHERE.Blockchain;
using System.Text.Json;
@@ -170,20 +173,49 @@ namespace SPHERE.Networking
internal static Packet BuildPacket(PacketHeader header, string message)
internal static Packet BuildPacket(Node node, PacketHeader header, string message)
{
if (Debugger.IsAttached || Debugger.IsLogging())
{
Environment.FailFast("Debugger detected! Exiting...");
}
Packet packet = new Packet
{
Header = header,
Content = message,
Signature = "TestSignature",
};
var modifiedHeader = new PacketHeader
{
NodeId = header.NodeId,
Node_Type = header.Node_Type,
IPAddress = header.IPAddress,
Port = header.Port,
PublicSignatureKey = header.PublicSignatureKey,
PublicEncryptKey = header.PublicEncryptKey,
Packet_Type = header.Packet_Type
};
var options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = false,
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
string serializedHeader = JsonSerializer.Serialize(modifiedHeader, options);
byte[] headerBytes = Encoding.UTF8.GetBytes(serializedHeader);
byte[] contentBytes = Encoding.UTF8.GetBytes(packet.Content);
int totalLength = headerBytes.Length + contentBytes.Length;
byte[] combinedBytes = new byte[totalLength];
Buffer.BlockCopy(headerBytes, 0, combinedBytes, 0, headerBytes.Length);
Buffer.BlockCopy(contentBytes, 0, combinedBytes, headerBytes.Length, contentBytes.Length);
byte[] signature = SignatureGenerator.SignByteArray(node, combinedBytes);
packet.Signature = Convert.ToBase64String(signature);
return packet;
}
@@ -410,10 +442,19 @@ namespace SPHERE.Networking
try
{
_stream.ReadTimeout = 5000;
_stream.WriteTimeout = 5000;
byte[] lengthPrefix = new byte[4];
// Read total message length
await ReadExactlyAsync(_stream, lengthPrefix, 4);
if (!await ReadExactlyAsync(_stream, lengthPrefix, 4))
{
SystemLogger.Log($"Error-ReadMessage: Failed to read message length.");
return (null, null, null);
}
int messageLength = BitConverter.ToInt32(lengthPrefix, 0);
// SystemLogger.Log($"Debug-ReadMessage: Declared Message Length: {messageLength} bytes");
@@ -427,9 +468,12 @@ namespace SPHERE.Networking
// Read the remaining packet
int remainingPacketSize = messageLength - 4;
byte[] fullPacket = new byte[remainingPacketSize];
await ReadExactlyAsync(_stream, fullPacket, remainingPacketSize);
//SystemLogger.Log($"Debug-ReadMessage: Fully Received Packet - {remainingPacketSize} bytes");
//await ReadExactlyAsync(_stream, fullPacket, remainingPacketSize);
if (!await ReadExactlyAsync(_stream, fullPacket, remainingPacketSize))
{
SystemLogger.Log($"Error-ReadMessage: Failed to read full packet. Expected {remainingPacketSize} bytes.");
return (null, null, null);
}
//Parse the packet to extract data
return ParsePacket(fullPacket);
@@ -530,13 +574,19 @@ namespace SPHERE.Networking
private static async Task<bool> ReadExactlyAsync(NetworkStream stream, byte[] buffer, int size)
{
if (stream == null || !stream.CanRead)
{
SystemLogger.Log($"Warning-ReadExactlyAsync: Stream is null or cannot be read.");
return false;
}
if (Debugger.IsAttached || Debugger.IsLogging())
{
Environment.FailFast("Debugger detected! Exiting...");
}
int totalBytesRead = 0;
try
{
while (totalBytesRead < size)

View File

@@ -39,11 +39,11 @@ namespace SPHERE.Configure
// The Local Symmetric Key is used to Encrypt the blockContact.
public static byte[] EncryptWithSymmetric(Contact contactData, byte[] key)
public static byte[] EncryptContactWithSymmetric(Contact contactData, byte[] key)
{
byte[] convertedKey = key;
string data = System.Text.Json.JsonSerializer.Serialize(contactData);
string data = JsonSerializer.Serialize(contactData);
using var aes = Aes.Create();
aes.Key = convertedKey;
aes.GenerateIV();
@@ -61,27 +61,33 @@ namespace SPHERE.Configure
return ms.ToArray(); // Return Base64-encoded encrypted data
}
public static Contact DecryptWithSymmetricKey(string encryptedData, string key)
public static Contact DecryptContactWithSymmetricKey(string data, byte[] key)
{
byte[] convertedKey = Convert.FromBase64String(key);
byte[] convertedEncryptedData = Convert.FromBase64String(encryptedData);
byte[] encryptedData = Convert.FromBase64String(data);
using var aes = Aes.Create();
// Extract IV from the encrypted data
byte[] iv = new byte[16];
Array.Copy(convertedEncryptedData, 0, iv, 0, iv.Length);
Array.Copy(encryptedData, 0, iv, 0, iv.Length);
aes.IV = iv;
aes.Key = convertedKey;
aes.Key = key;
using var decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
using var ms = new MemoryStream(convertedEncryptedData, iv.Length, convertedEncryptedData.Length - iv.Length);
using var ms = new MemoryStream(encryptedData, iv.Length, encryptedData.Length - iv.Length);
using var cryptoStream = new CryptoStream(ms, decryptor, CryptoStreamMode.Read);
using var reader = new StreamReader(cryptoStream);
string decryptedData = reader.ReadToEnd();
// Deserialize the contact from the data.
return System.Text.Json.JsonSerializer.Deserialize<Contact>(decryptedData);
Contact contact = JsonSerializer.Deserialize<Contact>(decryptedData);
if (contact != null)
{
return contact;
}
else
{
return null;
}
}
//Encrypt with a personal(public) Key Provides a secretKey to Validate its use.
@@ -295,7 +301,7 @@ namespace SPHERE.Configure
}
// Decrypts the Local Symmetric Key(LSK) with the Semi Public Key(SPK)
public static string DecryptLocalSymmetricKey(byte[] encryptedLocalSymmetricKey, byte[] semiPublicKey)
public static byte[] DecryptLocalSymmetricKey(byte[] encryptedLocalSymmetricKey, byte[] semiPublicKey)
{
// Convert the keys and encrypted data to byte arrays
@@ -315,7 +321,7 @@ namespace SPHERE.Configure
byte[] decryptedKeyBytes = reader.ReadBytes((int)(ms.Length - iv.Length));
return Convert.ToBase64String(decryptedKeyBytes); // Return Base64-encoded localSymmetricKey
return decryptedKeyBytes; // Return Base64-encoded localSymmetricKey
}
// Encrypts data using a local symmetric key and a salt
@@ -484,47 +490,57 @@ namespace SPHERE.Configure
}
// Retrieves the private Contact key from memory
internal byte[] GetPersonalKey(KeyGenerator.KeyType keyType)
internal byte[] GetPersonalKey(Node node, KeyGenerator.KeyType keyType)
{
if (keyType != KeyGenerator.KeyType.PrivatePersonalEncryptionKey || keyType != KeyGenerator.KeyType.PrivatePersonalSignatureKey || keyType != KeyGenerator.KeyType.PublicPersonalEncryptionKey || keyType != KeyGenerator.KeyType.PublicPersonalSignatureKey || keyType != KeyGenerator.KeyType.SemiPublicKey || keyType != KeyGenerator.KeyType.LocalSymmetricKey || keyType != KeyGenerator.KeyType.EncryptedLocalSymmetricKey)
{
SystemLogger.Log($"Error-GetPrivateContactKey: KeyType is not a Private Personal Key");
return null;
}
//SystemLogger.Log("Debug-GetPersonalKey: Attempting to retrieve a personal key.");
SecureString secureKey = keyType switch
{
KeyGenerator.KeyType.PrivatePersonalEncryptionKey => PrivatePersonalEncryptionKey,
KeyGenerator.KeyType.PrivatePersonalSignatureKey => PrivatePersonalSignatureKey,
KeyGenerator.KeyType.PublicPersonalSignatureKey => PublicPersonalSignatureKey,
KeyGenerator.KeyType.PublicPersonalEncryptionKey => PublicPersonalEncryptionKey,
KeyGenerator.KeyType.SemiPublicKey => SemiPublicKey,
KeyGenerator.KeyType.EncryptedLocalSymmetricKey => EncryptedLocalSymmetricKey,
KeyGenerator.KeyType.LocalSymmetricKey => LocalSymmetricKey,
KeyGenerator.KeyType.PrivatePersonalEncryptionKey => node.KeyManager.PrivatePersonalEncryptionKey,
KeyGenerator.KeyType.PrivatePersonalSignatureKey => node.KeyManager.PrivatePersonalSignatureKey,
KeyGenerator.KeyType.PublicPersonalSignatureKey => node.KeyManager.PublicPersonalSignatureKey,
KeyGenerator.KeyType.PublicPersonalEncryptionKey => node.KeyManager.PublicPersonalEncryptionKey,
KeyGenerator.KeyType.SemiPublicKey => node.KeyManager.SemiPublicKey,
KeyGenerator.KeyType.LocalSymmetricKey => node.KeyManager.LocalSymmetricKey,
KeyGenerator.KeyType.EncryptedLocalSymmetricKey => node.KeyManager.EncryptedLocalSymmetricKey,
_ => null
};
if (secureKey == null || secureKey.Length == 0)
{
throw new InvalidOperationException("Private key is not loaded in memory.");
SystemLogger.Log($"Error-GetPersonalKey: Key {keyType} is not available in memory.");
return null;
}
// Convert SecureString to String
// Convert SecureString to byte[]
IntPtr ptr = Marshal.SecureStringToGlobalAllocUnicode(secureKey);
try
{
return Convert.FromBase64String(Marshal.PtrToStringUni(ptr));
string base64Key = Marshal.PtrToStringUni(ptr);
if (string.IsNullOrEmpty(base64Key))
{
SystemLogger.Log($"Error-GetPersonalKey: Extracted key string is empty for {keyType}");
return null;
}
//SystemLogger.Log($"Debug-GetPersonalKey: Successfully retrieved {keyType}");
return Convert.FromBase64String(base64Key);
}
catch (FormatException ex)
{
SystemLogger.Log($"Error-GetPersonalKey: Failed to decode Base64 key. Reason: {ex.Message}");
return null;
}
finally
{
Marshal.ZeroFreeGlobalAllocUnicode(ptr);
Marshal.ZeroFreeGlobalAllocUnicode(ptr);
}
}
// Retrieves the private Node key from memory
internal byte[] GetNodeKey(KeyGenerator.KeyType keyType)
{
SystemLogger.Log($"Debug-GetNodeKey: Getting Node Key...@.@");
// SystemLogger.Log($"Debug-GetNodeKey: Getting Node Key...@.@");
try
{
@@ -663,60 +679,69 @@ namespace SPHERE.Configure
}
//Set the Private Personal Key in Memory
internal void SetPrivatePersonalKey(byte[] key, KeyGenerator.KeyType keyType)
internal void SetPrivatePersonalKey(Node node, byte[] key, KeyGenerator.KeyType keyType)
{
if (keyType != KeyGenerator.KeyType.PrivateNodeEncryptionKey &&
keyType != KeyGenerator.KeyType.PrivateNodeSignatureKey &&
keyType != KeyGenerator.KeyType.LocalSymmetricKey &&
keyType != KeyGenerator.KeyType.SemiPublicKey)
// SystemLogger.Log($"Debug-SetPrivatePersonalKey: Using KeyManager instance {node.KeyManager.GetHashCode()} to retrieve {keyType}");
if (key == null || key.Length == 0)
{
SystemLogger.Log("Error-SetPrivatePersonalKey: Key cannot be null or empty.");
return;
}
try
string keyString = Convert.ToBase64String(key);
SecureString newSecureString = new SecureString();
foreach (char c in keyString)
{
if (key == null || key.Length == 0)
{
SystemLogger.Log("Error- SetPrivatePersonalKey: Key cannot be null or empty.");
return;
}
SecureString newSecureString = new SecureString();
foreach (byte b in key)
{
newSecureString.AppendChar((char)b);
}
newSecureString.MakeReadOnly();
switch (keyType)
{
case KeyGenerator.KeyType.PrivateNodeEncryptionKey:
PrivatePersonalEncryptionKey?.Dispose();
PrivatePersonalEncryptionKey = newSecureString;
break;
case KeyGenerator.KeyType.PrivateNodeSignatureKey:
PrivatePersonalSignatureKey?.Dispose();
PrivatePersonalSignatureKey = newSecureString;
break;
case KeyGenerator.KeyType.SemiPublicKey:
SemiPublicKey?.Dispose();
SemiPublicKey = newSecureString;
break;
case KeyGenerator.KeyType.LocalSymmetricKey:
LocalSymmetricKey?.Dispose();
LocalSymmetricKey = newSecureString;
break;
}
// Wipe the original key from memory
Array.Clear(key, 0, key.Length);
newSecureString.AppendChar(c);
}
catch (Exception ex)
newSecureString.MakeReadOnly();
switch (keyType)
{
SystemLogger.Log($"Error- SetPrivatePersonalKey: Failed to Set Key Reason: {ex.Message}");
case KeyGenerator.KeyType.PrivatePersonalEncryptionKey:
node.KeyManager.PrivatePersonalEncryptionKey?.Dispose();
node.KeyManager.PrivatePersonalEncryptionKey = newSecureString;
// SystemLogger.Log($"Debug-SetPrivatePersonalKey: Successfully stored {keyType}");
break;
case KeyGenerator.KeyType.PrivatePersonalSignatureKey:
node.KeyManager.PrivatePersonalSignatureKey?.Dispose();
node.KeyManager.PrivatePersonalSignatureKey = newSecureString;
//SystemLogger.Log($"Debug-SetPrivatePersonalKey: Successfully stored {keyType}");
break;
case KeyGenerator.KeyType.PublicPersonalEncryptionKey:
node.KeyManager.PublicPersonalEncryptionKey?.Dispose();
node.KeyManager.PublicPersonalEncryptionKey = newSecureString;
//SystemLogger.Log($"Debug-SetPrivatePersonalKey: Successfully stored {keyType}");
break;
case KeyGenerator.KeyType.PublicPersonalSignatureKey:
node.KeyManager.PublicPersonalSignatureKey?.Dispose();
node.KeyManager.PublicPersonalSignatureKey = newSecureString;
//SystemLogger.Log($"Debug-SetPrivatePersonalKey: Successfully stored {keyType}");
break;
case KeyGenerator.KeyType.SemiPublicKey:
node.KeyManager.SemiPublicKey?.Dispose();
node.KeyManager.SemiPublicKey = newSecureString;
//SystemLogger.Log($"Debug-SetPrivatePersonalKey: Successfully stored {keyType}");
break;
case KeyGenerator.KeyType.LocalSymmetricKey:
node.KeyManager.LocalSymmetricKey?.Dispose();
node.KeyManager.LocalSymmetricKey = newSecureString;
// SystemLogger.Log($"Debug-SetPrivatePersonalKey: Successfully stored {keyType}");
break;
case KeyGenerator.KeyType.EncryptedLocalSymmetricKey:
node.KeyManager.EncryptedLocalSymmetricKey?.Dispose();
node.KeyManager.EncryptedLocalSymmetricKey = newSecureString;
//SystemLogger.Log($"Debug-SetPrivatePersonalKey: Successfully stored {keyType}");
break;
default:
SystemLogger.Log($"Error-SetPrivatePersonalKey: Unhandled KeyType {keyType}");
return;
}
}
@@ -984,7 +1009,7 @@ namespace SPHERE.Configure
{
try
{
SystemLogger.Log($"Debug-StoreKeyLocally: Attempting to Store a Key of type {keyType}");
//SystemLogger.Log($"Debug-StoreKeyLocally: Attempting to Store a Key of type {keyType}");
if (key == null || key.Length == 0)
{
@@ -996,16 +1021,16 @@ namespace SPHERE.Configure
if (File.Exists(KeyFilePath))
{
SystemLogger.Log($"Debug-StoreKeyLocally: File Path Exists - Loading existing file.");
//SystemLogger.Log($"Debug-StoreKeyLocally: File Path Exists - Loading existing file.");
newKeyStorage = LoadKeyFile() ?? new NodeKeyStorageFile();
}
else
{
SystemLogger.Log($"Debug-StoreKeyLocally: No File Existed. Creating new File...");
//SystemLogger.Log($"Debug-StoreKeyLocally: No File Existed. Creating new File...");
newKeyStorage = new NodeKeyStorageFile();
}
SystemLogger.Log($"Debug-StoreKeyLocally: Storing Keys:");
//SystemLogger.Log($"Debug-StoreKeyLocally: Storing Keys:");
switch (keyType)
{
@@ -1036,7 +1061,7 @@ namespace SPHERE.Configure
{
try
{
SystemLogger.Log($"Debug-LoadKeyFile: Loading Key File...");
// SystemLogger.Log($"Debug-LoadKeyFile: Loading Key File...");
if (!File.Exists(KeyFilePath))
{
@@ -1068,7 +1093,7 @@ namespace SPHERE.Configure
return null;
}
SystemLogger.Log($"Debug-LoadKeyFile: Successfully deserialized key file.");
// SystemLogger.Log($"Debug-LoadKeyFile: Successfully deserialized key file.");
return file;
}
catch (Exception ex)
@@ -1089,7 +1114,7 @@ namespace SPHERE.Configure
return;
}
SystemLogger.Log($"Debug-SaveKeyStorage: Saving Node Key Storage:");
//SystemLogger.Log($"Debug-SaveKeyStorage: Saving Node Key Storage:");
// Prevent saving if all keys are NULL
if (string.IsNullOrEmpty(keyStorage.NodePublicSignatureKey) &&
@@ -1112,7 +1137,7 @@ namespace SPHERE.Configure
}
File.WriteAllBytes(KeyFilePath, encryptedData);
SystemLogger.Log($"Debug-SaveKeyStorage: Successfully wrote Key to file.");
// SystemLogger.Log($"Debug-SaveKeyStorage: Successfully wrote Key to file.");
SetSecureFilePermissions(KeyFilePath);
}
@@ -1185,7 +1210,8 @@ namespace SPHERE.Configure
{
try
{
SystemLogger.Log($"Debug-UseKeyInStorageContainer: Attempting to get Key.");
// SystemLogger.Log($"Debug-UseKeyInStorageContainer: Using KeyManager instance {node.KeyManager.GetHashCode()} to retrieve {keyType}");
// SystemLogger.Log($"Debug-UseKeyInStorageContainer: Attempting to get Key.");
byte[] keyData= null;
PrivateKeyManager privateKeyManager = node.KeyManager;
@@ -1209,31 +1235,31 @@ namespace SPHERE.Configure
break;
case KeyType.PrivatePersonalEncryptionKey:
keyData = privateKeyManager.GetPersonalKey(KeyType.PrivatePersonalEncryptionKey);
keyData = privateKeyManager.GetPersonalKey(node, KeyType.PrivatePersonalEncryptionKey);
break;
case KeyType.PrivatePersonalSignatureKey:
keyData = privateKeyManager.GetPersonalKey(KeyType.PrivatePersonalSignatureKey);
keyData = privateKeyManager.GetPersonalKey(node, KeyType.PrivatePersonalSignatureKey);
break;
case KeyType.PublicPersonalEncryptionKey:
keyData = privateKeyManager.GetPersonalKey(KeyType.PrivatePersonalEncryptionKey);
keyData = privateKeyManager.GetPersonalKey(node, KeyType.PublicPersonalEncryptionKey);
break;
case KeyType.PublicPersonalSignatureKey:
keyData = privateKeyManager.GetPersonalKey(KeyType.PrivatePersonalSignatureKey);
keyData = privateKeyManager.GetPersonalKey(node, KeyType.PublicPersonalSignatureKey);
break;
case KeyType.SemiPublicKey:
keyData = privateKeyManager.GetPersonalKey(KeyType.SemiPublicKey);
keyData = privateKeyManager.GetPersonalKey(node, KeyType.SemiPublicKey);
break;
case KeyType.LocalSymmetricKey:
keyData = privateKeyManager.GetPersonalKey(KeyType.LocalSymmetricKey);
keyData = privateKeyManager.GetPersonalKey(node, KeyType.LocalSymmetricKey);
break;
case KeyType.EncryptedLocalSymmetricKey:
keyData = privateKeyManager.GetPersonalKey(KeyType.LocalSymmetricKey);
keyData = privateKeyManager.GetPersonalKey(node, KeyType.EncryptedLocalSymmetricKey);
break;
default:
@@ -1242,7 +1268,7 @@ namespace SPHERE.Configure
}
if (keyData == null || keyData.Length == 0)
{
SystemLogger.Log($"Error-UseKeyInStorageContainer: Retrieved key is null or empty for keyType: {keyType}");
// SystemLogger.Log($"Error-UseKeyInStorageContainer: Retrieved key is null or empty for keyType: {keyType}");
throw new Exception($"Key retrieval failed for {keyType}, keyData is null or empty.");
}
return keyData;

View File

@@ -1,44 +0,0 @@
using System;
using System.IO;
using System.Reflection;
namespace SPHERE.Configure
{
public static class SecureLoader
{
// private static bool _isLoaded = false;
// public static void EnsureLoaded()
// {
// if (_isLoaded) return; // Prevent redundant loading
// _isLoaded = true;
// string basePath = AppDomain.CurrentDomain.BaseDirectory;
// string[] possiblePaths =
// {
// Path.Combine(basePath, "Packet.dll"), // Standard location
// Path.Combine(basePath, "libs", "Packet.dll"), // Alternative "libs" directory
// Path.Combine(basePath, "bin", "Packet.dll"), // If it's inside a bin folder
// Path.Combine(basePath, "lib", "net8.0", "Packet.dll") // NuGet installation path
//};
// string packetDllPath = possiblePaths.FirstOrDefault(File.Exists)
// ?? throw new FileNotFoundException("Packet.dll not found in expected locations.");
// SystemLogger.Log($"[INFO] Dynamically loading Packet.dll from: {packetDllPath}");
// // 🔥 Load with LoadFrom() to properly register the assembly
// Assembly packetAssembly = Assembly.LoadFrom(packetDllPath);
// // 🔄 Validate successful loading
// if (packetAssembly == null)
// throw new InvalidOperationException("Failed to load Packet.dll into AppDomain.");
// SystemLogger.Log("[INFO] Packet.dll loaded successfully.");
// }
}
}

View File

@@ -108,18 +108,14 @@ namespace SPHERE.Configure
public static byte[] SignByteArray(Node node, byte[] data)
{
bool isTesting = Environment.GetEnvironmentVariable("SPHERE_TEST_MODE") == "true";
if (isTesting)
{
// Create the signature using the private key
try
{
using (var ecdsa = ECDsa.Create())
{
byte[] hash = SHA256.HashData(data);
//byte[] hash = SHA256.HashData(data);
ecdsa.ImportPkcs8PrivateKey(node.KeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PrivateNodeSignatureKey), out _);
byte[] signature = ecdsa.SignData(hash, HashAlgorithmName.SHA256);
byte[] signature = ecdsa.SignData(data, HashAlgorithmName.SHA256);
// Return the signature as a Base64-encoded string
return signature;
@@ -131,31 +127,7 @@ namespace SPHERE.Configure
SystemLogger.Log(ex.Message);
return null;
}
}
else
{
// Create the signature using the private key
try
{
using (var ecdsa = ECDsa.Create())
{
byte[] hash = SHA256.HashData(data);
ecdsa.ImportPkcs8PrivateKey(node.KeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PrivateNodeSignatureKey), out _);
byte[] signature = ecdsa.SignHash(hash);
// Return the signature as a Base64-encoded string
return signature;
}
}
catch (Exception ex)
{
SystemLogger.Log(ex.Message);
return null;
}
}
}
// Verify a byte array using the public key
@@ -163,20 +135,22 @@ namespace SPHERE.Configure
{
try
{
// Convert the Base64 public key back to a byte array
byte[] publicKeyBytes = publicKey;
// Import the public key
using (ECDsa ecdsa = ECDsa.Create())
{
ecdsa.ImportSubjectPublicKeyInfo(publicKeyBytes, out _);
ecdsa.ImportSubjectPublicKeyInfo(publicKey, out _);
// Convert the signature back to a byte array
byte[] signatureBytes = signature;
byte[] receivedHash = SHA256.HashData(data);
//byte[] receivedHash = SHA256.HashData(data);
bool isValid = ecdsa.VerifyData(data, signature, HashAlgorithmName.SHA256);
// Verify the signature
return ecdsa.VerifyHash(receivedHash, signatureBytes);
//return ecdsa.VerifyHash(receivedHash, signatureBytes);
if (!isValid)
{
SystemLogger.Log("Signature verification failed.");
}
return isValid;
}
}
catch (Exception ex)

View File

@@ -186,6 +186,11 @@ namespace SPHERE.Configure
{
Peer peer = new Peer();
List<Peer> peers = node.RoutingTable.GetBestReputationPeers(node.Peer.NodeId, 10);
if(peers.Count==0)
{
SystemLogger.Log("No peers found Skipping Ping ");
return;
}
Random rnd = new Random();
int r = rnd.Next(peers.Count);
peer = peers[r];
@@ -235,8 +240,13 @@ namespace SPHERE.Configure
SystemLogger.Log("Broadcasting peer ping to all known peers...");
List<Peer> peers = node.RoutingTable.GetAllPeers();
if (peers.Count == 0)
{
SystemLogger.Log("No peers found Skipping Auto Broadcast ping ");
return;
}
foreach (var peer in peers)
foreach (var peer in peers)
{
node.NetworkManager.PingPeerAsync(node, peer);
}

View File

@@ -41,7 +41,7 @@ namespace SPHERE.Configure.Logging
}
else
{
// Console.WriteLine(message);
Console.WriteLine(message);
}

View File

@@ -56,17 +56,12 @@ namespace SPHERE.Security
LocalSymmetricKey,
SemiPublicKey,
CNGCert,
//PublicTestNodeSignatureKey,
//PrivateTestNodeSignatureKey,
//PublicTestNodeEncryptionKey,
//PrivateTestNodeEncryptionKey,
}
internal static void GeneratePersonalKeyPairSets(Password exportPassword)
internal static void GeneratePersonalKeyPairSets(Node node)
{
using var signaturePair = ECDsa.Create(ECCurve.NamedCurves.nistP256);
using var encryptPair = ECDiffieHellman.Create(ECCurve.NamedCurves.nistP256);
PrivateKeyManager PrivateKeyManager = new();
PrivateKeyManager PrivateKeyManager = node.KeyManager;
if (signaturePair == null || encryptPair == null)
{
throw new InvalidOperationException("Failed to create cryptographic key pairs.");
@@ -79,16 +74,10 @@ namespace SPHERE.Security
try
{
PrivateKeyManager.SetPrivatePersonalKey(privateSignatureKey, KeyType.PrivatePersonalSignatureKey);
PrivateKeyManager.SetPrivatePersonalKey(publicSignatureKey, KeyType.PublicPersonalSignatureKey);
PrivateKeyManager.SetPrivatePersonalKey(privateEncryptionKey, KeyType.PrivatePersonalEncryptionKey);
PrivateKeyManager.SetPrivatePersonalKey(publicEncryptionKey, KeyType.PublicPersonalEncryptionKey);
//ServiceAccountManager.StorePrivateKeyInContainerWithExportPlainText(privateSignatureKey, KeyType.PrivatePersonalSignatureKey, exportPassword);
//ServiceAccountManager.StoreKeyInContainerWithExport(publicSignatureKey, KeyType.PublicPersonalSignatureKey);
//ServiceAccountManager.StorePrivateKeyInContainerWithExportPlainText(privateEncryptionKey, KeyType.PrivatePersonalEncryptionKey, exportPassword);
//ServiceAccountManager.StoreKeyInContainerWithExport(publicEncryptionKey, KeyType.PublicPersonalEncryptionKey);
PrivateKeyManager.SetPrivatePersonalKey(node, privateSignatureKey, KeyType.PrivatePersonalSignatureKey);
PrivateKeyManager.SetPrivatePersonalKey(node, publicSignatureKey, KeyType.PublicPersonalSignatureKey);
PrivateKeyManager.SetPrivatePersonalKey(node, privateEncryptionKey, KeyType.PrivatePersonalEncryptionKey);
PrivateKeyManager.SetPrivatePersonalKey(node, publicEncryptionKey, KeyType.PublicPersonalEncryptionKey);
}
catch (Exception ex)

View File

@@ -11,6 +11,10 @@ using static SPHERE.Blockchain.Contact;
using System;
using System.Xml.Linq;
using static SPHERE.Networking.Packet;
using SPHERE.Configure;
using static SPHERE.Security.KeyGenerator;
using System.Text.Json;
using System.Diagnostics.Eventing.Reader;
@@ -59,7 +63,7 @@ namespace SPHERE.TestingLib
Console.WriteLine($"Debug: Starting Create Client ");
Client client = new Client();
client.clientListenerPort = testClientListenerPort;
client.clientIP = IPAddress.Parse(testClientIP);
client.clientIP = client.GetLocalIPAddress();
Console.WriteLine($"Debug: Starting Create TestNode ");
try
@@ -74,23 +78,6 @@ namespace SPHERE.TestingLib
throw;
}
try
{
Console.WriteLine("Retrieving Keys from Storage...");
byte[] publicSigKey = testNode.KeyManager.UseKeyInStorageContainer(testNode, KeyGenerator.KeyType.PublicNodeSignatureKey);
byte[] privateSigKey = testNode.KeyManager.UseKeyInStorageContainer(testNode, KeyGenerator.KeyType.PrivateNodeSignatureKey);
byte[] publicEncKey = testNode.KeyManager.UseKeyInStorageContainer(testNode, KeyGenerator.KeyType.PublicNodeEncryptionKey);
byte[] privateEncKey = testNode.KeyManager.UseKeyInStorageContainer(testNode, KeyGenerator.KeyType.PrivateNodeEncryptionKey);
string sigKeyBase64 = Convert.ToBase64String(publicSigKey);
string encKeyBase64 = Convert.ToBase64String(publicEncKey);
}
catch (Exception ex)
{
Console.WriteLine($"Error Retrieving Keys: {ex.Message}");
throw;
}
try
{
@@ -178,6 +165,7 @@ namespace SPHERE.TestingLib
}
Console.WriteLine("Node Created Successfully!");
testNode.Client.StartClientListenerAsync(testNode);
return testNode;
}
catch (Exception ex)
@@ -349,7 +337,6 @@ namespace SPHERE.TestingLib
PreviousHash = "PreviousHashExample",
BlockCreationTime = DateTime.UtcNow,
LastUpdateTime = DateTime.UtcNow,
EncryptionAlgorithm = "AES256",
KeyUsagePolicies = "MESSAGE_ENCRYPTION_ONLY",
PublicSignatureKey = peer.PublicSignatureKey,
PublicEncryptionKey = peer.PublicEncryptKey,
@@ -569,53 +556,23 @@ namespace SPHERE.TestingLib
}
}
public static Contact TestCreateNewContact(string displayName, string name, string blockId, string? avatarURL, string? description, Password privateKeyPassword)
{
var semiPublicKey = testSemiPublicKey;
var localSymmetricKey = testLocalSymmetricKey;
var encryptedLocalSymmetricKey = testLocalEncryptedSymmetricKey;
ContactKeys keys = new ContactKeys
{
PublicPersonalEncryptionKey = TestUseKeyInStorageContainer(KeyGenerator.KeyType.PublicPersonalEncryptionKey),
PublicPersonalSignatureKey = TestUseKeyInStorageContainer(KeyGenerator.KeyType.PublicPersonalSignatureKey),
SemiPublicKey = TestUseKeyInStorageContainer(KeyGenerator.KeyType.SemiPublicKey),
LocalSymmetricKey = TestUseKeyInStorageContainer(KeyGenerator.KeyType.LocalSymmetricKey)
};
ContactMetaData metaData = new ContactMetaData
{
DisplayName = displayName,
Name = name,
AvatarURLHash = avatarURL,
Description = description,
};
Contact contact = new Contact
{
MetaData = metaData,
Keys = keys,
};
return contact;
}
public class NodeManager
public class NodeManager
{
public static List<Node> Nodes = new List<Node>();
public static void CreateFakeNodeTest(int nodeToMake)
public static void CreateFakeNodeTest(int nodeToMake, bool? silent)
{
Console.WriteLine("Setting test Variable True.");
Environment.SetEnvironmentVariable("SPHERE_TEST_MODE", "true");
string testModeEnv = Environment.GetEnvironmentVariable("SPHERE_TEST_MODE");
Console.WriteLine($"SPHERE_TEST_MODE= {testModeEnv}.");
if (silent != null && silent != true)
{
Console.WriteLine("Setting test Variable True.");
Console.WriteLine($"SPHERE_TEST_MODE= {testModeEnv}.");
}
for (int i = 0; i < nodeToMake; i++)
{
try
@@ -623,29 +580,40 @@ namespace SPHERE.TestingLib
Console.WriteLine("Creating a test node with a fake STUN...");
// Create a test node
Console.WriteLine("Starting testing.CreateTestNodeWithFakeSTUNAsync.");
Node testNode = CreateTestNodeWithFakeSTUNAsync(NodeType.Full);
Console.WriteLine("\n=== Node Created ===");
Console.WriteLine($"Node ID: {testNode.Peer.NodeId}");
Console.WriteLine($"Node IP: {testNode.Peer.NodeIP}");
Console.WriteLine($"Node Port: {testNode.Peer.NodePort}");
Console.WriteLine($"Node Type: {testNode.Peer.Node_Type}");
Console.WriteLine($"Public Signature Key: {testNode.Peer.PublicSignatureKey}");
Console.WriteLine($"Public Encryption Key: {testNode.Peer.PublicEncryptKey}");
if (silent != null && silent != true)
{
Console.WriteLine("\n=== Node Created ===");
Console.WriteLine($"Node ID: {testNode.Peer.NodeId}");
Console.WriteLine($"Node IP: {testNode.Peer.NodeIP}");
Console.WriteLine($"Node Port: {testNode.Peer.NodePort}");
Console.WriteLine($"Node Type: {testNode.Peer.Node_Type}");
Console.WriteLine($"Public Signature Key: {testNode.Peer.PublicSignatureKey}");
Console.WriteLine($"Public Encryption Key: {testNode.Peer.PublicEncryptKey}");
Console.WriteLine("\n=== Routing Table ===");
Console.WriteLine("\n=== Routing Table ===");
}
int totalPeers = testNode.RoutingTable.GetAllPeers().Count();
Console.WriteLine($"\nRouting Table Contains {totalPeers}..");
Console.WriteLine($"First 5 Peers...");
if (silent != null && silent != true)
{
Console.WriteLine($"\nRouting Table Contains {totalPeers}..");
Console.WriteLine($"First 5 Peers...");
}
int totalPeersCountDown = 5;
foreach (var peer in testNode.RoutingTable.GetAllPeers())
{
if (totalPeersCountDown > 0)
{
Console.WriteLine($"Peer ID: {peer.NodeId}, IP: {peer.NodeIP}, Port: {peer.NodePort}, Trust Score: {peer.Reputation}");
totalPeersCountDown--;
if (silent != null && silent != true)
{
Console.WriteLine($"Peer ID: {peer.NodeId}, IP: {peer.NodeIP}, Port: {peer.NodePort}, Trust Score: {peer.Reputation}");
}
totalPeersCountDown--;
}
else
{
@@ -653,16 +621,23 @@ namespace SPHERE.TestingLib
}
}
Console.WriteLine("\n=== DHT Blocks ===");
int totalBlocks = testNode.ContactDHT.GetTotalBlockCount();
Console.WriteLine($"\nDHT Contains {totalBlocks}..");
Console.WriteLine($"First 5 Blocks...");
if (silent != null && silent != true)
{
Console.WriteLine("\n=== DHT Blocks ===");
Console.WriteLine($"\nDHT Contains {totalBlocks}..");
Console.WriteLine($"First 5 Blocks...");
}
int totalBlocksCountDown = 5;
foreach (var block in testNode.ContactDHT.GetCurrentState())
{
if (totalBlocksCountDown > 0)
{
Console.WriteLine($"Block ID: {block.Header.BlockId}, Created: {block.Header.BlockCreationTime}, Updated: {block.Header.LastUpdateTime}");
if (silent != null && silent != true)
{
Console.WriteLine($"Block ID: {block.Header.BlockId}, Created: {block.Header.BlockCreationTime}, Updated: {block.Header.LastUpdateTime}");
}
totalBlocksCountDown--;
}
else
@@ -671,7 +646,10 @@ namespace SPHERE.TestingLib
}
}
Console.WriteLine("\nTest node creation completed successfully.");
if (silent != null && silent != true)
{
Console.WriteLine("\nTest node creation completed successfully.");
}
}
catch (Exception ex)
{
@@ -685,13 +663,13 @@ namespace SPHERE.TestingLib
}
}
Console.ReadLine(); // Keep the console open
Console.ReadLine();
}
public static async Task TestBootstrap()
{
Node hostNode = new Node();
try
{
Environment.SetEnvironmentVariable("SPHERE_TEST_MODE", "true");
@@ -701,10 +679,9 @@ namespace SPHERE.TestingLib
try
{
//Create a Full Fake Node DHT and RT and assign as HOST
CreateFakeNodeTest(1);
CreateFakeNodeTest(1,false);
hostNode = GetFirstNode();
Console.WriteLine($"Starting hostNode Listener at {hostNode.Client.clientIP}:{hostNode.Client.clientListenerPort}");
hostNode.Client.StartClientListenerAsync(hostNode, hostNode.Client);
Console.WriteLine($"hostNode Created Successfully");
Console.WriteLine($"hostNode DHT size is {hostNode.ContactDHT.GetTotalBlockCount()}");
Console.WriteLine($"hostNode Routing Table size is {hostNode.RoutingTable.GetAllPeers().Count()}");
@@ -714,14 +691,14 @@ namespace SPHERE.TestingLib
Console.WriteLine($"Error: Creating hostNode. {ex.Message}");
throw new Exception();
}
Node babyNode = new Node();
Node babyNode = Node.CreateNodeUsingSTUN(NodeType.Full);
try
{
// Create a babyNode with no Rt or DHT.
babyNode = CreateTestNodeWithNoDHTorRoutingTable(NodeType.Full);
Console.WriteLine($"Creating babyNode");
// Create a babyNode with no Rt or DHT.
Console.WriteLine($"babyNode Created Successfully");
Console.WriteLine($"Starting babyNode Listener at {babyNode.Client.clientIP}:{babyNode.Client.clientListenerPort}");
babyNode.Client.StartClientListenerAsync(babyNode, babyNode.Client);
Console.WriteLine($"Starting babyNode Listener at {babyNode.Client.clientIP.ToString()}:{babyNode.Client.clientListenerPort}");
Console.WriteLine($"babyNode DHT Starting size is {babyNode.ContactDHT.GetTotalBlockCount()}");
Console.WriteLine($"babyNode Routing Table Starting size is {babyNode.RoutingTable.GetAllPeers().Count()}");
@@ -741,10 +718,10 @@ namespace SPHERE.TestingLib
}
catch (Exception ex)
{
Console.WriteLine($"Error: Failed to send BootStrapRequest");
Console.WriteLine($"Error: Failed to send BootStrapRequest. Reason: {ex.Message}");
}
await Task.Delay(300); // A slight delay to allow async operations to settle (optional)
await Task.Delay(300); // A slight delay to allow async operations to settle (optional)
Console.WriteLine($"babyNode has processed the BootStrap.");
Console.WriteLine($"babyNode finished the test with a DHT of size: {babyNode.ContactDHT.GetTotalBlockCount()}");
Console.WriteLine($"babyNode finished the test with a Routing Table of size: {babyNode.RoutingTable.GetAllPeers().Count()}");
@@ -780,7 +757,7 @@ namespace SPHERE.TestingLib
// Reset and create test nodes
Nodes.Clear();
CreateFakeNodeTest(5);
CreateFakeNodeTest(5, false);
hostNode1 = Nodes[0];
hostNodes.Add(hostNode1);
@@ -829,21 +806,13 @@ namespace SPHERE.TestingLib
babyNode.RoutingTable.ClearRoutingTable();
babyNode.RoutingTable.AddPeer(hostNode4.Peer);
foreach (var node in hostNodes)
{
node.Client.StartClientListenerAsync(node, node.Client);
}
babyNode.Client.StartClientListenerAsync(babyNode, babyNode.Client);
// Broadcasting network connection
Console.WriteLine("Debug-TestBrodcastToPeers: babyNode Broadcasting Connection to Network...");
await babyNode.NetworkManager.BroadcastConnectionToNetwork(babyNode);
Console.WriteLine("Debug-TestBrodcastToPeers: babyNode Broadcast completed.");
// Print routing table sizes AFTER broadcast
// 🕒 Wait for peer propagation
// Wait for peer propagation
await Task.Delay(TimeSpan.FromSeconds(2)); // Adjust delay if needed
// Print routing table sizes AFTER broadcast
@@ -861,6 +830,7 @@ namespace SPHERE.TestingLib
Console.WriteLine($"Debug-TestBrodcastToPeers: [ERROR] Stack Trace: {ex.StackTrace}");
throw;
}
Console.ReadLine();
}
@@ -886,6 +856,135 @@ namespace SPHERE.TestingLib
return Nodes[0];
}
public static async Task TestGetBlockProcess()
{
Environment.SetEnvironmentVariable("SPHERE_TEST_MODE", "true");
string testModeEnv = Environment.GetEnvironmentVariable("SPHERE_TEST_MODE");
Console.WriteLine($"Debug-TestGetBlockProcess: SPHERE_TEST_MODE = {testModeEnv}");
List<Node> hostNodes = new List<Node>();
Node hostNode1 = new Node();
Node hostNode2 = new Node();
Node hostNode3 = new Node();
Node hostNode4 = new Node();
Node babyNode = new Node();
try
{
Console.WriteLine("Debug-TestGetBlockProcess: Initializing test environment...");
// Reset and create test nodes
Nodes.Clear();
CreateFakeNodeTest(5,true);
hostNode1 = Nodes[0];
hostNodes.Add(hostNode1);
hostNode2 = Nodes[1];
hostNodes.Add(hostNode2);
hostNode3 = Nodes[2];
hostNodes.Add(hostNode3);
hostNode4 = Nodes[3];
hostNodes.Add(hostNode4);
// Clearing routing tables to prevent stale data
hostNode1.RoutingTable.ClearRoutingTable();
hostNode2.RoutingTable.ClearRoutingTable();
hostNode3.RoutingTable.ClearRoutingTable();
hostNode4.RoutingTable.ClearRoutingTable();
// Adding initial peer connections
hostNode1.RoutingTable.AddPeer(hostNode2.Peer);
hostNode2.RoutingTable.AddPeer(hostNode1.Peer);
hostNode3.RoutingTable.AddPeer(hostNode2.Peer);
hostNode4.RoutingTable.AddPeer(hostNode3.Peer);
// Create a baby node and add a connection
Console.WriteLine("Debug-TestGetBlockProcess: Creating babyNode...@5");
babyNode = Nodes[4];
babyNode.RoutingTable.ClearRoutingTable();
hostNode1.RoutingTable.AddPeer(babyNode.Peer);
hostNode2.RoutingTable.AddPeer(babyNode.Peer);
hostNode3.RoutingTable.AddPeer(babyNode.Peer);
hostNode4.RoutingTable.AddPeer(babyNode.Peer);
babyNode.RoutingTable.AddPeer(hostNode1.Peer);
babyNode.RoutingTable.AddPeer(hostNode2.Peer);
babyNode.RoutingTable.AddPeer(hostNode3.Peer);
babyNode.RoutingTable.AddPeer(hostNode4.Peer);
//build a contact
string alias = "@SphereTest";
string name = "Kenneth:Lasyone";
string contactId = Node.GenerateKademliaId();
Password password = Password.GenerateRandomPassword();
string pin = "12345";
Contact newContact = Contact.CreateNewContact(hostNode1, contactId , alias, name, password, pin);
//add it to a block
Block block = Block.CreateContactBlock(hostNode1, "UNKNOWN", newContact);
SystemLogger.Log($"Debug-TestGetBlockProcess: Contact Length on HostNode {block.EncryptedContact.Length}.");
// add that block to a host.
hostNode1.ContactDHT.AddBlock(block);
SystemLogger.Log($"Debug-TestGetBlockProcess: BabyNode requesting block with ID of {block.Header.BlockId}.");
await NetworkManager.RequestBlockFromNetwork(babyNode, block.Header.BlockId);
await Task.Delay(TimeSpan.FromSeconds(5));
Block recievedBlock = babyNode.ContactDHT.GetBlock(block.Header.BlockId);
string recievedContact = recievedBlock.EncryptedContact;
if (recievedBlock!=null)
{
SystemLogger.Log($"Debug-TestGetBlockProcess: BabyNode Has found the block with ID of {recievedBlock.Header.BlockId}.");
}
else
{
SystemLogger.Log($"Debug-TestGetBlockProcess: BabyNode did not find the block after requesting.");
return;
}
SystemLogger.Log($"Debug-TestGetBlockProcess: Received Contact Length on BabyNode {recievedBlock.EncryptedContact.Length}.");
byte[] LocalSymetricKey = Encryption.DecryptLocalSymmetricKey(recievedBlock.EncryptedLocalSymmetricKey, newContact.Keys.SemiPublicKey);
Contact incomingContact = DecryptAndBuildContact(recievedContact, LocalSymetricKey);
if (incomingContact != null)
{
SystemLogger.Log($"Debug-TestGetBlockProcess: BabyNode Has found the Contact with ID of {incomingContact.MetaData.ContactID}.");
SystemLogger.Log($"Debug-TestGetBlockProcess: BabyNode Has found the Contact with Name of {incomingContact.MetaData.Name}.");
SystemLogger.Log($"Debug-TestGetBlockProcess: BabyNode Has found the Contact with DisplayName of {incomingContact.MetaData.DisplayName}.");
SystemLogger.Log($"Debug-TestGetBlockProcess: BabyNode Has successfully Completed the test. .");
}
else
{
SystemLogger.Log($"Debug-TestGetBlockProcess: BabyNode Failed to access Contact {recievedBlock.Header.BlockId}.");
return;
}
}
catch (Exception ex)
{
Console.WriteLine($"Debug-TestGetBlockProcess: [ERROR] {ex.Message}");
Console.WriteLine($"Debug-TestGetBlockProcess: [ERROR] Stack Trace: {ex.StackTrace}");
throw;
}
Console.ReadLine();
}
}
}