V tomto krátkom bloku popisujem dva triky, ktoré idú spraviť vo Windowsovom CNG Api (Cryptohraphy Next Generation) na C# kóde.
TPM (Trusted platform module) čip sa nachádza na stále viac notebookuoch a počítačoch, je to čip na ktorý sa dajú ukladať šifrovacie a prihlasovacie kľúče (napríklad Windows ich využíva na FIDO2 autentifikáciu). Pomocou Microsoft Platform Crypto Provider je možné vytvoriť kľúčový pár a k nemu certifikát, chránený pomocou TPM čipu.
using CngKey key = CngKey.Create(CngAlgorithm.Rsa,
"KeyProtectedUsingTpm",
new CngKeyCreationParameters()
{
ExportPolicy = CngExportPolicies.None,
KeyCreationOptions = CngKeyCreationOptions.None,
KeyUsage = CngKeyUsages.AllUsages,
Provider = new CngProvider("Microsoft Platform Crypto Provider"),
UIPolicy = new CngUIPolicy(CngUIProtectionLevels.ProtectKey)
});
var cng = new RSACng(key);
CertificateRequest certificateRequest = new CertificateRequest("CN=ProtectedUsingTpm Example",
cng,
HashAlgorithmName.SHA256,
RSASignaturePadding.Pkcs1);
X509Certificate2 certificate = certificateRequest.CreateSelfSigned(DateTimeOffset.Now, DateTimeOffset.Now.AddDays(365));
using X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadWrite);
store.Add(certificate);
Kód vytvorí kľúčový pár chránený TPM čipom a používateľskou akciou, vytvorí k nemu self-signed certifikát a uloží ho do Windows certificate storu používateľa.
Pomocou CNG API je možné programovo zadať PIN k čipovej karte, ktorý by si inak CSP provider pýtal pomocou dialógu.
string thumbprint = "B6A2EC31AC1B48F7569BD5AF91CEBD2622F462E3";
string pin = "123456789";
using X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection collection = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);
X509Certificate2 cert = collection[0];
using RSA rsa = cert.GetRSAPrivateKey();
RSACng rsaCng = rsa as RSACng;
byte[] propertyBytes = Encoding.Unicode.GetBytes($"{pin}\0");
const string PIN_PROPERTY = "SmartCardPin";
CngProperty pinProperty = new CngProperty(
PIN_PROPERTY,
propertyBytes,
CngPropertyOptions.None);
rsaCng.Key.SetProperty(pinProperty);
byte[] data = Encoding.UTF8.GetBytes("Hello World!");
byte[] signature = rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pss);
Console.WriteLine("Signature {0}", Convert.ToBase64String(signature));
Kód si zo storu certifikátov vytiahne príslušný certifikát podla thumbprintu. Jeho privátnemu kľúču nastaví PIN a podpíše ním dáta.