【问题标题】:PKCS11 unwrap private RSA key to eToken HSMPKCS11 将私有 RSA 密钥解包到 eToken HSM
【发布时间】:2019-08-27 14:41:13
【问题描述】:

我正在尝试通过 PKCS#11 互操作将 RSA 私钥传输到我的 HSM(SafeNet eToken),然后在 HSM 上解包。

这是我的代码(更新):

            session.Login(CKU.CKU_USER, pin);
            var x509Certificate = new X509Certificate2(File.ReadAllBytes(path), "", X509KeyStorageFlags.Exportable);
            var privateKey = x509Certificate.PrivateKey as RSACryptoServiceProvider;
            var keyPair = DotNetUtilities.GetRsaKeyPair(privateKey);
            byte[] privateKeyBytes;
            using (var memoryStream = new MemoryStream())
            {
                using (TextWriter streamWriter = new StreamWriter(memoryStream))
                {
                    var pemWriter = new PemWriter(streamWriter);
                    pemWriter.WriteObject(keyPair.Private);
                    streamWriter.Flush();
                }
                privateKeyBytes = memoryStream.GetBuffer();
            }

            // Create temporary DES3 key for wrapping/unwrapping
            var tempKeyAttributes = new List<ObjectAttribute>
            {
                new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY),
                new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES3),
                new ObjectAttribute(CKA.CKA_ENCRYPT, true),
                new ObjectAttribute(CKA.CKA_UNWRAP, true)
            };
            var tempKey = session.GenerateKey(new Mechanism(CKM.CKM_DES3_KEY_GEN), tempKeyAttributes);

            var encrypted =
                session.Encrypt(new Mechanism(CKM.CKM_DES3_ECB), tempKey, privateKeyBytes);

            string label = "private1";

            // Define how the new RSA private key should look like on the HSM
            var privateKeyAttributes = new List<ObjectAttribute>
            {
                new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_PRIVATE_KEY),
                new ObjectAttribute(CKA.CKA_TOKEN, true),
                new ObjectAttribute(CKA.CKA_PRIVATE, true),
                new ObjectAttribute(CKA.CKA_MODIFIABLE, true),
                new ObjectAttribute(CKA.CKA_SENSITIVE, false),
                new ObjectAttribute(CKA.CKA_LABEL, label),
                new ObjectAttribute(CKA.CKA_ID, Encoding.ASCII.GetBytes(label)),
                new ObjectAttribute(CKA.CKA_ALWAYS_AUTHENTICATE, false),
                new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_RSA),

            };
            var privateKeyHandle = session.UnwrapKey(new Mechanism(CKM.CKM_DES3_ECB), tempKey,
                encrypted, privateKeyAttributes);


//results in: Method C_UnwrapKey returned CKR_WRAPPED_KEY_INVALID

但它不起作用 - 以 Net.Pkcs11Interop.Common.Pkcs11Exception: Method C_UnwrapKey returned CKR_TEMPLATE_INCONSISTENT 失败。

(更新) 现在它会导致 CKR_WRAPPED_KEY_INVALID。 但是,如果我使用 SafeNet 手动导入相同的 PFX 文件,则不会出现错误 - 一切似乎都很好。

有什么想法吗?可能是我用错了一些参数?

【问题讨论】:

  • 在 yourprivateKeyAttributes 中尝试不要从私钥设置任何属性。基本上你设置的最后 8 个属性(模数,...系数),删除它们,然后使用其他属性。这些将在解包成功后填充。
  • Vladimir 您是否通过第一条评论的提示解决了您的问题?
  • (根据您的建议更新了顶部的方法代码)谢谢,CKR_TEMPLATE_INCONSISTENT 已消失,但现在我收到“方法 C_UnwrapKey 返回 CKR_WRAPPED_KEY_INVALID”。所以,privateKeyBytes 长度正好是 2048。但是如果我使用 SafeNet 手动导入相同的 PFX 文件,则不会发生错误 - 一切似乎都很好。
  • 您当前正在使用ECB 模式。通过提供IV 尝试使用CBC 模式加密私钥。
  • @VladimirK 我认为您不应该使用 PEM 编码的私钥。看看this answer to similar question

标签: pkcs#11 pkcs11interop


【解决方案1】:

最后是做这件事的代码:

   var x509Certificate = new X509Certificate2(File.ReadAllBytes(path), "",
                X509KeyStorageFlags.Exportable);
            var privateKey = x509Certificate.PrivateKey as RSACryptoServiceProvider;
            if (privateKey == null) throw new Exception($"Private key is null for {x509Certificate.SerialNumber}");
            var privateKeyParams = privateKey.ExportParameters(true);
            session.Login(CKU.CKU_USER, pin);
            // Create temporary DES3 key for wrapping/unwrapping
            var tempKeyAttributes = new List<ObjectAttribute>
            {
                new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY),
                new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES3),
                new ObjectAttribute(CKA.CKA_ENCRYPT, true),
                new ObjectAttribute(CKA.CKA_DECRYPT, true),
                new ObjectAttribute(CKA.CKA_UNWRAP, true),
                new ObjectAttribute(CKA.CKA_WRAP, true)
            };
            // Preparing unencrypted private key
            var unencryptedPrivateKey = PrivateKeyInfoFactory.CreatePrivateKeyInfo(
                new RsaPrivateCrtKeyParameters(
                    new BigInteger(1, privateKeyParams.Modulus),
                    new BigInteger(1, privateKeyParams.Exponent),
                    new BigInteger(1, privateKeyParams.D),
                    new BigInteger(1, privateKeyParams.P),
                    new BigInteger(1, privateKeyParams.Q),
                    new BigInteger(1, privateKeyParams.DP),
                    new BigInteger(1, privateKeyParams.DQ),
                    new BigInteger(1, privateKeyParams.InverseQ))).GetEncoded();
            var tempKey = session.GenerateKey(new Mechanism(CKM.CKM_DES3_KEY_GEN), tempKeyAttributes);
            var result = new MemoryStream();
            var stream = new MemoryStream(unencryptedPrivateKey);
            //Encrypting
            session.Encrypt(new Mechanism(CKM.CKM_DES3_ECB), tempKey, stream,
                result);
            var encrypted = result.ToArray();
            string label = x509Certificate.SerialNumber;
            // Define how the new RSA private key should look like on the HSM
            var privateKeyAttributes = new List<ObjectAttribute>
            {
                new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_PRIVATE_KEY),
                new ObjectAttribute(CKA.CKA_TOKEN, true),
                new ObjectAttribute(CKA.CKA_PRIVATE, true),
                new ObjectAttribute(CKA.CKA_MODIFIABLE, true),
                new ObjectAttribute(CKA.CKA_SENSITIVE, false),
                new ObjectAttribute(CKA.CKA_LABEL, label),
                new ObjectAttribute(CKA.CKA_ID, Encoding.ASCII.GetBytes(label)),
                new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_RSA)
            };
            var privateKeyHandle = session.UnwrapKey(new Mechanism(CKM.CKM_DES3_ECB), tempKey,
                encrypted, privateKeyAttributes);
            return privateKeyHandle;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多