Created
February 11, 2017 21:07
-
-
Save dhcgn/635fe52763392db7447cd62665bce08a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using Net.Pkcs11Interop.Common; | |
using Net.Pkcs11Interop.HighLevelAPI; | |
using Net.Pkcs11Interop.HighLevelAPI.MechanismParams; | |
using NUnit.Framework; | |
namespace HsmTry | |
{ | |
public class NitroKeyEncryption | |
{ | |
// private const string LibraryPath = @"C:\Program Files\OpenSC Project\PKCS11-Spy\pkcs11-spy.dll"; | |
private const string LibraryPath = @"C:\Windows\System32\opensc-pkcs11.dll"; | |
private const string UserPin = "805732"; | |
/// <summary> | |
/// | |
/// </summary> | |
/// <param name="aliceLabel">Existing public and private key on the NitroKey</param> | |
/// <param name="bobLabel">Existing public and private key on the NitroKey</param> | |
/// <returns></returns> | |
public static byte[] Derive(string aliceLabel, string bobLabel) | |
{ | |
using (Pkcs11 pk = new Pkcs11(LibraryPath, false)) | |
{ | |
var slot = pk.GetSlotList(false).First(); | |
using (Session session = slot.OpenSession(false)) | |
{ | |
session.Login(CKU.CKU_USER, UserPin); | |
ObjectHandle objectAlice = GetObjectByLabel(aliceLabel, session, CKO.CKO_PRIVATE_KEY); | |
// What if PublicKey is generated by e.g. BouncyCastle? Same Format? | |
ObjectHandle objectBob = GetObjectByLabel(bobLabel, session, CKO.CKO_PUBLIC_KEY); | |
var objectBobPublicKey = GetDataByCka(objectBob, session, CKA.CKA_VALUE); | |
Assert.That(objectBob.ObjectId, Is.Not.EqualTo(objectAlice.ObjectId)); | |
byte[] data = session.GenerateRandom(24); | |
// Or different Params? Can Iteration and data be null? | |
var mechanismParams = new CkEcdh1DeriveParams(1000, data, objectBobPublicKey); | |
var mechanism = new Mechanism(CKM.CKM_DH_PKCS_DERIVE, mechanismParams); | |
var publicKeyAttribute = new List<ObjectAttribute> | |
{ | |
// See c++ Sample, but where to get these data? | |
// https://www.cryptsoft.com/pkcs11doc/v220/group__SEC__11__14__KEY__MANAGEMENT__FUNCTIONS.html | |
// new ObjectAttribute(CKA.CKA_PRIME, ???), | |
// new ObjectAttribute(CKA.CKA_BASE, ???), | |
}; | |
var privateKeyAttribute = new List<ObjectAttribute> | |
{ | |
new ObjectAttribute(CKA.CKA_DERIVE, true), | |
}; | |
ObjectHandle generateKeyPairPublicKeyHandler; | |
ObjectHandle generateKeyPairPrivateKeyHandler; | |
session.GenerateKeyPair(new Mechanism(CKM.CKM_DH_PKCS_KEY_PAIR_GEN), publicKeyAttribute, privateKeyAttribute, out generateKeyPairPublicKeyHandler, out generateKeyPairPrivateKeyHandler); | |
var deriveAttributes = new List<ObjectAttribute> | |
{ | |
// Do I need these ObjectAttributes? | |
// new ObjectAttribute(CKA.CKA_VALUE, true), | |
// new ObjectAttribute(CKA.CKA_VALUE_LEN,(ulong) objectBobPublicKey.Length), | |
new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY), | |
new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_AES), | |
new ObjectAttribute(CKA.CKA_ENCRYPT, true), | |
new ObjectAttribute(CKA.CKA_DECRYPT, true), | |
}; | |
ObjectHandle derivedKey = session.DeriveKey(mechanism, objectAlice, deriveAttributes); | |
// Is CKA_VALUE of derivedKey the derived secret? | |
Assert.IsTrue(derivedKey.ObjectId != CK.CK_INVALID_HANDLE); | |
return GetDataByCka(derivedKey, session, CKA.CKA_VALUE); | |
} | |
} | |
} | |
public static List<string> GetAllLabel() | |
{ | |
using (Pkcs11 pk = new Pkcs11(LibraryPath, false)) | |
{ | |
var slot = pk.GetSlotList(false).First(); | |
using (Session session = slot.OpenSession(false)) | |
{ | |
session.Login(CKU.CKU_USER, UserPin); | |
List<ObjectAttribute> objectAttributes = new List<ObjectAttribute> | |
{ | |
new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_PUBLIC_KEY), | |
new ObjectAttribute(CKA.CKA_TOKEN, true) | |
}; | |
List<ObjectHandle> foundObjects = session.FindAllObjects(objectAttributes); | |
var attributes = new List<ulong> { (ulong)CKA.CKA_LABEL }; | |
var labels = foundObjects.Select(handle => | |
{ | |
var requiredAttributes = session.GetAttributeValue(handle, attributes); | |
return requiredAttributes[0].GetValueAsString(); | |
}); | |
return labels.ToList(); | |
} | |
} | |
} | |
public static byte[] GetDataByCka(ObjectHandle label, Session session, CKA type) | |
{ | |
var attributes = new List<ulong> { (ulong)type }; | |
var requiredAttributes = session.GetAttributeValue(label, attributes); | |
return requiredAttributes[0].GetValueAsByteArray(); | |
} | |
private static ObjectHandle GetObjectByLabel(string label, Session session, CKO KeyType) | |
{ | |
List<ObjectAttribute> objectAttributes = new List<ObjectAttribute> | |
{ | |
new ObjectAttribute(CKA.CKA_CLASS, KeyType), | |
new ObjectAttribute(CKA.CKA_LABEL, label), | |
new ObjectAttribute(CKA.CKA_TOKEN, true) | |
}; | |
List<ObjectHandle> foundObjects = session.FindAllObjects(objectAttributes); | |
Assert.That(foundObjects, Has.Count.EqualTo(1)); | |
var objectHandle = foundObjects.First(); | |
return objectHandle; | |
} | |
public static void OpenSession() | |
{ | |
using (var pk = new Net.Pkcs11Interop.HighLevelAPI.Pkcs11(LibraryPath, false)) | |
{ | |
foreach (var slot in pk.GetSlotList(true)) | |
{ | |
var slotinfo = slot.GetSlotInfo(); | |
var tokenInfo = slot.GetTokenInfo(); | |
using (var session = slot.OpenSession(true)) | |
{ | |
var sessionInfo = session.GetSessionInfo(); | |
session.Login(CKU.CKU_USER, UserPin); | |
var objectAttributes = new List<ObjectAttribute>() | |
{ | |
new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_DATA), | |
new ObjectAttribute(CKA.CKA_TOKEN, true) | |
}; | |
var publice = session.FindAllObjects(objectAttributes); | |
foreach (var objectHandle in publice) | |
{ | |
Console.Out.WriteLine("" + objectHandle.ToString()); | |
} | |
session.Logout(); | |
} | |
} | |
} | |
} | |
/// <summary> | |
/// Bug: Doesn't work! | |
/// </summary> | |
/// <param name="label"></param> | |
public static void Encrypt(string label) | |
{ | |
using (Pkcs11 pk = new Pkcs11(LibraryPath, false)) | |
{ | |
var slot = pk.GetSlotList(false).First(); | |
using (Session session = slot.OpenSession(false)) | |
{ | |
session.Login(CKU.CKU_USER, UserPin); | |
List<ObjectAttribute> objectAttributes = new List<ObjectAttribute> | |
{ | |
new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_PRIVATE_KEY), | |
new ObjectAttribute(CKA.CKA_LABEL, label), | |
new ObjectAttribute(CKA.CKA_TOKEN, true) | |
}; | |
List<ObjectHandle> foundObjects = session.FindAllObjects(objectAttributes); | |
var temp = foundObjects.First(); | |
byte[] iv = session.GenerateRandom(8); | |
Mechanism mechanism = new Mechanism(CKM.CKM_AES_CBC_ENCRYPT_DATA, iv); | |
byte[] sourceData = ConvertUtils.Utf8StringToBytes("Our new password"); | |
// Encrypt data | |
byte[] encryptedData = session.Encrypt(mechanism, temp, sourceData); | |
} | |
} | |
} | |
public static void GetSlots() | |
{ | |
// string lib = @"C:\Program Files\OpenSC Project\OpenSC\tools\opensc.dll"; | |
// string lib = @"C:\Program Files\OpenSC Project\OpenSC\tools\smm-local.dll"; | |
using (var pk = new Net.Pkcs11Interop.HighLevelAPI.Pkcs11(LibraryPath, false)) | |
{ | |
var libraryInfo = pk.GetInfo(); | |
Console.WriteLine("Library"); | |
Console.WriteLine(" Manufacturer: " + libraryInfo.ManufacturerId); | |
Console.WriteLine(" Description: " + libraryInfo.LibraryDescription); | |
Console.WriteLine(" Version: " + libraryInfo.LibraryVersion); | |
foreach (var slot in pk.GetSlotList(false)) | |
{ | |
// Show basic information about slot | |
var slotInfo = slot.GetSlotInfo(); | |
Console.WriteLine(); | |
Console.WriteLine($"Slot ({slot.SlotId})"); | |
Console.WriteLine(" Manufacturer: " + slotInfo.ManufacturerId); | |
Console.WriteLine(" Description: " + slotInfo.SlotDescription); | |
Console.WriteLine(" Token present: " + slotInfo.SlotFlags.TokenPresent); | |
var session = slot.OpenSession(true); | |
session.Login(CKU.CKU_USER, UserPin); | |
var temp = session.FindAllObjects(new List<ObjectAttribute>() {new ObjectAttribute(CKA.CKA_LABEL)}); | |
var slotInfo2 = slot.GetSlotInfo(); | |
session.Logout(); | |
session.CloseSession(); | |
if (slotInfo.SlotFlags.TokenPresent) | |
{ | |
// Show basic information about token present in the slot | |
var tokenInfo = slot.GetTokenInfo(); | |
Console.WriteLine("Token"); | |
Console.WriteLine(" Manufacturer: " + tokenInfo.ManufacturerId); | |
Console.WriteLine(" Model: " + tokenInfo.Model); | |
Console.WriteLine(" Serial number: " + tokenInfo.SerialNumber); | |
Console.WriteLine(" Label: " + tokenInfo.Label); | |
Console.WriteLine(" SlotId: " + tokenInfo.SlotId); | |
// Show list of mechanisms supported by the token | |
Console.WriteLine("Supported mechanisms: "); | |
foreach (var mechanism in slot.GetMechanismList()) | |
Console.WriteLine(" " + mechanism); | |
} | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment