PKCS11Interop:如何使用私钥提取证书?

PKCS11Interop : How to extract certificate with private key?

我有一个第三方应用程序(我们不想使用),它可以使用私钥从我们的卡 reader 中提取证书,并将其插入存储。 正如我所说,我们出于多种原因不想使用它,所以我们尝试通过 PKCS11 直接读取卡 reader。 当我们在 C# 中开发时,我们使用 PKCS11 Interop 库来管理它。但是,我无法检索链接到此证书的关联私钥。我该怎么做?

这是我的代码:

List<ObjectAttribute> objectAttributes = new List<ObjectAttribute>();
objectAttributes.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_CERTIFICATE));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_PRIVATE, false));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_TOKEN, true));
//objectAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, UTF8Encoding.UTF8.GetBytes("Certificat d'Authentification CPS")));
//CurrentSession.FindObjectsInit(objectAttributes);
oObjCollection = CurrentSession.FindAllObjects(objectAttributes);
//if (oObjCollection.Count > 0)
foreach (var item in oObjCollection)
{
  var oAttriVal = CurrentSession.GetAttributeValue(item, new List<CKA>() { CKA.CKA_VALUE, CKA.CKA_ID }).FirstOrDefault();
  oResult = new X509Certificate2(oAttriVal.GetValueAsByteArray());
  X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
  store.Open(OpenFlags.ReadWrite);
  store.Add(oResult);
  store.Close();
}

如果我尝试检索私钥,我可以,但它不可读,否则我看不到如何将它与我检索到的证书相关联?

List<ObjectAttribute> objectAttributes = new List<ObjectAttribute>();
                objectAttributes = new List<ObjectAttribute>();

                objectAttributes = new List<ObjectAttribute>();
                objectAttributes.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_PRIVATE_KEY));
                objectAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_RSA));

                CurrentSession.FindObjectsInit(objectAttributes);
                var oObjCollection = CurrentSession.FindObjects(1);
                if (oObjCollection.Count > 0)
                {
                    oPrivKeyObjectHandle = oObjCollection[0];
                }
                List<ObjectAttribute> privKeyAttributes = new List<ObjectAttribute>();
                if (oPrivKeyObjectHandle != null)
                {
                    List<CKA> privKeyAttrsToRead = new List<CKA>();
                    privKeyAttrsToRead.Add(CKA.CKA_LABEL);
                    privKeyAttrsToRead.Add(CKA.CKA_ID);
                    privKeyAttrsToRead.Add(CKA.CKA_VALUE);
                    privKeyAttrsToRead.Add(CKA.CKA_VALUE_BITS);

                    privKeyAttributes = CurrentSession.GetAttributeValue(oPrivKeyObjectHandle, privKeyAttrsToRead);
                }
                CurrentSession.FindObjectsFinal();

感谢您的帮助

在大多数情况下,您不需要 - 大多数 PKCS#11 设备不允许您从设备中提取私钥,这是有原因的。

您所指的"driver"很可能不会提取密钥,但可以在系统需要执行此类操作时通过调用设备上的签名和解密功能来使用私钥.这是由许多供应商提供的 CSP 模块完成的。

您将需要做同样的事情,即如果不编写您自己的 CSP(加密服务提供商),您很可能无法使用 CryptoAPI 进行操作,这将与您的第三方应用程序执行相同的操作。

我终于成功了。

我的流程是这样的:我用第三方软件分析存储的证书的私钥。

当我这样做时,我会像这样从第三方 DLL 加载 CspParameters :

var oParams = new CspParameters(1, "ASIP Sante Cryptographic Provider");
oParams.Flags = CspProviderFlags.UseExistingKey;
oParams.KeyNumber = (int)KeyNumber.Signature;
oParams.KeyContainerName = System.Text.RegularExpressions.Regex.Replace(GetAttributeValue(item, CKA.CKA_SUBJECT).First().GetValueAsString(), @"[^\u0020-\u007E]", string.Empty);

在我的特定情况下,KeyContainerName 是只有 ASCII 字符的主题(这不是默认情况)。

当我用这个 CSP 创建 RSACryptoServiceProvider 时,效果很好,我终于不能使用第三方应用程序了。

请注意,ASIP Sante Cryptographic Provider 是与第三方软件一起安装的提供程序,它带有用于 Windows CSP 的特定 DLL。

此代码可能与 Mono 不兼容,Linux/Mac ...