Skip to content

Instantly share code, notes, and snippets.

@dhcgn
Created February 11, 2017 21:07
Show Gist options
  • Save dhcgn/635fe52763392db7447cd62665bce08a to your computer and use it in GitHub Desktop.
Save dhcgn/635fe52763392db7447cd62665bce08a to your computer and use it in GitHub Desktop.
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