main: Added HIP-02 to sending HNS

This commit is contained in:
Nathan Woodburn 2023-06-15 13:46:45 +10:00
parent 2572b17898
commit 5323a8ff0d
Signed by: nathanwoodburn
GPG Key ID: 203B000478AD0EF1
3 changed files with 204 additions and 28 deletions

View File

@ -27,6 +27,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="DnsClient" Version="1.7.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="QRCoder" Version="1.4.3" />
</ItemGroup>

View File

@ -75,6 +75,7 @@ namespace FireWallet
labelBalance = new Label();
buttonRenewAll = new Button();
panelSend = new Panel();
labelSendingHIPAddress = new Label();
checkBoxSendSubFee = new CheckBox();
buttonSendMax = new Button();
buttonSendHNS = new Button();
@ -86,6 +87,7 @@ namespace FireWallet
labelSendingAmount = new Label();
labelSendingTo = new Label();
labelSendPrompt = new Label();
labelHIPArrow = new Label();
panelRecieve = new Panel();
buttonAddressVerify = new Button();
pictureBoxReceiveQR = new PictureBox();
@ -557,6 +559,7 @@ namespace FireWallet
//
// panelSend
//
panelSend.Controls.Add(labelSendingHIPAddress);
panelSend.Controls.Add(checkBoxSendSubFee);
panelSend.Controls.Add(buttonSendMax);
panelSend.Controls.Add(buttonSendHNS);
@ -568,12 +571,23 @@ namespace FireWallet
panelSend.Controls.Add(labelSendingAmount);
panelSend.Controls.Add(labelSendingTo);
panelSend.Controls.Add(labelSendPrompt);
panelSend.Location = new Point(1113, 42);
panelSend.Controls.Add(labelHIPArrow);
panelSend.Location = new Point(138, 33);
panelSend.Name = "panelSend";
panelSend.Size = new Size(974, 521);
panelSend.TabIndex = 2;
panelSend.Visible = false;
//
// labelSendingHIPAddress
//
labelSendingHIPAddress.AutoSize = true;
labelSendingHIPAddress.Location = new Point(375, 130);
labelSendingHIPAddress.Name = "labelSendingHIPAddress";
labelSendingHIPAddress.Size = new Size(64, 15);
labelSendingHIPAddress.TabIndex = 17;
labelSendingHIPAddress.Text = "To Address";
labelSendingHIPAddress.Visible = false;
//
// checkBoxSendSubFee
//
checkBoxSendSubFee.AutoSize = true;
@ -616,11 +630,11 @@ namespace FireWallet
//
labelSendingError.AutoSize = true;
labelSendingError.Font = new Font("Segoe UI", 12F, FontStyle.Regular, GraphicsUnit.Point);
labelSendingError.Location = new Point(615, 131);
labelSendingError.Location = new Point(679, 130);
labelSendingError.Name = "labelSendingError";
labelSendingError.Size = new Size(52, 21);
labelSendingError.Size = new Size(78, 21);
labelSendingError.TabIndex = 13;
labelSendingError.Text = "label1";
labelSendingError.Text = "labelError";
labelSendingError.Visible = false;
//
// labelSendingFee
@ -691,6 +705,17 @@ namespace FireWallet
labelSendPrompt.TabIndex = 0;
labelSendPrompt.Text = "Send HNS";
//
// labelHIPArrow
//
labelHIPArrow.AutoSize = true;
labelHIPArrow.Font = new Font("Segoe UI", 18F, FontStyle.Bold, GraphicsUnit.Point);
labelHIPArrow.Location = new Point(346, 119);
labelHIPArrow.Name = "labelHIPArrow";
labelHIPArrow.Size = new Size(32, 32);
labelHIPArrow.TabIndex = 18;
labelHIPArrow.Text = "⮡ ";
labelHIPArrow.Visible = false;
//
// panelRecieve
//
panelRecieve.Controls.Add(buttonAddressVerify);
@ -1044,12 +1069,12 @@ namespace FireWallet
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(1152, 575);
Controls.Add(panelSend);
Controls.Add(panelSettings);
Controls.Add(panelaccount);
Controls.Add(panelPortfolio);
Controls.Add(panelRecieve);
Controls.Add(panelDomains);
Controls.Add(panelSend);
Controls.Add(panelNav);
Controls.Add(statusStripmain);
Icon = (Icon)resources.GetObject("$this.Icon");
@ -1178,5 +1203,7 @@ namespace FireWallet
private ToolStripMenuItem githubToolStripMenuItem;
private ToolStripMenuItem websiteToolStripMenuItem;
private ToolStripMenuItem supportDiscordServerToolStripMenuItem;
private Label labelHIPArrow;
private Label labelSendingHIPAddress;
}
}

View File

