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>
<ItemGroup> <ItemGroup>
<PackageReference Include="DnsClient" Version="1.7.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="QRCoder" Version="1.4.3" /> <PackageReference Include="QRCoder" Version="1.4.3" />
</ItemGroup> </ItemGroup>

View File

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

View File

@ -10,6 +10,10 @@ using System.Text;
using System.Security.Policy; using System.Security.Policy;
using System.Windows.Forms; using System.Windows.Forms;
using System.Net; using System.Net;
using DnsClient;
using DnsClient.Protocol;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
namespace FireWallet namespace FireWallet
{ {
@ -199,20 +203,20 @@ namespace FireWallet
if (!Directory.Exists(dir + "hsd")) if (!Directory.Exists(dir + "hsd"))
{ {
NotifyForm Notifyinstall = new NotifyForm("Installing hsd\nThis may take a few minutes\nDo not close FireWallet", false); NotifyForm Notifyinstall = new NotifyForm("Installing hsd\nThis may take a few minutes\nDo not close FireWallet", false);
Notifyinstall.Show(); Notifyinstall.Show();
// Wait for the notification to show // Wait for the notification to show
await Task.Delay(1000); await Task.Delay(1000);
string repositoryUrl = "https://github.com/handshake-org/hsd.git"; string repositoryUrl = "https://github.com/handshake-org/hsd.git";
string destinationPath = dir + "hsd"; string destinationPath = dir + "hsd";
CloneRepository(repositoryUrl, destinationPath); CloneRepository(repositoryUrl, destinationPath);
Notifyinstall.CloseNotification(); Notifyinstall.CloseNotification();
Notifyinstall.Dispose(); Notifyinstall.Dispose();
} }
if (!Directory.Exists(dir + "hsd\\node_modules")) if (!Directory.Exists(dir + "hsd\\node_modules"))
{ {
AddLog("HSD install failed"); AddLog("HSD install failed");
this.Close(); this.Close();
return false; return false;
} }
@ -1084,17 +1088,17 @@ namespace FireWallet
{ {
try try
{ {
string response = await APIGet("fee", false); string response = await APIPost("", false, "{\"method\": \"estimatefee\",\"params\": [ 3 ]}");
JObject resp = JObject.Parse(response); JObject resp = JObject.Parse(response);
decimal fee = Convert.ToDecimal(resp["rate"].ToString()); string result = resp["result"].ToString();
fee = fee / 1000000; decimal fee = decimal.Parse(result);
if (fee < 0.0001m) fee = 1; if (fee < 0.001m) fee = 1;
return fee.ToString(); return fee.ToString();
//return resp["rate"].ToString();
} }
catch catch
{ {
AddLog("GetFee Error");
return "1"; return "1";
} }
} }
@ -1160,6 +1164,7 @@ namespace FireWallet
labelSendingMax.Text = "Max: " + balance.ToString() + " HNS"; labelSendingMax.Text = "Max: " + balance.ToString() + " HNS";
textBoxSendingTo.Focus(); textBoxSendingTo.Focus();
string fee = await GetFee(); string fee = await GetFee();
labelSendingFee.Text = "Est. Fee: " + fee + " HNS"; labelSendingFee.Text = "Est. Fee: " + fee + " HNS";
labelSendingError.Hide(); labelSendingError.Hide();
@ -1255,14 +1260,96 @@ namespace FireWallet
} }
#endregion #endregion
#region Send #region Send
// Store TLSA hash
private string TLSA = "";
private async void textBoxSendingTo_Leave(object sender, EventArgs e) private async void textBoxSendingTo_Leave(object sender, EventArgs e)
{ {
labelSendingError.Hide();
labelHIPArrow.Hide();
labelSendingHIPAddress.Hide();
if (textBoxSendingTo.Text == "") return; if (textBoxSendingTo.Text == "") return;
if (textBoxSendingTo.Text.Substring(0, 1) == "@") if (textBoxSendingTo.Text.Substring(0, 1) == "@")
{ {
labelSendingError.Show(); string domain = textBoxSendingTo.Text.Substring(1);
labelSendingError.Text = "HIP-02 Not supported yet";
return; 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 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) private void textBoxSendingAmount_Leave(object sender, EventArgs e)
{ {
decimal amount = 0; decimal amount = 0;