热门使用机制CKM_ECDH1_DERIVE与pkcs11interop

时间:2017-02-21 21:31:14

标签: pkcs#11 elliptic-curve opensc pkcs11interop nitrokey

我买了一台NitroKey HSM并希望通过EC获得一个秘密。 Previosly question

为此,我想使用CKM_ECDH1_DERIVE机制。这个HSM支持哪个,请参阅:

参考PKCS#11 specification必须考虑这一点:

  1. 机制CKM_ECDH1_DERIVE必须与函数Derive(页188)
  2. 一起使用
  3. 机制CKM_ECDH1_DERIVE期望参数CK_ECDH1_DERIVE_PARAMS(页222)具有以下参数:
    1. kdf :共享密钥值(CKD)上使用的密钥派生函数
    2. sharedData :双方共享的一些数据
    3. publicData :其他方的EC公钥值
  4. 函数DeriveKey期望这些参数:
    1. 机制CKM.CKM_ECDH1_DERIVE
    2. ObjectHandle PrivateKey
    3. ObjectAttributes(第338页)
      1. CKA.CKA_CLASS - > CKO.CKO_SECRET_KEY
      2. CKA.CKA_KEY_TYPE - > CKK.CKK_GENERIC_SECRET
      3. 但是"但是,由于这些事实都隐含在机制中,因此无需指定其中任何一个"所以这些可以为空吗?
  5. 问题

    所以有了这些信息,我试图实现一种方法。

    但是我得到了这个错误:

      

    Net.Pkcs11Interop.Common.Pkcs11Exception:方法C_DeriveKey返回CKR_TEMPLATE_INCOMPLETE

    Session.DeriveKey

    CKR_TEMPLATE_INCOMPLETE的说明(页64):

      

    如果提供的模板中的属性值与任何默认属性一起使用   值和由对象创建贡献给对象的任何属性值   函数本身,不足以完全指定要创建的对象,然后尝试   应该失败,错误代码为CKR_TEMPLATE_INCOMPLETE。

    和此处(页98)

      

    CKR_TEMPLATE_INCOMPLETE:为创建对象指定的模板是   不完整,缺乏一些必要的属性。更多信息,请参见第10.1节   信息。

    但我使用了nesseary属性:

    1. CKA.CKA_CLASS - > CKO.CKO_SECRET_KEY
    2. CKA.CKA_KEY_TYPE - > CKK.CKK_GENERIC_SECRET
    3. 想法?

      代码

      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;
              }
          }
      }
      

      另请参阅要点(相同代码)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)
      

      我偶然发现了公钥,我不确定我是否以正确的方式提取公钥。因为它的长度为664 Bit

      CKA.CKA_VALUECKO.CKO_PUBLIC_KEY)的

      664 Bit

      BFEEelKE3TrpE3e3f5nJATxEZrU0UeauhV/dFZXeXz5gqgZjuCtkJaUTainC/Mh357x3FyO7sGoPhzokD34oj5PJs0ItvATIKYtzvwaUkdZlDc0=
      

      使用pkcs15-tool864 Bit

      提取
      pkcs15-tool.exe --read-public-key 20
      -----BEGIN PUBLIC KEY-----
      MGowFAYHKoZIzj0CAQYJKyQDAwIIAQEJA1IABHpShN066RN3t3+ZyQE8RGa1NFHm
      roVf3RWV3l8+YKoGY7grZCWlE2opwvzId+e8dxcju7BqD4c6JA9+KI+TybNCLbwE
      yCmLc78GlJHWZQ3N
      -----END PUBLIC KEY-----
      
      • 为什么pkcs15-toolCKO.CKO_PUBLIC_KEY之间的公钥不同?
      • CkEcdh1DeriveParamspublicData期望采用哪种格式?
      • 我是否以正确的方式提取publicData?或者正确的方法是什么?
      • CKA.CKA_VALUE_LEN的值是否必须等于我的EC(320 Bit)的长度?

1 个答案:

答案 0 :(得分:4)

这是一个非常好的和完整的问题描述。

CKR_TEMPLATE_INCOMPLETE总是很难处理,因为几乎每个图书馆供应商都希望提供不同的属性集,而这个错误并不能揭示缺少哪些确切的属性。

快速查看OpenSC source code后,我会尝试使用以下模板:

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, ???)
};

但我不确定CKA_VALUE_LEN属性的正确值是什么。