Skip to content

Instantly share code, notes, and snippets.

View jspilman's full-sized avatar

Jeremy Spilman jspilman

View GitHub Profile

Secure Wallet Extensions through Payment Protocol

The first rule of fight club is... 'Never trust a private key to a third party.'

Jeremy Spilman (jeremy@taplink.co)
April 2, 2013
DRAFT v0.3

Forward

@jspilman
jspilman / PaymentChannel.cs
Last active March 30, 2024 01:03
Proof of Concept for Payment Channels
// 0) User and AP negotiate how much to escrow, who pays the fees, and how far in the future nLockTime
// will be set (how long user’s funds will be tied if AP doesn’t close the channel)
long apUnspent = Util.Amount("0.27");
long userUnspent = Util.Amount("6.123");
long escrowAmount = Util.Amount("5");
long payerFee = 0;
long apFee = Util.Amount(".0005");
long userChange = userUnspent - escrowAmount - payerFee;
long apChange = apUnspent - apFee;
Payment Protocol uses X.509 certs to sign a Payment Request. This allows wallets to display meta-data from the cert
to the payer instead of the address, which should make it easier to verify where money is being sent, and prevent
an attacker from changing an address displayed to a user so that coins are sent to the wrong place.
The difficulty is that Payment Requests must be generated live, and therefore the cert used to sign those requests
must also be live, exposing the cert to theft similar to a hot wallet. The question... is there a way to sign something
once, offline, which verifies the address belongs to the payee?
1) Given a root or intermediate certificate 'parent' cert which is kept offline, and a child certificate of 'parent'
which is kept hot on the payment server.
@jspilman
jspilman / Stealth Payments
Last active August 19, 2017 12:30
Working implementation of stealth payments in Bitcoin using OP_RETURN! See TxID: 6e8576d6f65947b249a19402b6359c5a490abf67d50869a18518ccae41f94419 on Test NeT
// BIP32 Wallet
byte[] entropy = Util.DoubleSHA256(Encoding.ASCII.GetBytes("Stealth Address"));
HdNode wallet = HdNode.Create(entropy, mainNet: false).GetSecretChild(0);
// A TxID on Test-Net with 1BTC in Vout[1], spendable by wallet/0'/0'
byte[] unspentPubKey = wallet.GetSecretChild(0, 0).PublicKey;
byte[] unspentPrivKey = wallet.GetSecretChild(0, 0).PrivateKey;
string unspentAddr = Util.PubKeyToAddress(unspentPubKey, mainNet: false);
byte[] unspentTxId = Util.HexToBytes("4b8fd9c4f5cb233c687e3e883f7c284f9abc2698dd08f1ec6770f488a27a9704");
TxOut unspentTxOut = TxOut.PayToPubKeyHash(Util.Amount("1"), unspentPubKey);