- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试使用PFX文件创建一个名为COM的互操作程序集。
TlbImp.exe非常满意使用“ sn.exe -k”(包含公钥和私钥)创建的SNK文件,但问题是我有一个PFX文件...
我可以使用sn.exe -p将公用密钥从PFX导出到SNK,但它只能导出公用密钥,而TlbImp.exe根本不喜欢。我可以同时导出公钥和私钥吗?
我尝试使用安装PFX文件
sn.exe -i MyCompany.pfx xyz
然后使用导入类型库
TlbImp.exe / keycontainer:xyz ...“,
但这给了我
TlbImp:错误TI0000:指定了无效的强名称参数。
我能做什么?
谢谢!
更新:奥列格的答案和下面的实用程序完美地工作。
PFX文件(重新导出后)可以成功用于提取
公用密钥(sn.exe -p)与tlbimp.exe(tlbimp.exe)一起使用
/publickey:xyz.pub)。然后可以使用PFX文件对互操作进行重新签名
dll(sn.exe -R)
Comodo确实确实把球丢了上。下面是转储(certutil.exe
-dump -v xyz.pfx)的原始和固定PFX文件:
之前:
CERT_KEY_PROV_INFO_PROP_ID(2):
密钥容器= {36BDD7BD-F295-47B2-B9E7-C25BD5B4313E}
唯一的容器名称:
bf63afd9ba3fb912ccd3423c6486e5fc_25e0623f-f712-49e2-abda-f31f014b5dae
提供程序= Microsoft增强加密提供程序v1.0
ProviderType = 1
标志= 0
KeySpec = 1-AT_KEYEXCHANGE
...
私钥:
私钥
版本:2
aiKeyAlg:0xa400
CALG_RSA_KEYX
算法类别:0xa000(5)ALG_CLASS_KEY_EXCHANGE
算法类型:0x400(2)ALG_TYPE_RSA
算法子ID:0x0(0)ALG_SID_RSA_ANY
后:
CERT_KEY_PROV_INFO_PROP_ID(2):
密钥容器= {DBA6454E-F6D2-4F0B-AB1B-9E4F7C0E139C}
唯一的容器名称:
d2d09f87081c1af7c4225889f1af2250_25e0623f-f712-49e2-abda-f31f014b5dae
提供程序= Microsoft增强加密提供程序v1.0
ProviderType = 1
标志= 0
KeySpec = 2-AT_SIGNATURE
...
私钥:
私钥
版本:2
aiKeyAlg:0x2400
CALG_RSA_SIGN
算法类别:0x2000(1)ALG_CLASS_SIGNATURE
算法类型: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
tlbimp.exe
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_SIGNATURE
),另一个用于密钥交换(
AT_KEYEXCHANGE
)。您可以浏览
CryptGenKey函数的参数以获取更多详细信息。两个键可以完全不同。例如,您可以将一个大小为4096的密钥容器的私钥保存在数字签名中,并将另一个大小为2048的私钥保存在同一容器的密钥交换部分中。
CERT_KEY_PROV_INFO_PROP_ID
。它保存
CRYPT_KEY_PROV_INFO结构,其中
dwKeySpec
(具有值
AT_SIGNATURE
,
AT_KEYEXCHANGE
或其他类似
AT_KEYEXCHANGE | AT_SIGNATURE
的字段)与其他字段
pwszContainerName
(例如
le-fe9728d2-af26-4f15-9be0-48c5af6f21dc
),
pwszProvName
(例如
dwProvType
)。因此,可以完全参考证书中的密钥。
PROV_RSA_FULL
工具的情况下没有问题,但是在使用
SignTool.exe
的情况下会出现错误
CN = UTN-USERFirst-Object
OU = http://www.usertrust.com
O = The USERTRUST Network
L = Salt Lake City
S = UT
C = US
tlbimp.exe
的以下参数来执行此操作:
MakeCert.exe
的密钥容器中,以方便将来查找和检查。实际上,无需指定参数,容器名称将基于新的GUID自动生成。
'myKeyContainer'
进行相同的操作。
CertUtil.exe
与-p参数一起使用来执行此操作:
sn.exe
重现该错误。
tlbimp.exe
,则
-sky exchange
的使用将成功,您可以在下一步中使用
tlbimp.exe
。之后,您可以另外对dll使用代码签名
Interop.My.dll
而不是AT_KEYEXCHANGE。如果打开密钥容器,则应将
AT_SIGNATURE
用作
KeyNumber.Exchange
参数,并在下一步中使用
CspParameters.KeyNumber
。
KeyNumber.Signature
中设置名称为
REG_DWORD
且值为2(
KeySpec
)的
AT_SIGNATURE
值。我对此进行了测试,但这对
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\StrongName
的使用没有帮助。
tlbimp.exe
。例如
ChangeKeyProvInfo.exe "Dmitry Streblechenko"
#define STRICT
#include <windows.h>
#include <wincrypt.h>
#include <tchar.h>
#pragma comment (lib, "Crypt32.lib")
int _tmain(int argc, LPCTSTR *argv)
{
HCERTSTORE hStore = NULL;
PCCERT_CONTEXT pCertContext = NULL;
LPCTSTR pszCertSubjectName = NULL;
BOOL bSuccess, bResult = FALSE;
DWORD cbData = 0, dwKeySpec = 0;
HCRYPTKEY hKey = 0, hKeyNew = 0;
BOOL fCallerFreeProvOrNCryptKey;
PBYTE pPrivateKeyBlob = NULL;
PUBLICKEYSTRUC *pPublicKey = NULL;
HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProvOrNCryptKey = 0;
PCRYPT_KEY_PROV_INFO pKeyProvInfo = NULL;
if (argc != 2) {
_tprintf(TEXT("USAGE:\r\n\tChangeKeyProvInfo.exe CertSubjectName\n"));
return 1;
}
pszCertSubjectName = argv[1];
__try {
hStore = CertOpenStore (CERT_STORE_PROV_SYSTEM,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
(HCRYPTPROV_LEGACY)0,
CERT_STORE_ENUM_ARCHIVED_FLAG | CERT_STORE_OPEN_EXISTING_FLAG | CERT_SYSTEM_STORE_CURRENT_USER,
TEXT("MY"));
if (hStore == NULL) {
_tprintf(TEXT("Error in CertOpenStore(): %d"), GetLastError());
__leave;
}
pCertContext = CertFindCertificateInStore (hStore,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
0,
CERT_FIND_SUBJECT_STR,
pszCertSubjectName,
NULL);
if (pCertContext == NULL) {
_tprintf(TEXT("Error in CertFindCertificateInStore(): %d"), GetLastError());
__leave;
}
bSuccess = CryptAcquireCertificatePrivateKey(pCertContext,
CRYPT_ACQUIRE_COMPARE_KEY_FLAG | CRYPT_ACQUIRE_NO_HEALING,
NULL,
&hCryptProvOrNCryptKey,
&dwKeySpec,
&fCallerFreeProvOrNCryptKey);
if (!bSuccess) {
_tprintf(TEXT("Error in CryptAcquireCertificatePrivateKey(): %d"), GetLastError());
__leave;
}
bSuccess = CryptGetUserKey (hCryptProvOrNCryptKey, dwKeySpec, &hKey);
if (!bSuccess) {
_tprintf(TEXT("Error in CryptGetUserKey(): %d"), GetLastError());
__leave;
}
// get privale key as clear text data in form PRIVATEKEYBLOB
cbData = 0;
bSuccess = CryptExportKey (hKey, 0, PRIVATEKEYBLOB, 0, NULL, &cbData);
if (!bSuccess) {
_tprintf(TEXT("Error in CryptExportKey(): %d"), GetLastError());
__leave;
}
pPrivateKeyBlob = (PBYTE)LocalAlloc(LPTR, cbData);
if (pPrivateKeyBlob == NULL) {
_tprintf(TEXT("Error in LocalAlloc(): %d"), GetLastError());
__leave;
}
bSuccess = CryptExportKey (hKey, 0, PRIVATEKEYBLOB, 0, pPrivateKeyBlob, &cbData);
if (!bSuccess) {
_tprintf(TEXT("Error in CryptExportKey(): %d"), GetLastError());
__leave;
}
// the PRIVATEKEYBLOB started with the PUBLICKEYSTRUC which contains the KeyAlg
// CALG_RSA_KEYX are used for AT_KEYEXCHANGE
// CALG_RSA_SIGN are used for AT_SIGNATURE
pPublicKey = (PUBLICKEYSTRUC *)pPrivateKeyBlob;
if (pPublicKey->aiKeyAlg == CALG_RSA_SIGN) {
_tprintf(TEXT("Currently AT_SIGNATURE are used - nothing to do.\n"));
__leave;
} else if (pPublicKey->aiKeyAlg != CALG_RSA_KEYX) {
_tprintf(TEXT("ERROR: Unknown algorithm 0x%X are used\n"), pPublicKey->aiKeyAlg);
__leave;
}
// !!!!!! the next line in the most important !!!!!!
pPublicKey->aiKeyAlg = CALG_RSA_SIGN;
bSuccess = CryptImportKey (hCryptProvOrNCryptKey, pPrivateKeyBlob, cbData, (HCRYPTKEY)NULL, CRYPT_EXPORTABLE, &hKeyNew);
if (!bSuccess) {
_tprintf(TEXT("Error in CertGetCertificateContextProperty(): %d"), GetLastError());
__leave;
}
_tprintf(TEXT("The key container has successfully imported the same key for the AT_SIGNATURE usage.\n"));
bSuccess = CertGetCertificateContextProperty (pCertContext, CERT_KEY_PROV_INFO_PROP_ID, 0, &cbData);
if (!bSuccess) {
_tprintf(TEXT("Error in CertGetCertificateContextProperty(): %d"), GetLastError());
__leave;
}
pKeyProvInfo = (PCRYPT_KEY_PROV_INFO)LocalAlloc (LPTR, cbData);
if (pKeyProvInfo == NULL) {
_tprintf(TEXT("Error in LocalAlloc(): %d"), GetLastError());
__leave;
}
bSuccess = CertGetCertificateContextProperty (pCertContext, CERT_KEY_PROV_INFO_PROP_ID, pKeyProvInfo, &cbData);
if (!bSuccess) {
_tprintf(TEXT("Error in CertGetCertificateContextProperty(): %d"), GetLastError());
__leave;
}
// !!!!!! the next line in the most important !!!!!!
pKeyProvInfo->dwKeySpec = AT_SIGNATURE;
bSuccess = CertSetCertificateContextProperty (pCertContext, CERT_KEY_PROV_INFO_PROP_ID, CERT_SET_PROPERTY_IGNORE_PERSIST_ERROR_FLAG, pKeyProvInfo);
if (!bSuccess) {
_tprintf(TEXT("Error in CertSetCertificateContextProperty(): %d"), GetLastError());
__leave;
}
_tprintf(TEXT("The certificale property was successfully changed to use the key with AT_SIGNATURE.\n"));
bResult = TRUE;
}
__finally {
if (pPrivateKeyBlob)
pPrivateKeyBlob = (PBYTE) LocalFree (pPrivateKeyBlob);
if (pKeyProvInfo)
pKeyProvInfo = (PCRYPT_KEY_PROV_INFO) LocalFree (pKeyProvInfo);
if (pCertContext)
bSuccess = CertFreeCertificateContext (pCertContext);
if (hKeyNew)
bSuccess = CryptDestroyKey (hKeyNew);
if (hCryptProvOrNCryptKey)
bSuccess = CryptReleaseContext (hCryptProvOrNCryptKey, 0);
if (hStore)
bSuccess = CertCloseStore (hStore, CERT_CLOSE_STORE_CHECK_FLAG);
}
return bResult? 0: 1;
}
ChangeKeyProvInfo.exe
分析保存在
My.pfx中的第一个证书。您可以看到完整的输出
here。输出中最重要的部分是:
...
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
certutil.exe -dump -v My.pfx
的
The output表明问题已解决:
...
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
关于com - 使用PFX文件制作一个名为COM的互操作程序集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8365849/
我试图找出如何访问 ClojureScript 中的 Javascript 对象属性。如果我事先知道属性(property)的名称,那就很容易了。获取foo.bar我只是做 (.-bar foo) I
我是 .NET 的新手。我想制作一个控制台应用程序,将 .pptx 文件转换为 .wmv。我已经使用 powerpoint interop 做到了这一点。但我有一些问题。首先,如果我构建应用程序并将其
我计划将我的许可系统的核心转移到 C++,但我仍然更喜欢使用 .NET 前端进行设计。无论如何,我刚刚读完互操作功能,并决定对其进行测试。问题是,它对我来说只是花花公子,但对任何其他用户都不起作用。我
系统管理员正在编写一些常用的管理 Power Shell 脚本。主要用于 AD 管理(更新交易所详细信息、在安全组中移动人员等) 我想使用 C# 中的这些脚本(我打算将其编写为库,供网站使用)。 我看
我想在我的应用程序中使用 COM 对象。 如何确保对象已在机器中注册? 我找到的唯一解决方案(也是 on SO)是在初始化周围使用 try-catch block : try { Foo.Ba
这个问题在这里已经有了答案: How to call Java code from C#? (4 个答案) 关闭 10 个月前。 您能给我一些关于使 C# 代码和 Java 代码互操作的建议吗?让我
我正在使用 Microsoft.Office.Interop.Excel 从 C# 创建一个 Excel 工作表,但我无法按照用户想要的方式获取页脚。 1) 如何将页脚文本加粗? 2)如何将页码放在页
我正在使用 F# 和 Excel Interop 将数据输出到 Excel 电子表格。我的第一种方法是单独设置每个单元格: worksheet.Range(range1).Value2 <- "=su
与来自 Silverlight 的 COM 控件进行交互的选项有哪些? 在我的特定项目中,我有一个旧的 ActiveX 身份验证控件,我想在我的 Silverlight 应用程序中利用它。没有太多无聊
我需要针对以下场景的一些建议: 我的 Uni 组有一个巨大的 SVN 存储库。我实际上对整个项目的子目录感兴趣(例如/trunk/projects/my_project)- 不知道它是否真的与 SVN
我有一个 .NET 程序集,它是通过 COM Interop 从 Delphi 主机调用的。据我所知,.NET 代码中任何未处理的异常都将由 .net com 互操作框架处理,并且相应的 HRESUL
我有一个程序可以在单击按钮时创建两个 pdf 文件。它在 WinForms 中使用 Microsoft Office 互操作,文件创建过程如下; 用户在程序中工作 点击按钮 程序根据一个带有书签的模板
我有一个第三方 DLL 用 Delphi“a.dll”(无源代码)编写。 这个 DLL 有一个带有这个签名的方法。 function GetAny(pFileName: String): String
想知道是否有人成功使用 JDEdwards XMLInterop 功能。我已经使用它有一段时间了(使用一个简单的 PInvoke,稍后将发布代码)。我正在寻找是否有更好和/或更强大的方法。 谢谢。 最
我正在尝试让 javafx2 与 Clojure 一起使用 - 在实现像 DoubleBinding 这样的抽象类时,我不确定 Clojure 中 super.bind(moo) 的等价物是什么。我正
有人有使用 Firebird 与 .NET 框架互操作的经验吗?如果有,进展如何? 最佳答案 我在商业桌面应用程序中使用了 firebird。 它的性能很好,直到您处理返回大型结果集的查询。在这些情况
我正在 Excel 工作表中复制并插入行,如下所示: while (rowsToAdd > 0) { // copy the existing row insert
我无法确保正确销毁托管窗口。 我有一个 HwndHost 派生类,正在 TabControl 中显示(尽管这可能不相关)。我试图在选项卡关闭时销毁托管内容(而不是在包含的窗口关闭时)。 我目前拥有 m
我有两个 python 类,它们都可以使用 COM 互操作机制独立于 VBA 编写脚本。但我希望一个能够以父子模式或工厂模式控制另一个的创建。 我已经尝试过,但无法开始工作,我已将其提炼为下面的 MC
我们在我们编写的 C# dll(程序集 A)中使用 Microsoft 提供的 COM DLL (dsofile.dll)。为了避免必须注册 COM dll,我已将对 dsofile.dll 的引用的
我是一名优秀的程序员,十分优秀!