Update DETERMINISTIC spec

This commit is contained in:
nicolas.dorier 2023-10-25 14:02:06 +09:00
parent dcefece799
commit a6bec75bb2
No known key found for this signature in database
GPG Key ID: 6618763EF09186FE
6 changed files with 50 additions and 44 deletions

View File

@ -4,7 +4,7 @@
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>1.0.14</Version>
<Version>1.0.15</Version>
</PropertyGroup>
<PropertyGroup>

View File

@ -5,7 +5,7 @@
<TargetFramework>net6.0</TargetFramework>
<LangVersion>10.0</LangVersion>
<Nullable>enable</Nullable>
<Version>1.0.15</Version>
<Version>1.0.16</Version>
</PropertyGroup>
<PropertyGroup>

View File

@ -8,35 +8,24 @@ using System.Threading.Tasks;
namespace BTCPayServer.NTag424;
public record CardKey(AESKey AESKey)
{
public static CardKey Random() => new CardKey(AESKey.Random());
public CardKey(byte[] bytes) : this(new AESKey(bytes))
public AESKey DeriveAuthenticationKey()
{
}
public AESKey DeriveAuthenticationKey(byte[] uid)
{
Helpers.ValidateUID(uid);
return AESKey.Derive(Helpers.Concat(
new byte[] { 0x2d, 0x00, 0x3f, 0x78 },
uid));
new byte[] { 0x2d, 0x00, 0x3f, 0x78 }));
}
public BoltcardKeys DeriveBoltcardKeys(IssuerKey issuerKey, byte[] uid)
public BoltcardKeys DeriveBoltcardKeys(IssuerKey issuerKey)
{
return DeriveBoltcardKeys(issuerKey.DeriveEncryptionKey(), uid);
return DeriveBoltcardKeys(issuerKey.DeriveEncryptionKey());
}
public BoltcardKeys DeriveBoltcardKeys(AESKey encryptionKey, byte[] uid)
public BoltcardKeys DeriveBoltcardKeys(AESKey encryptionKey)
{
Helpers.ValidateUID(uid);
var appMasterKey = AESKey.Derive(Helpers.Concat(
new byte[] { 0x2d, 0x00, 0x3f, 0x76 },
uid));
var authKey = DeriveAuthenticationKey(uid);
new byte[] { 0x2d, 0x00, 0x3f, 0x76 }));
var authKey = DeriveAuthenticationKey();
var k1 = AESKey.Derive(Helpers.Concat(
new byte[] { 0x2d, 0x00, 0x3f, 0x79 },
uid));
new byte[] { 0x2d, 0x00, 0x3f, 0x79 }));
var k2 = AESKey.Derive(Helpers.Concat(
new byte[] { 0x2d, 0x00, 0x3f, 0x7a },
uid));
new byte[] { 0x2d, 0x00, 0x3f, 0x7a }));
return new BoltcardKeys(appMasterKey, encryptionKey, authKey, k1, k2);
}
@ -45,14 +34,10 @@ public record CardKey(AESKey AESKey)
{
if (!PICCData.ExtractPC(uri, out _, out var c))
return false;
return this.DeriveAuthenticationKey(piccData.Uid).CheckSunMac(c, piccData, payload);
return this.DeriveAuthenticationKey().CheckSunMac(c, piccData, payload);
}
public bool CheckSunMac([NotNullWhen(true)] string? c, BoltcardPICCData piccData, byte[]? payload = null)
{
return this.DeriveAuthenticationKey(piccData.Uid).CheckSunMac(c, piccData, payload);
}
public byte[] ToBytes()
{
return AESKey.ToBytes();
return this.DeriveAuthenticationKey().CheckSunMac(c, piccData, payload);
}
}

View File

@ -4,6 +4,7 @@ using System.Linq;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using static BTCPayServer.NTag424.Helpers;
using static BTCPayServer.NTag424.Ntag424;
namespace BTCPayServer.NTag424;
@ -18,12 +19,37 @@ public record IssuerKey(AESKey AESKey)
{
}
public CardKey CreateCardKey(byte[] uid, int version)
{
Helpers.ValidateUID(uid);
if (version < 0)
throw new ArgumentOutOfRangeException(nameof(version));
var k = AESKey.Derive(Helpers.Concat(
new byte[] { 0x2d, 0x00, 0x3f, 0x75 },
uid,
Helpers.UIntToBytesLE((uint)version)));
return new CardKey(k);
}
public AESKey DeriveEncryptionKey()
{
return AESKey.Derive(Helpers.Concat(
new byte[] { 0x2d, 0x00, 0x3f, 0x77 }));
}
public bool CheckSunMac([NotNullWhen(true)] Uri? uri, BoltcardPICCData piccData, int version, byte[]? payload = null)
{
if (!PICCData.ExtractPC(uri, out _, out var c))
return false;
return CheckSunMac(c, piccData, version, payload);
}
public bool CheckSunMac([NotNullWhen(true)] string? c, BoltcardPICCData piccData, int version, byte[]? payload = null)
{
var cardKey = CreateCardKey(piccData.Uid, version);
return cardKey.CheckSunMac(c, piccData, payload);
}
/// <summary>
/// Get the ID from the UID
/// </summary>

