Skip to content

Instantly share code, notes, and snippets.

@sondreb
Created December 23, 2019 10:54
Show Gist options
  • Save sondreb/1544a6f2355fa5151a7e47506d023b18 to your computer and use it in GitHub Desktop.
Save sondreb/1544a6f2355fa5151a7e47506d023b18 to your computer and use it in GitHub Desktop.
using NBitcoin;
using System;
namespace Example
{
class Program
{
static void Main(string[] args)
{
// Merchant private key for their identity published on the Blockcore Hubs:
BitcoinSecret privateKeyIdentity = new BitcoinSecret("L3ifTKKFe3Bs9ty1FtYKGubz2JED9PseNCjn62FBbKfAp1CdXQMu", Network.Main);
var identity = privateKeyIdentity.PubKey.GetAddress(ScriptPubKeyType.Legacy, Network.Main); // 1QHYV8gvGci7SZ7kdXL76o7vioGTVJBdZJ
// Generate a key pair, this will normally be from a HD wallet derived path:
BitcoinSecret privateKeyAddress = new BitcoinSecret("KysDJGLNsBoHs9vfZhNnooTnBjGWNbyBMi2YqJTEWcUsEw1ee8gp", Network.Main);
var address = privateKeyAddress.PubKey.GetAddress(ScriptPubKeyType.Legacy, Network.Main);
// What we'll do is sign a message that contains both a timestamp to verify
var message = $"{identity} want you to send 0.00100000 to {address}";
var signature = privateKeyIdentity.PrivateKey.SignMessage(message);
// The merchant generates this payment requests scanned with QR:
dynamic paymentRequest = new
{
network = "main", // To know what network this payment is for.
amount = 0.00100000, // The amount in BTC.
time = DateTimeOffset.UtcNow.ToUnixTimeSeconds(), // The time is used to verify that we're actually reciving a new payment requests and not reusing an older one.
addresses = address.ToString(), // BIP70 has outputs to multiple address, so we'll support this as well. Right now we'll leave it to a single address.
identity = identity.ToString(), // This is the identity we'll use lookup the profile on the Blockcore Hub network.
signature = signature, // Signature we can use to verify that reciving address is signed with the identity provided.
url = "https://example.org/identity"
};
// After the payeer receives the payment request, they must verify that it has not been tampered with:
BitcoinPubKeyAddress publicAddress = new BitcoinPubKeyAddress(paymentRequest.identity, Network.Main);
var verifycationMessage = $"{paymentRequest.identity} want you to send {String.Format("{0:0.00000000}", paymentRequest.amount)} to {paymentRequest.addresses}";
bool isSignatureValid = publicAddress.VerifyMessage(verifycationMessage, paymentRequest.signature);
if (isSignatureValid)
{
Console.WriteLine("The signature is correct.");
// The next step is to actually verify the identity, since anyone could have made the payment request and just signed it with a fake profile.
// 1. Verify the identity against your contact list. If you have already traded with the individual/merchant, no additional verification is needed.
// 2. If the identity is not in contact list, retrieve the profile from Blockcore Hubs network.
// 3. Retrieve the available reviews made by your "social network" (contact list) of the specific merchant profile. You will know if your friends trust, or distrust, the merchant.
// As an alternative to using the Blockcore Hubs network, we could rely on an URL similar to BIP70 that ends user to a payment confirmation page.
// It is also possible that this URL, could simply be a link to a basic webpage on the merchant website that lists the identity of the merchant.
var identityUrl = paymentRequest.url; // If the identity is returned in this URL, we can be sure that at least the merchant is in control of their web server.
}
else
{
Console.WriteLine("You got trouble ... signature is INCORRECT!");
}
Console.WriteLine("Prett ENTER to exit.");
Console.ReadLine();
}
}
}
@sondreb
Copy link
Author

sondreb commented Dec 23, 2019

In this example, only a few of the values in the paymentRequest is included. In a real scenario, all of the payment request must be part of the signature, or else the values can be easily manipulated (such as the url or time).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment