From e83a4e141302edfb5e5746bcf070b061f28eca75 Mon Sep 17 00:00:00 2001 From: "nicolas.dorier" Date: Tue, 24 Oct 2023 18:57:16 +0900 Subject: [PATCH] Update README --- README.md | 57 +++++++++++++++++++++++-------------------------------- 1 file changed, 24 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index b43d236..1d447de 100644 --- a/README.md +++ b/README.md @@ -63,34 +63,19 @@ using System; using System.Security; using System.Collections; +// Set keys have you have setup the card +var encryptionKey = AESKey.Default; +var authenticationKey = AESKey.Default; + using var ctx = await PCSCContext.WaitForCard(); var ntag = ctx.CreateNTag424(); -// In prod: var issuerKey = IssuerKey.Random(); -var issuerKey = new IssuerKey("00000000000000000000000000000001".HexToBytes()); -// In prod: var cardKey = CardKey.Random(); -var cardKey = new CardKey("00000000000000000000000000000002".HexToBytes()); - -// First time authenticate is with the default 00000000000000000000000000000000 key -await ntag.AuthenticateEV2First(0, AESKey.Default); -var uid = await ntag.GetCardUID(); - -var keys = cardKey.DeriveBoltcardKeys(issuerKey, uid); -await ntag.SetupBoltcard("lnurlw://blahblah.com", BoltcardKeys.Default, keys); var uri = await ntag.TryReadNDefURI(); -var piccData = issuerKey.TryDecrypt(uri); -if (piccData is null) - throw new SecurityException("Impossible to decrypt with issuerKey"); +var piccData = PICCData.TryBoltcardDecryptCheck(encryptionKey, authenticationKey, uri); +if (piccData == null) + throw new SecurityException("Impossible to decrypt or validate"); -// In production, you would fetch the card key from database -// var cardKey = await GetCardKey(issuerKey.GetId(piccData.Uid)); - -if (!cardKey.CheckSunMac(uri, piccData)) - throw new SecurityException("Impossible to decrypt with issuerKey"); - -await ntag.ResetCard(issuerKey, cardKey); -// If this method didn't throw an exception, it has been successfully decrypted and authenticated. -// You can reset the card with `await ntag.ResetCard(issuerKey, cardKey);`. +// The LNUrlw service should also check `piccData.Counter` is always increasing between payments to avoid replay attacks. ``` ### How to setup a bolt card @@ -127,21 +112,26 @@ await ntag.SetupBoltcard(lnurlwService, BoltcardKeys.Default, keys); Here is an example of how to setup a card with deterministic keys, and decrypt the PICCData. ```csharp +using System.Security; +using BTCPayServer.NTag424; + using var ctx = await PCSCContext.WaitForCard(); var ntag = ctx.CreateNTag424(); -var issuerKey = new IssuerKey("00000000000000000000000000000001".HexToBytes()); + +// In prod: var issuerKey = IssuerKey.Random(); +var issuerKey = new IssuerKey(new byte[16]); +// In prod: var cardKey = CardKey.Random(); +var cardKey = new CardKey(new byte[16]); // First time authenticate is with the default 00.000 key await ntag.AuthenticateEV2First(0, AESKey.Default); var uid = await ntag.GetCardUID(); -//var nonce = IssuerKey.RandomNonce(); -var nonce = new byte[16]; // Please use IssuerKey.RandomNonce() in production - // SaveNonce should be implemented by the server -await SaveNonce(issuerKey.GetId(uid), nonce); +await SaveCardKey(issuerKey.GetId(uid), cardKey); -var keys = issuerKey.DeriveBoltcardKeys(uid, nonce); + +var keys = cardKey.DeriveBoltcardKeys(issuerKey, uid); await ntag.SetupBoltcard("lnurlw://blahblah.com", BoltcardKeys.Default, keys); var uri = await ntag.TryReadNDefURI(); @@ -149,14 +139,15 @@ var piccData = issuerKey.TryDecrypt(uri); if (piccData == null) throw new SecurityException("Impossible to decrypt with issuerKey"); -// In real life, you would fetch the nonce from database -// var nonce = await FetchNonce(issuerKey.GetId(piccData.Uid)); -if (!issuerKey.CheckSunMac(uri, piccData, nonce)) +// In production, you would fetch the card key from database +// var cardKey = await GetCardKey(issuerKey.GetId(piccData.Uid)); + +if (!cardKey.CheckSunMac(uri, piccData)) throw new SecurityException("Impossible to check the SUN MAC"); // If this method didn't throw an exception, it has been successfully decrypted and authenticated. -// You can reset the card with `await ntag.ResetCard(issuerKey, nonce);`. +// You can reset the card with `await ntag.ResetCard(issuerKey, cardKey);`. ``` ## License