dhc*_*cgn 5 elliptic-curve pkcs#11 opensc nitrokey pkcs11interop
我买了一个 NitroKey HSM,想用 EC 推导出一个秘密。 以前的问题
为此,我想使用这些CKM_ECDH1_DERIVE机制。此 HSM 支持哪个,请参阅:

参考PKCS#11 规范,必须考虑:
CKM_ECDH1_DERIVE必须与功能一起使用Derive(页 188)CKM_ECDH1_DERIVE需要CK_ECDH1_DERIVE_PARAMS带有以下参数的参数(页 222):
DeriveKey需要以下参数:
因此,根据这些信息,我尝试实现一种方法。
但我收到此错误:
Net.Pkcs11Interop.Common.Pkcs11Exception:方法 C_DeriveKey 返回 CKR_TEMPLATE_INCOMPLETE
在Session.DeriveKey。
说明CKR_TEMPLATE_INCOMPLETE(第 64 页):
如果提供的模板中的属性值,连同任何默认属性值和对象创建函数本身贡献给对象的任何属性值,都不足以完全指定要创建的对象,则尝试应该失败并显示错误代码CKR_TEMPLATE_INCOMPLETE。
和这里(第 98 页)
CKR_TEMPLATE_INCOMPLETE:为创建对象指定的模板不完整,缺少一些必要的属性。有关更多信息,请参阅第 10.1 节。
但我使用了必要的属性:
想法?
private const string LibraryPath = @"C:\Windows\System32\opensc-pkcs11.dll";
public static byte[] Derive(string privateEc, string publicEc)
{
Func<string, Session, CKO, ObjectHandle> getObjectHandle = (label, session, keyType) =>
{
var objectAttributes = new List<ObjectAttribute>
{
new ObjectAttribute(CKA.CKA_CLASS, keyType),
new ObjectAttribute(CKA.CKA_LABEL, label),
new ObjectAttribute(CKA.CKA_TOKEN, true)
};
return session.FindAllObjects(objectAttributes).First();
};
Func<ObjectHandle, Session, CKA, byte[]> getDataFromObject = (handle, session, type) =>
{
var attributes = new List<ulong> {(ulong) type};
var requiredAttributes = session.GetAttributeValue(handle, attributes);
return requiredAttributes[0].GetValueAsByteArray();
};
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);
var objectPrivate = getObjectHandle(privateEc, session, CKO.CKO_PRIVATE_KEY);
var objectPublic = getObjectHandle(publicEc, session, CKO.CKO_PUBLIC_KEY);
var publicKey = getDataFromObject(objectPublic, session, CKA.CKA_VALUE);
byte[] data = session.GenerateRandom(32);
var mechanism = new Mechanism(CKM.CKM_ECDH1_DERIVE, new CkEcdh1DeriveParams(1000, data, publicKey));
var deriveAttributes = new List<ObjectAttribute>
{
new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY),
new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_GENERIC_SECRET),
};
var derivedKey = session.DeriveKey(mechanism, objectPrivate, deriveAttributes);
var derivedSecret = getDataFromObject(derivedKey, session, CKA.CKA_VALUE);
Console.Out.WriteLine(Convert.ToBase64String(derivedSecret));
return derivedSecret;
}
}
}
Run Code Online (Sandbox Code Playgroud)
另请参阅要点(相同代码)https://gist.github.com/dhcgn/4ea235cdb20155ec5ea9dc9bbf3c9887
现在使用更新的 ObjectAttributes 列表(感谢答案),我得到了异常Net.Pkcs11Interop.Common.Pkcs11Exception : Method C_DeriveKey returned CKR_DATA_LEN_RANGE。
CKR_DATA_LEN_RANGE:加密操作的明文输入数据长度错误。根据操作的机制,这可能意味着明文数据太短、太长,或者不是某个特定块大小的倍数。此返回值的优先级高于 CKR_DATA_INVALID。
因为CKA.CKA_VALUE_LEN我尝试了不同的值但没有成功:
CKA_VALUE_LEN
-------------
24 (192)
40 (320)
48 (384)
Run Code Online (Sandbox Code Playgroud)
我偶然发现了公钥,我不确定我是否以正确的方式提取了公钥。因为它的长度为664 Bit.
CKA.CKA_VALUE的CKO.CKO_PUBLIC_KEY(664 Bit):
BFEEelKE3TrpE3e3f5nJATxEZrU0UeauhV/dFZXeXz5gqgZjuCtkJaUTainC/Mh357x3FyO7sGoPhzokD34oj5PJs0ItvATIKYtzvwaUkdZlDc0=
Run Code Online (Sandbox Code Playgroud)
用pkcs15-tool( 864 Bit)提取
pkcs15-tool.exe --read-public-key 20
-----BEGIN PUBLIC KEY-----
MGowFAYHKoZIzj0CAQYJKyQDAwIIAQEJA1IABHpShN066RN3t3+ZyQE8RGa1NFHm
roVf3RWV3l8+YKoGY7grZCWlE2opwvzId+e8dxcju7BqD4c6JA9+KI+TybNCLbwE
yCmLc78GlJHWZQ3N
-----END PUBLIC KEY-----
Run Code Online (Sandbox Code Playgroud)
pkcs15-tool和之间的公钥不同CKO.CKO_PUBLIC_KEY?CkEcdh1DeriveParams期望哪种格式publicData?publicData以正确的方式提取?或者什么是正确的方法?CKA.CKA_VALUE_LEN等于我的 EC ( 320 Bit)的长度吗?这是对问题的一个非常好的和完整的描述。
CKR_TEMPLATE_INCOMPLETE 处理起来总是很痛苦,因为几乎每个库供应商都希望提供不同的属性集,而这个错误并没有显示缺少哪些确切的属性。
快速查看OpenSC 源代码后,我将尝试使用以下模板:
var deriveAttributes = new List<ObjectAttribute>
{
new ObjectAttribute(CKA.CKA_TOKEN, false),
new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY),
new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_GENERIC_SECRET),
new ObjectAttribute(CKA.CKA_SENSITIVE, false),
new ObjectAttribute(CKA.CKA_EXTRACTABLE, true),
new ObjectAttribute(CKA.CKA_ENCRYPT, true),
new ObjectAttribute(CKA.CKA_DECRYPT, true),
new ObjectAttribute(CKA.CKA_WRAP, true),
new ObjectAttribute(CKA.CKA_UNWRAP, true),
new ObjectAttribute(CKA.CKA_VALUE_LEN, ???)
};
Run Code Online (Sandbox Code Playgroud)
但是我不确定CKA_VALUE_LEN属性的正确值是什么。