@ -10,6 +10,10 @@ using System.Text;
using System.Security.Policy;
using System.Windows.Forms;
using System.Net;
using DnsClient;
using DnsClient.Protocol;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
namespace FireWallet
{
@ -199,27 +203,27 @@ namespace FireWallet
if (!Directory.Exists(dir + "hsd"))
{
NotifyForm Notifyinstall = new NotifyForm("Installing hsd\nThis may take a few minutes\nDo not close FireWallet", false);
Notifyinstall.Show();
// Wait for the notification to show
await Task.Delay(1000);
Notifyinstall.Show();
// Wait for the notification to show
await Task.Delay(1000);
string repositoryUrl = "https://github.com/handshake-org/hsd.git";
string destinationPath = dir + "hsd";
CloneRepository(repositoryUrl, destinationPath);
string repositoryUrl = "https://github.com/handshake-org/hsd.git";
string destinationPath = dir + "hsd";
CloneRepository(repositoryUrl, destinationPath);
Notifyinstall.CloseNotification();
Notifyinstall.Dispose();
}
if (!Directory.Exists(dir + "hsd\\node_modules"))
{
AddLog("HSD install failed");
Notifyinstall.CloseNotification();
Notifyinstall.Dispose();
}
if (!Directory.Exists(dir + "hsd\\node_modules"))
{
AddLog("HSD install failed");
this.Close();
return false;
}
}
}
hsdProcess = new Process();
@ -280,9 +284,9 @@ namespace FireWallet
}
}
hsdProcess.Start();
// Wait for HSD to start
await Task.Delay(2000);
@ -1084,17 +1088,17 @@ namespace FireWallet
{
try
{
string response = await APIGet("fee", false);
string response = await APIPost("", false, "{\"method\": \"estimatefee\",\"params\": [ 3 ]}");
JObject resp = JObject.Parse(response);
decimal fee = Convert.ToDecimal(resp["rate"].ToString());
fee = fee / 1000000;
if (fee < 0.0001m) fee = 1;
string result = resp["result"].ToString();
decimal fee = decimal.Parse(result);
if (fee < 0.001m) fee = 1;
return fee.ToString();
//return resp["rate"].ToString();
}
catch
{
AddLog("GetFee Error");
return "1";
}
}
@ -1160,6 +1164,7 @@ namespace FireWallet
labelSendingMax.Text = "Max: " + balance.ToString() + " HNS";
textBoxSendingTo.Focus();
string fee = await GetFee();
labelSendingFee.Text = "Est. Fee: " + fee + " HNS";
labelSendingError.Hide();
@ -1255,14 +1260,96 @@ namespace FireWallet
}
#endregion
#region Send
// Store TLSA hash
private string TLSA = "";
private async void textBoxSendingTo_Leave(object sender, EventArgs e)
{
labelSendingError.Hide();
labelHIPArrow.Hide();
labelSendingHIPAddress.Hide();
if (textBoxSendingTo.Text == "") return;
if (textBoxSendingTo.Text.Substring(0, 1) == "@")
{
labelSendingError.Show();
labelSendingError.Text = "HIP-02 Not supported yet";
return;
string domain = textBoxSendingTo.Text.Substring(1);
try
{
IPAddress iPAddress = null;
TLSA = "";
// Create an instance of LookupClient using the custom options
NameServer nameServer = new NameServer(IPAddress.Parse("127.0.0.1"), 5350);
var options = new LookupClientOptions(nameServer);
options.EnableAuditTrail = true;
options.UseTcpOnly = true;
options.Recursion = true;
options.UseCache = false;
options.RequestDnsSecRecords = true;
options.Timeout = TimeSpan.FromSeconds(5);
var client = new LookupClient(options);
// Perform the DNS lookup for the specified domain using DNSSec
var result = client.Query(domain, QueryType.A);
// Display the DNS lookup results
foreach (var record in result.Answers.OfType<ARecord>())
{
iPAddress = record.Address;
}
if (iPAddress == null)
{
labelSendingError.Show();
labelSendingError.Text = "HIP-02 lookup failed";
return;
}
// Get TLSA record
var resultTLSA = client.Query("_443._tcp." + domain, QueryType.TLSA);
foreach (var record in resultTLSA.Answers.OfType<TlsaRecord>())
{
TLSA = record.CertificateAssociationDataAsString;
}
string url = "https://" + iPAddress.ToString() + "/.well-known/wallets/HNS";
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback = ValidateServerCertificate;
// Create an instance of HttpClient with the custom handler
using (var httpclient = new HttpClient(handler))
{
httpclient.DefaultRequestHeaders.Add("Host", domain);
// Send a GET request to the specified URL
HttpResponseMessage response = httpclient.GetAsync(url).Result;
// Response
string address = response.Content.ReadAsStringAsync().Result;
labelSendingHIPAddress.Text = address;
labelSendingHIPAddress.Show();
labelHIPArrow.Show();
}
}
catch (Exception ex)
{
AddLog(ex.Message);
labelSendingError.Show();
labelSendingError.Text = "HIP-02 lookup failed";
}
}
else
{
@ -1287,6 +1374,67 @@ namespace FireWallet
}
}
}
public bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
// Customize the certificate validation logic here if needed
// Return true to accept the certificate or false to reject it
X509Certificate2 cert2 = new X509Certificate2(certificate);
var rsaPublicKey = (RSA)cert2.PublicKey.Key;
// Calculate the SHA-256 hash of the public key
using (var sha256 = SHA256.Create())
{
byte[] publicKeyBytes = rsaPublicKey.ExportSubjectPublicKeyInfo();
byte[] publicKeyHash = sha256.ComputeHash(publicKeyBytes);
// Convert the hash value to hexadecimal format
string hexFingerprint = ByteArrayToHexString(publicKeyHash);
if (hexFingerprint == TLSA)
{
return true;
}
else
{
AddLog("TLSA mismatch");
return false;
}
}
}
static string ByteArrayToHexString(byte[] bytes)
{
StringBuilder hex = new StringBuilder(bytes.Length * 2);
foreach (byte b in bytes)
{
hex.AppendFormat("{0:X2}", b);
}
return hex.ToString();
}
private static string GetHash(HashAlgorithm hashAlgorithm, byte[] input)
{
// Convert the input string to a byte array and compute the hash.
byte[] data = hashAlgorithm.ComputeHash(input);
// Create a new Stringbuilder to collect the bytes
// and create a string.
var sBuilder = new StringBuilder();
// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("x2"));
}
// Return the hexadecimal string.
return sBuilder.ToString();
}
private void textBoxSendingAmount_Leave(object sender, EventArgs e)
{
decimal amount = 0;