我有一个简单的方法可以通过Pkcs11Interop访问我的HSM。
这是功能:
static public byte[] findTargetKeySValue(String label, String type, string command)
{
try
{
string pkcs11LibraryPath = @"C:\Program Files\SafeNet\Protect Toolkit 5\Protect Toolkit C SDK\bin\hsm\cryptoki.dll";
Utility.Logger("cryptoki dll path " + pkcs11LibraryPath, command);
using (Pkcs11 pkcs11 = new Pkcs11(pkcs11LibraryPath, Inter_Settings.AppType))
{
// Find first slot with token present
Slot slot = Inter_Helpers.GetUsableSlot(pkcs11);
// Open RW session
using (Session session = slot.OpenSession(SessionType.ReadOnly))
{
// Login as normal user
session.Login(CKU.CKU_USER, Inter_Settings.NormalUserPin);
// Prepare attribute template that defines search criteria
List<ObjectAttribute> objectAttributes = new List<ObjectAttribute>();
objectAttributes.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY));
if (type == "DES")
objectAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES));
else if (type == "DES2")
objectAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES2));
else if (type == "DES3")
objectAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES3));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, label));//PROVAK
List<ObjectHandle> foundObjects = session.FindAllObjects(objectAttributes);
var key = foundObjects[0];
byte[] plainKeyValue = null;
List<ObjectAttribute> readAttrsSensitive = session.GetAttributeValue(key, new List<CKA>() { CKA.CKA_SENSITIVE });
if (!readAttrsSensitive[0].GetValueAsBool())
{
Utility.Logger("findTargetKeySValue chiave " + label + " non senstive", command);
List<ObjectAttribute> readAttrs = session.GetAttributeValue(key, new List<CKA>() { CKA.CKA_VALUE });
if (readAttrs[0].CannotBeRead)
throw new Exception("Key cannot be exported");
else
plainKeyValue = readAttrs[0].GetValueAsByteArray();
//Console.WriteLine(ByteArrayToAsciiHEX(plainKeyValue));
session.Logout();
return plainKeyValue;
}
else
{
Utility.Logger("findTargetKeySValue chiave " + label + " senstive", command);
Console.WriteLine("wrap/unwrap");
objectAttributes = new List<ObjectAttribute>();
objectAttributes.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES3));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, "WRAPPING_KEY")); //WRAPPING_KEY WRK
foundObjects = session.FindAllObjects(objectAttributes);
var wrappingKey = foundObjects[0];
Mechanism m = new Mechanism(CKM.CKM_DES3_ECB);
var wrapped = session.WrapKey(m, wrappingKey, key);
//Console.WriteLine("wrapped " + ByteArrayToAsciiHEX(wrapped));
//Console.WriteLine(ByteArrayToAsciiHEX(session.Decrypt(m, wrappingKey, wrapped)));
var k = session.Decrypt(m, wrappingKey, wrapped);
session.Logout();
return k;
}
}
}
}
catch (Exception e)
{
//Console.WriteLine(e.ToSafeString());
Utility.Logger("findTargetKeySValue " + e.ToSafeString(), command);
return null;
}
}
当套接字服务器收到来自客户端的调用时,我在套接字服务器中调用了此方法。
为了测试它,我创建了一个带循环的小程序。在此循环中,它每秒钟发送大约3个请求到使用Pkcs11Interop的服务器。
让我们将此测试程序称为tester.exe。如果我运行tester.exe,一切似乎都还可以。但是,当第一个tester.exe运行时,我尝试执行另一个tester.exe实例,但出现错误
Net.Pkcs11Interop.Common.Pkcs11Exception:方法C_Initialize返回了2147483907
在此特定行代码中:
using (Pkcs11 pkcs11 = new Pkcs11(pkcs11LibraryPath, Inter_Settings.AppType))
为什么?哪有问题
更新:
AppType为
public static AppType AppType = AppType.MultiThreaded;
设置为:
static Inter_Settings()
{
if (AppType == AppType.MultiThreaded)
{
InitArgs40 = new LLA40.CK_C_INITIALIZE_ARGS();
InitArgs40.Flags = CKF.CKF_OS_LOCKING_OK;
InitArgs41 = new LLA41.CK_C_INITIALIZE_ARGS();
InitArgs41.Flags = CKF.CKF_OS_LOCKING_OK;
InitArgs80 = new LLA80.CK_C_INITIALIZE_ARGS();
InitArgs80.Flags = CKF.CKF_OS_LOCKING_OK;
InitArgs81 = new LLA81.CK_C_INITIALIZE_ARGS();
InitArgs81.Flags = CKF.CKF_OS_LOCKING_OK;
}
// Convert strings to byte arrays
SecurityOfficerPinArray = ConvertUtils.Utf8StringToBytes(SecurityOfficerPin);
NormalUserPinArray = ConvertUtils.Utf8StringToBytes(NormalUserPin);
ApplicationNameArray = ConvertUtils.Utf8StringToBytes(ApplicationName);
// Build PKCS#11 URI that identifies private key usable in signature creation tests
Pkcs11UriBuilder pkcs11UriBuilder = new Pkcs11UriBuilder();
pkcs11UriBuilder.ModulePath = Pkcs11LibraryPath;
pkcs11UriBuilder.Serial = TokenSerial;
pkcs11UriBuilder.Token = TokenLabel;
pkcs11UriBuilder.PinValue = NormalUserPin;
pkcs11UriBuilder.Type = CKO.CKO_PRIVATE_KEY;
pkcs11UriBuilder.Object = ApplicationName;
PrivateKeyUri = pkcs11UriBuilder.ToString();
}
UPDATE2:
public class InteropHSM
{
private Pkcs11 _pkcs11 = null;
private Slot _slot = null;
public InteropHSM()
{
string pkcs11LibraryPath = @"C:\Program Files\SafeNet\Protect Toolkit 5\Protect Toolkit C SDK\bin\hsm\cryptoki.dll";
_pkcs11 = new Pkcs11(pkcs11LibraryPath, Inter_Settings.AppType);
_slot = Inter_Helpers.GetUsableSlot(_pkcs11);
}
public byte[] findTargetKeySValue(String label, String type, string command)
{
try
{
//string pkcs11LibraryPath = @"C:\Program Files\SafeNet\Protect Toolkit 5\Protect Toolkit C SDK\bin\hsm\cryptoki.dll";
//Utility.Logger("cryptoki dll path " + pkcs11LibraryPath, command);
//using (Pkcs11 pkcs11 = new Pkcs11(pkcs11LibraryPath, Inter_Settings.AppType))
//{
//Slot slot = Inter_Helpers.GetUsableSlot(_pkcs11);
using (Session session = _slot.OpenSession(SessionType.ReadOnly))
{
// Login as normal user
session.Login(CKU.CKU_USER, Inter_Settings.NormalUserPin);
// Prepare attribute template that defines search criteria
List<ObjectAttribute> objectAttributes = new List<ObjectAttribute>();
objectAttributes.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY));
if (type == "DES")
objectAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES));
else if (type == "DES2")
objectAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES2));
else if (type == "DES3")
objectAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES3));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, label));//PROVAK
List<ObjectHandle> foundObjects = session.FindAllObjects(objectAttributes);
var key = foundObjects[0];
byte[] plainKeyValue = null;
List<ObjectAttribute> readAttrsSensitive = session.GetAttributeValue(key, new List<CKA>() { CKA.CKA_SENSITIVE });
if (!readAttrsSensitive[0].GetValueAsBool())
{
Utility.Logger("findTargetKeySValue chiave " + label + " non senstive", command);
List<ObjectAttribute> readAttrs = session.GetAttributeValue(key, new List<CKA>() { CKA.CKA_VALUE });
if (readAttrs[0].CannotBeRead)
throw new Exception("Key cannot be exported");
else
plainKeyValue = readAttrs[0].GetValueAsByteArray();
//Console.WriteLine(ByteArrayToAsciiHEX(plainKeyValue));
session.Logout();
return plainKeyValue;
}
else
{
Utility.Logger("findTargetKeySValue chiave " + label + " senstive", command);
Console.WriteLine("wrap/unwrap");
objectAttributes = new List<ObjectAttribute>();
objectAttributes.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES3));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, "WRAPPING_KEY")); //WRAPPING_KEY WRK
foundObjects = session.FindAllObjects(objectAttributes);
var wrappingKey = foundObjects[0];
Mechanism m = new Mechanism(CKM.CKM_DES3_ECB);
var wrapped = session.WrapKey(m, wrappingKey, key);
//Console.WriteLine("wrapped " + ByteArrayToAsciiHEX(wrapped));
Console.WriteLine(ByteArrayToAsciiHEX(session.Decrypt(m, wrappingKey, wrapped)));
var k = session.Decrypt(m, wrappingKey, wrapped);
session.Logout();
return k;
}
}
//}
}
catch (Exception e)
{
//Console.WriteLine(e.ToSafeString());
Utility.Logger("findTargetKeySValue " + e.ToSafeString(), command);
return null;
}
}
public static string ByteArrayToAsciiHEX(byte[] ba)
{
string hex = BitConverter.ToString(ba);
return hex.Replace("-", "");
}
}
每次调用时,服务器实例都在上面的类中,并调用方法findTargetKeySValue。如果服务器接收到并发请求,则它将导致HSM交互失败...但是我发疯了,每次会话都不同,就像规范中所说的那样。
更新3
Thread t = new Thread(() => ih.findTargetKeySValue(label, type, command));
t.Start();
Thread tt = new Thread(() => ih.findTargetKeySValue(label, type, command));
tt.Start();
Thread ttt = new Thread(() => ih.findTargetKeySValue(label, type, command));
ttt.Start();
Thread tttt = new Thread(() => ih.findTargetKeySValue(label, type, command));
tttt.Start();
Thread ttttt = new Thread(() => ih.findTargetKeySValue(label, type, command));
ttttt.Start();
我创建了这个简单的代码片段来测试多线程(上面定义了findTargetKeySValue),它崩溃并显示消息“方法C_Initialize返回了2147483907”。此代码由供应商定义,并且为CKR_CRYPTOKI_UNUSABLE。我将在下一个测试中使用它。
UPDATE4:
我更改了代码
public InteropHSM()
{
string pkcs11LibraryPath = @"C:\Program Files\SafeNet\Protect Toolkit 5\Protect Toolkit C SDK\bin\hsm\cryptoki.dll";
_pkcs11 = new Pkcs11(pkcs11LibraryPath, Inter_Settings.AppType);
_slot = Inter_Helpers.GetUsableSlot(_pkcs11);
session = _slot.OpenSession(SessionType.ReadOnly);
session.Login(CKU.CKU_USER, Inter_Settings.NormalUserPin);
}
public byte[] findTargetKeySValue(String label, String type, string command)
{
try
{
List<ObjectAttribute> objectAttributes = new List<ObjectAttribute>();
objectAttributes.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY));
if (type == "DES")
objectAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES));
else if (type == "DES2")
objectAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES2));
else if (type == "DES3")
objectAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES3));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, label));//PROVAK
List<ObjectHandle> foundObjects = session.FindAllObjects(objectAttributes);
var key = foundObjects[0];
byte[] plainKeyValue = null;
List<ObjectAttribute> readAttrsSensitive = session.GetAttributeValue(key, new List<CKA>() { CKA.CKA_SENSITIVE });
if (!readAttrsSensitive[0].GetValueAsBool())
{
Utility.Logger("findTargetKeySValue chiave " + label + " non senstive", command);
List<ObjectAttribute> readAttrs = session.GetAttributeValue(key, new List<CKA>() { CKA.CKA_VALUE });
if (readAttrs[0].CannotBeRead)
throw new Exception("Key cannot be exported");
else
plainKeyValue = readAttrs[0].GetValueAsByteArray();
//Console.WriteLine(ByteArrayToAsciiHEX(plainKeyValue));
session.Logout();
Console.WriteLine(plainKeyValue);
return plainKeyValue;
}
else
{
Utility.Logger("findTargetKeySValue chiave " + label + " senstive", command);
Console.WriteLine("wrap/unwrap");
objectAttributes = new List<ObjectAttribute>();
objectAttributes.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES3));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, "WRAPPING_KEY")); //WRAPPING_KEY WRK
foundObjects = session.FindAllObjects(objectAttributes);
var wrappingKey = foundObjects[0];
Mechanism m = new Mechanism(CKM.CKM_DES3_ECB);
var wrapped = session.WrapKey(m, wrappingKey, key);
//Console.WriteLine("wrapped " + ByteArrayToAsciiHEX(wrapped));
Console.WriteLine(ByteArrayToAsciiHEX(session.Decrypt(m, wrappingKey, wrapped)));
var k = session.Decrypt(m, wrappingKey, wrapped);
//session.Logout();
return k;
}
}
catch (Exception e)
{
Console.WriteLine(e.ToSafeString());
Utility.Logger("findTargetKeySValue " + e.ToSafeString(), command);
return null;
}
}
我用UPDATE3中的代码来称呼它。当代码调用时,我得到方法C_FindObjectsFinal返回CKR_OPERATION_NOT_INITIALIZED
List<ObjectHandle> foundObjects = session.FindAllObjects(objectAttributes);
您没有在多线程应用程序中正确使用PKCS#11 API。这是一个已知问题。
简短的答案是您需要确保:
Pkcs11
应用程序中使用类的单个实例(即在服务器启动期间加载,在服务器停止期间卸载)Session
为每个加密操作使用类的新实例长答案是您需要阅读PKCS#11 v2.20规范的“第6章-概述”,其中解释了PKCS#11 API的所有基本概念。在完成这个强制性阅读,你可以看一看类Pkcs11Interop.PDF项目,可以在多线程环境中使用类的工作代码示例。Pkcs11RsaSignature
这是从示例4修复代码的方法:
public InteropHSM()
{
string pkcs11LibraryPath = @"C:\Program Files\SafeNet\Protect Toolkit 5\Protect Toolkit C SDK\bin\hsm\cryptoki.dll";
_pkcs11 = new Pkcs11(pkcs11LibraryPath, Inter_Settings.AppType);
_slot = Inter_Helpers.GetUsableSlot(_pkcs11);
session = _slot.OpenSession(SessionType.ReadOnly);
session.Login(CKU.CKU_USER, Inter_Settings.NormalUserPin);
}
public byte[] findTargetKeySValue(String label, String type, string command)
{
try
{
List<ObjectAttribute> objectAttributes = new List<ObjectAttribute>();
objectAttributes.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY));
if (type == "DES")
objectAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES));
else if (type == "DES2")
objectAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES2));
else if (type == "DES3")
objectAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES3));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, label));//PROVAK
using (var session2 = _slot.OpenSession(SessionType.ReadOnly))
{
List<ObjectHandle> foundObjects = session2.FindAllObjects(objectAttributes);
var key = foundObjects[0];
byte[] plainKeyValue = null;
List<ObjectAttribute> readAttrsSensitive = session2.GetAttributeValue(key, new List<CKA>() { CKA.CKA_SENSITIVE });
if (!readAttrsSensitive[0].GetValueAsBool())
{
Utility.Logger("findTargetKeySValue chiave " + label + " non senstive", command);
List<ObjectAttribute> readAttrs = session2.GetAttributeValue(key, new List<CKA>() { CKA.CKA_VALUE });
if (readAttrs[0].CannotBeRead)
throw new Exception("Key cannot be exported");
else
plainKeyValue = readAttrs[0].GetValueAsByteArray();
Console.WriteLine(plainKeyValue);
return plainKeyValue;
}
else
{
Utility.Logger("findTargetKeySValue chiave " + label + " senstive", command);
Console.WriteLine("wrap/unwrap");
objectAttributes = new List<ObjectAttribute>();
objectAttributes.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES3));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, "WRAPPING_KEY")); //WRAPPING_KEY WRK
foundObjects = session2.FindAllObjects(objectAttributes);
var wrappingKey = foundObjects[0];
Mechanism m = new Mechanism(CKM.CKM_DES3_ECB);
var wrapped = session2.WrapKey(m, wrappingKey, key);
//Console.WriteLine("wrapped " + ByteArrayToAsciiHEX(wrapped));
Console.WriteLine(ByteArrayToAsciiHEX(session2.Decrypt(m, wrappingKey, wrapped)));
var k = session2.Decrypt(m, wrappingKey, wrapped);
return k;
}
}
}
catch (Exception e)
{
Console.WriteLine(e.ToSafeString());
Utility.Logger("findTargetKeySValue " + e.ToSafeString(), command);
return null;
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句