使用PFX文件生成具有强名称的COM互操作程序集

使用PFX文件生成具有强名称的COM互操作程序集,com,interop,cryptography,com-interop,public-key-encryption,Com,Interop,Cryptography,Com Interop,Public Key Encryption,我正在尝试使用PFX文件创建一个具有强名称的COM互操作程序集。 TlbImp.exe对使用“sn.exe-k”(包含公钥和私钥)创建的SNK文件非常满意,但问题是我有一个PFX文件… 我可以使用sn.exe-p将公钥从PFX导出到SNK,但它只导出公钥,而TlbImp.exe根本不喜欢。我可以同时导出公钥和私钥吗? 我尝试使用 sn.exe-i MyCompany.pfx xyz 然后使用 TlbImp.exe/keycontainer:xyz…, 但这给了我 TlbImp:错误TI0000:

我正在尝试使用PFX文件创建一个具有强名称的COM互操作程序集。
TlbImp.exe对使用“sn.exe-k”(包含公钥和私钥)创建的SNK文件非常满意,但问题是我有一个PFX文件…
我可以使用sn.exe-p将公钥从PFX导出到SNK,但它只导出公钥,而TlbImp.exe根本不喜欢。我可以同时导出公钥和私钥吗?

我尝试使用
sn.exe-i MyCompany.pfx xyz
然后使用
TlbImp.exe/keycontainer:xyz…,
但这给了我
TlbImp:错误TI0000:指定的强名称参数无效

我能做什么?
谢谢大家!

更新:奥列格的答案和下面的实用程序运行得非常好。 PFX文件(重新导出后)可成功用于提取 与tlbimp.exe(tlbimp.exe)一起使用的公钥(sn.exe-p) /publickey:xyz.pub)。然后可以使用PFX文件对互操作进行重新签名 dll(sn.exe-R)

科摩多真的把球落在了这个上面。下面是转储文件(certutil.exe) -原始和固定pfx文件的dump-v xyz.pfx):

之前:

证书密钥证明信息财产ID(2):
密钥容器={36BDD7BD-F295-47B2-B9E7-C25BD5B4313E}
唯一容器名称: bf63afd9ba3fb912ccd3423c6486e5fc_25e0623f-f712-49e2-abda-f31f014b5dae
Provider=Microsoft增强加密提供程序v1.0
ProviderType=1
标志=0
KeySpec=1——AT_KEYEXCHANGE

私钥:
PRIVATEKEYBLOB
版本:2
aiKeyAlg:0xa400
计算RSA密钥
算法类:0xa000(5)ALG类密钥交换
算法类型:0x400(2)ALG_Type_RSA
算法子id:0x0(0)ALG_SID_RSA_ANY

之后:

证书密钥证明信息财产ID(2):
密钥容器={DBA6454E-F6D2-4F0B-AB1B-9E4F7C0E139C}
唯一容器名称: d2d09f87081c1af7c4225889f1af2250_25e0623f-f712-49e2-abda-f31f014b5dae
Provider=Microsoft增强加密提供程序v1.0
ProviderType=1
标志=0
KeySpec=2——AT_签名 …
私钥:
PRIVATEKEYBLOB
版本:2
aiKeyAlg:0x2400
计算符号
算法类:0x2000(1)ALG_类签名
算法类型:0x400(2)ALG_Type_RSA
算法子id:0x0(0)ALG_SID_RSA_ANY

尝试执行以下操作

sn.exe -p MyCompany.pfx MyCompany.pub
tlbimp.exe My.dll /delaysign /publickey:MyCompany.pub /out:Interop.My.dll
sn.exe -R Interop.My.dll MyCompany.pfx
如果从COM DLL的tlb文件创建主互操作程序集,则将以

tlbimp.exe My.tlb /primary /delaysign /publickey:MyCompany.pub /out:Interop.My.dll
您还可以使用互操作程序集的代码签名:

signtool.exe sign /f MyCompany.pfx /p password /t http://timestamp.verisign.com/scripts/timstamp.dll /v Interop.My.dll
更新:我找到了您出现问题的原因。首先,我应该解释(或提醒)密钥容器的一个功能

私钥存在于密钥容器中。密钥容器可以位于本地硬盘上文件夹
%APPDATA%\Microsoft\Crypto\RSA\YourUserSid
中的某个文件中。同样,密钥容器可以是PFX文件的一部分。在这两种情况下一个密钥容器最多可以保存两个私钥:一个用于数字签名(
AT_签名
)和另一个用于密钥交换(
AT_密钥交换
。您可以查看函数参数以了解更多详细信息。两个密钥可以完全不同。例如,您可以在一个密钥容器的数字签名中持有4096大小的私钥,并在同一容器的密钥交换部分持有另一个2048大小的私钥

证书具有its中的
CERT\u KEY\u PROV\u PROP\u ID
。它保存了
dwKeySpec
(值为
AT\u签名
AT\u密钥交换
或其他类似的
AT\u密钥交换| AT\u签名
)字段与其他字段一起使用的结构
pwszzannerName
le-fe9728d2-af26-4f15-9be0-48c5af6f21dc
pwszProvName
dwProvType
)(
PROV_RSA_FULL
),因此可以从证书中完整引用密钥

问题是您拥有的证书的密钥保存在容器的密钥交换部分,而不是数字签名部分。使用
SignTool.exe
tool时没有问题,但是使用
tlbimp.exe
时会出现错误

TlbImp:错误TI1000:类型库导入程序遇到错误 意外异常:System.Security.SecurityException-无效 程序集公钥。(HRESULT的异常:0x8013141E)

我想这是通过Tucows获得的Comodo或可能是Comodo证书的常见问题

CN = UTN-USERFirst-Object
OU = http://www.usertrust.com
O = The USERTRUST Network
L = Salt Lake City
S = UT
C = US
要重现我描述的问题,您可以执行以下步骤:

1) 创建密钥对,将其保存在新密钥容器的密钥交换中,并创建用于创建密钥对的自签名证书。例如,我们可以使用
MakeCert.exe
的以下参数来执行此操作:

MakeCert.exe-pe-ss MY-a sha1-cy authority-len 2048-e 12/31/2020 -r-n“CN=我的公司根权限,O=我的公司,C=DE”-eku 1.3.6.1.5.5.7.3.3-天空交易所-len 2048-sk myKeyContainer

在上面的示例中,我们使用显式指定的名称
'myKeyContainer'
将新密钥保存在密钥容器中,以便于将来查找和检查。实际上,不指定参数,容器名称将根据新GUID自动生成

2) 使用“证书”管理单元将新创建的证书从MMC.EXE导出为PFX文件。导出过程中必须选择密码。Altern
ChangeKeyProvInfo.exe "Dmitry Streblechenko"
...
  CERT_KEY_PROV_INFO_PROP_ID(2):
    ...
    KeySpec = 1 -- AT_KEYEXCHANGE

...
Private Key:
  PRIVATEKEYBLOB
  Version: 2
  aiKeyAlg: 0xa400
    CALG_RSA_KEYX
    Algorithm Class: 0xa000(5) ALG_CLASS_KEY_EXCHANGE
...
Encryption test passed
...
  CERT_KEY_PROV_INFO_PROP_ID(2):
    ...
    KeySpec = 2 -- AT_SIGNATURE

...
Private Key:
  PRIVATEKEYBLOB
  Version: 2
  aiKeyAlg: 0x2400
    CALG_RSA_SIGN
    Algorithm Class: 0x2000(1) ALG_CLASS_SIGNATURE
...
Signature test passed