mirror of
https://github.com/kl3mta3/SPHERE.git
synced 2025-12-30 13:39:47 -06:00
Debugged Get requests and Push Token Issuance
This commit is contained in:
@@ -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),
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.");
|
||||
// }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace SPHERE.Configure.Logging
|
||||
}
|
||||
else
|
||||
{
|
||||
// Console.WriteLine(message);
|
||||
Console.WriteLine(message);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user