Update README

This commit is contained in:
nicolas.dorier 2023-10-24 18:57:16 +09:00
parent cca4420b9b
commit e83a4e1413
No known key found for this signature in database
GPG Key ID: 6618763EF09186FE

View File

@ -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