View File

@ -400,13 +400,7 @@ public class Ntag424
/// <returns></returns>
public async Task ResetCard(IssuerKey issuerKey, CardKey cardKey)
{
var encryptionKey = issuerKey.DeriveEncryptionKey();
if (CurrentSession is null)
await AuthenticateEV2First(1, encryptionKey);
if (encryptionKey != CurrentSession!.Key)
await AuthenticateEV2NonFirst(1, encryptionKey);
var uid = await GetCardUID();
var keys = cardKey.DeriveBoltcardKeys(issuerKey, uid);
var keys = cardKey.DeriveBoltcardKeys(issuerKey);
await ResetCard(keys);
}

View File

@ -79,14 +79,15 @@ public class UnitTest1
{
var uid = "04a39493cc8680".HexToBytes();
var issuerKey = new IssuerKey("00000000000000000000000000000001".HexToBytes());
var cardKey = new CardKey("00000000000000000000000000000002".HexToBytes());
var keys = cardKey.DeriveBoltcardKeys(issuerKey, uid);
var cardKey = issuerKey.CreateCardKey(uid, 1);
var keys = cardKey.DeriveBoltcardKeys(issuerKey);
Logs.WriteLine("K0: " + keys.AppMasterKey.ToBytes().ToHex());
Logs.WriteLine("K1: " + keys.EncryptionKey.ToBytes().ToHex());
Logs.WriteLine("K2: " + keys.AuthenticationKey.ToBytes().ToHex());
Logs.WriteLine("K3: " + keys.K3.ToBytes().ToHex());
Logs.WriteLine("K4: " + keys.K4.ToBytes().ToHex());
Logs.WriteLine("ID: " + issuerKey.GetId(uid).ToHex());
Logs.WriteLine("CardKey: " + cardKey.AESKey.ToBytes().ToHex());
}
[Fact]
@ -180,13 +181,13 @@ public class UnitTest1
using var ctx = await PCSCContext.WaitForCard();
var ntag = ctx.CreateNTag424();
var issuerKey = new IssuerKey("00000000000000000000000000000001".HexToBytes());
var cardKey = new CardKey("00000000000000000000000000000002".HexToBytes());
// First time authenticate is with the default 00.000 key
await ntag.AuthenticateEV2First(0, AESKey.Default);
var uid = await ntag.GetCardUID();
var cardKey = issuerKey.CreateCardKey(uid, 0);
var keys = cardKey.DeriveBoltcardKeys(issuerKey, uid);
var keys = cardKey.DeriveBoltcardKeys(issuerKey);
await ntag.SetupBoltcard("lnurlw://blahblah.com", BoltcardKeys.Default, keys);
var uri = await ntag.TryReadNDefURI();
@ -207,13 +208,14 @@ public class UnitTest1
public async Task Reset()
{
var issuerKey = new IssuerKey("00000000000000000000000000000001".HexToBytes());
var cardKey = new CardKey("00000000000000000000000000000002".HexToBytes());
using var ctx = PCSCContext.Create();
var ntag = ctx.CreateNTag424();
await ntag.AuthenticateEV2First(0, AESKey.Default);
var uid = await ntag.GetCardUID();
var keys = cardKey.DeriveBoltcardKeys(issuerKey, uid);
var cardKey = issuerKey.CreateCardKey(uid, 1);
var keys = cardKey.DeriveBoltcardKeys(issuerKey);
await ntag.SetupBoltcard("lnurlw://test.com", BoltcardKeys.Default, keys);
await ntag.ResetCard(issuerKey, cardKey);
@ -270,14 +272,13 @@ public class UnitTest1
using var ctx = PCSCContext.Create();
var ntag = ctx.CreateNTag424();
var issuerKey = new IssuerKey("00000000000000000000000000000001".HexToBytes());
var cardKey = new CardKey("00000000000000000000000000000002".HexToBytes());
var nonce = "00010000000000000000000000000000".HexToBytes();
//await ntag.ResetCard(issuerKey, nonce);
await ntag.AuthenticateEV2First(0, AESKey.Default);
var uid = await ntag.GetCardUID();
var keys = cardKey.DeriveBoltcardKeys(issuerKey, uid);
var cardKey = issuerKey.CreateCardKey(uid, 1);
var keys = cardKey.DeriveBoltcardKeys(issuerKey);
await ntag.SetupBoltcard("http://test.com", BoltcardKeys.Default, keys);
var uri = await ntag.TryReadNDefURI();
issuerKey.TryDecrypt(uri);