证书:找不到用于解密的证书和私钥签名时出错
-
30-09-2019 - |
题
我在为开发人员提供许多服务器和个人电脑的公司工作。服务器是win2003,开发PC是Windows XP。
在名为 preiis01 的服务器 Win2003 中,在预生产环境中,公司其他人员使用任何其他用户(domainCompany\adminsystems)安装客户端证书,用于登录服务器 preiis01。
任何管理员都使用用户“domainCompany\adminsystems”登录服务器 preiis01(使用终端服务器、Windows XP 的远程桌面)。
管理员用户是domainCompany\adminsystems”,它安装证书。
管理员用户安装如下:
会话登录如“ DomainCompany AdminSystems”证书是PFX文件。安装 PFX 并使用向导。密钥私有不检查导出。输入密码并安装。
有一个应用程序Web,其AppPool Identity是:网络服务帐户。
Web服务器是IIS 6.0。
在 preiis01 中,
该管理员用户执行 mmc -> 管理单元 -> 本地计算机的证书。在节点 -> 个人 -> 证书中,他看到了客户端证书:
签发给 ENTIDAD COMPANY INSURE SA - CIF A93 - 姓名 1 姓名 1
由 FNMT Class 2 CA 颁发
在证书属性中,指纹:“93 BC A4 AD 58 C9 3C AF 8B EB 0B 2F 86 C7 9D 81 70 A6 C4 13”
该管理员用户执行以下命令:
winhttpcertcfg.exe LOCAL_MACHINE\My -s "ENTIDAD COMPANY INSURE SA - CIF A93 - NOMBRE SURNAME1 NAME1" -g -a "网络服务"
结果是:
配套证书:
CN=ENTIDAD 公司保险 SA - CIF A93 - 姓名 1 姓名 1
组织单位=703015476
OU=FNMT 2 类 CA
O=FNMT
C=ES
授予帐户的私钥访问:NT 权威机构\网络服务
现在,管理员用户执行以下命令:
winhttpcertcfg.exe -l -c LOCAL_MACHINE\My -s "ENTIDAD COMPANY INSURE SA - CIF A93 - NOMBRE SURNAME1 NAME1"
结果是:
配套证书:
CN=ENTIDAD 公司保险 SA - CIF A93 - 姓名 1 姓名 1
组织单位=700012476
OU=FNMT 2 类 CA
O=FNMT
C=ES
其他帐户和访问私钥的组包括:domainCompany AdminSystems nt Interution System in in Administrator nt Intery Network Service
现在,在服务器 Win2003、IIS 6.0 中的应用程序 Web 的 aspx 页面中,我有以下代码:
笔记:对于“ENTIDAD COMPANY INSURE SA - CIF A93 - NOMBRE SURNAME1 NAME1”证书,X509Certificate2.HasPrivateKeyAccess() 的值为 NO (false)。
ASP.NET 应用程序使用身份执行::NT 权威机构\网络服务
lbInfo.Text += "<br/><br/>ASP.NET application executes using the identity :: <b>" + WindowsIdentity.GetCurrent().Name + "</b><br>";
var store = new X509Store(StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
Certificates = store.Certificates;
repeater1.DataSource = Certificates;
repeater1.DataBind();
var nombreCertificado = "ENTIDAD COMPANY INSURE SA - CIF A93 - NOMBRE SURNAME1 NAME1";
store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection col = store.Certificates.Find(X509FindType.FindBySubjectName, nombreCertificado, false);
if (col.Count > 0)
{
X509Certificate2 certificate = col[0];
store.Close();
Message.Text = "Certificado " + nombreCertificado + " encontrado en " + StoreLocation.LocalMachine;
FirmarConCertificado(nombreCertificado, certificate);
}
else
{
store.Close();
Message.Text = "El certificado " + nombreCertificado + " no esta instalado en la máquina";
}
public void FirmarConCertificado(string nombreCertificado, X509Certificate2 certificate)
{
try
{
var mensaje = "Datos de prueba";
System.Text.Encoding enc = System.Text.Encoding.Default;
byte[] data = enc.GetBytes(mensaje);
var contentInfo = new System.Security.Cryptography.Pkcs.ContentInfo(data);
var signedCms = new System.Security.Cryptography.Pkcs.SignedCms(contentInfo, true);
var cmsSigner = new System.Security.Cryptography.Pkcs.CmsSigner(certificate);
// Sign the CMS/PKCS #7 message
signedCms.ComputeSignature(cmsSigner);
// Encode the CMS/PKCS #7 message
var ret = Convert.ToBase64String(signedCms.Encode());
Message.Text += "Firmado con Certificado " + nombreCertificado + " encontrado en " + StoreLocation.LocalMachine;
}
catch (Exception ex)
{
Message.Text = "Error al firmar con certificado: " + ex.ToString();
Message.Text += "<br /><br />InnerException: " + ex.InnerException;
}
}
该代码对我来说失败了,我收到以下错误:找不到用于解密的证书和私钥。
错误行是:signedCms.ComputeSignature(cmsSigner);
证书错误:System.Security.Cryptography.CryptographicException:找不到证书和私钥进行解密。
at System.Security.Cryptography.Pkcs.PkcsUtils.CreateSignerEncodeInfo(CmsSigner signer, Boolean silent) at System.Security.Cryptography.Pkcs.SignedCms.Sign(CmsSigner signer, Boolean silent) at System.Security.Cryptography.Pkcs.SignedCms.ComputeSignature (CMSSIGNER签名者,布尔值silent)第242行
然后,管理员用户(我记得是安装证书的人)执行以下命令:
FindPrivateKey我的LocalMachine -T“ 93 BC A4 AD 58 C9 3C AF 8B EB 0B 2F 86 C7 9D 81 70 A6 C4 C4 13” –C
findprivatekey我的localmachine -n“ entidad Company Inesure sa -cif a93 -nombre surmame1 name1” –A
findprivatekey我的localmachine -n“ cn = entidad Company Inesure sa -cif a93 -nombre surname1 name1” –A
所有 3 个命令的结果都是相同的:
FindPrivateKey可帮助用户查找X.50 9证书的私钥文件的位置。
用法:FindPrivateKey [{{-n} | {-t}} [-f | -d | -A]
证书的主题名称
证书的指标(使用certmgr.exe获取)
-f 仅输出文件名
-d 仅输出目录
- 输出绝对文件名,例如FindPrivateKey我的现有使用者-n“ CN = John Doe”
例如findprivatekey我的localmachine -t“ 03 33 98 63 D0 47 E7 48 71 33 62 62 64 76 5 C 4C 9D 42 42 1D 6B 52” -C
FindPrivateKey 没有得到任何东西,但 winhttpcertcfg.exe -l 工作正常(匹配证书)
我们使用 winhttpcertcfg.exe 工具向网络服务用户授予权限,并在代码 ASP.NET(在网络服务帐户下执行)中找到了证书。但使用证书签名时失败。
如果有人可以给我们一些信息或建议
更新:
域“domainCompany\Pre_Certificado”中的用户在存储本地计算机中安装证书。
domainCompany\Pre_Certificado 是管理员,位于 IIS_WPG 组中,具有本地策略:“作为服务登录“
我在 IIS 6.0 中配置 AppPool Identity:域公司\Pre_Certificado
ASP.NET 应用程序使用身份执行::域公司\Pre_Certificado
我回收 AppPool 并执行应用程序,我得到 System.Security.Cryptography.CryptographyException:找不到用于解密的证书和私钥
如果我再次测试,使用domainCompany\Pre_Certificado用户登录服务器IIS中的会话,我在ASP.NET应用程序中调用页面,一切正常。
(笔记:使用终端服务器登录服务器IIS)
但是如果在服务器 IIS 中注销会话(用户:domainCompany\Pre_Certificado),我收到相同的错误:
System.Security.Cryptography.CryptographicException:找不到用于解密的证书和私钥
有什么建议 ??
解决方案
请检查这个 文档 这将帮助您解决问题。我建议使用以下命令选项:
winhttpcertcfg -g -c LOCAL_MACHINE\My -s MyCertificate -a TESTUSER
其他提示
按照与以下相同的方式执行前 2 个步骤 IIS 7.5(点击此处)
- 创建/购买证书。确保它有私钥。
- 将证书导入“本地计算机”帐户。最好使用MMC证书。 确保选中“允许导出私钥”
以管理员身份运行以下命令。替换以下内容:
- 将 [Subject] 替换为证书的主题,如果包含空格,请使用引号。我认为只要没有其他以同一主题开头的证书,您也可以只输入第一个单词。
- 将 [Store] 替换为您导入到的证书存储区,我认为在 IIS 6 上默认是“ROOT”或“MY”,即“LOCAL_MACHINE OOT”或“LOCAL_MACHINE\MY”
- 将 [computername] 替换为计算机的名称。您也许可以对 [computernam] 使用“.\”表示法,即“. ETWORK SERVICE”但我还没有尝试过。
winhttpcertcfg.exe -g -a "[计算机名]\网络服务" -c LOCAL_MACHINE\[存储] -s "[主题]"
笔记: 如果您在“NETWORK SERVICE”以外的身份下运行 ASP.NET 应用程序池,则需要将上述命令中的“NETWORK SERVICE”更改为您运行 IIS 应用程序池的身份。
可能还需要向匿名用户授予访问权限。如果您允许匿名访问,则请求将以匿名用户而不是网络服务的身份运行。