【问题标题】:Problems when P/Invoking CertCreateSelfSignCertificateP/Invoking CertCreateSelfSignCertificate 时的问题
【发布时间】:2015-06-10 12:49:15
【问题描述】:

我关注this article (in it there is a link to a .cs file at the bottom of the page) 以生成自签名X509Certificate2。文章中的代码有效,但现在我想扩展它。我正在尝试将可选参数_In_opt_ PCRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm 传递给CertCreateSelfSignCertificate

我已经为它创建了这个结构:

struct CryptoApiBlob
{
    public Int32 cbData;
    public IntPtr pbData;
}

struct CryptAlgorithmIdentifier {
    public String pszObjId;
    public CryptoApiBlob Parameters;
}

我试图用来创建它的代码是:

CryptAlgorithmIdentifier algorithm = new CryptAlgorithmIdentifier { pszObjId = "szOID_NIST_AES256_CBC", Parameters = new CryptoApiBlob { cbData = 0 } };
algorithmPointer = Marshal.AllocHGlobal(Marshal.SizeOf(algorithm));
Marshal.StructureToPtr(algorithm, algorithmPointer, false);

然后我将algorithmPointer 传递给方法。

当我尝试将其传递给 CertCreateSelfSignCertificate 时出现此错误:

未处理的类型异常 在 mscorlib.dll 中发生“System.Runtime.InteropServices.COMException”

附加信息:函数调用的 ASN1 参数错误。 (HRESULT 异常:0x80093109)

是否有人碰巧知道为什么会发生这种情况,或者可以看到我定义结构或在内存中分配结构的方式有任何问题?

【问题讨论】:

  • COMException?无需通过 P/Invoke 调用 COM。 .NET 很容易与 COM 集成。但乍一看,strings 很难互操作,而且你没有表现出足够的帮助。哦,你不需要任何 P/Invokes 来处理这个 - .NET 有你需要的一切。例如,请参阅stackoverflow.com/questions/22230745/…
  • @Luaan .NET 有自签名证书吗?很抱歉,您发布的示例使用了名为 Bouncy Castle 的第 3 方 API。我不打算使用任何 3rd 方 API。
  • 呃,我的错 - 看到这个,直接使用 COM - stackoverflow.com/questions/13806299/… 仍然可以在纯 .NET 中做所有事情,但 COM 工作得很好。
  • @Luaan 很有帮助,谢谢!
  • 是的,这只是被无异常代码隐藏的真正错误位置。但是很明显,您尝试 P/Invoke 的方法只是底层 COM 功能的 C 包装器。坚持使用 COM - .NET 基本上是 COM 2.0 :))

标签: c# .net pinvoke marshalling x509certificate2


【解决方案1】:

正如@Luaan 所指出的,在 p/invoke 中正确编组字符串可能很棘手,通常最容易避免 p/invoke 互操作。但是我仍然很好奇这里出了什么问题。

PCRYPT_ALGORITHM_IDENTIFIER 上的 MSDN 文档看来,在这种情况下,您应该传入算法 "2.16.840.1.101.3.4.1.42" 的实际 OID。列表中的szOID_NIST_AES256_CBC 只有扩展为所述 OID 字符串的 C/C++ 标识符(或宏)。

【讨论】:

  • 我之前试过了,但问题是我收到以下错误消息:Invalid algorithm specified. (Exception from HRESULT: 0x80090008)
  • 可以,因为没有“szOID_NIST_AES256_CBC”算法的地方。应该有来自 sha1、sha2 系列的 OID 值。
  • @CryptoGuy 我很幸运,例如,1.2.840.113549.1.1.13 (szOID_RSA_SHA512RSA)。您能否详细说明为什么它需要使用 SHA 系列?
  • 根据您的问题,您正在配置签名算法。它必须是适合数字签名的非对称算法。 AES 是对称算法,仅用于加密操作。 SHA(X) 是签名算法。另外,我不建议在测试之前使用 SHA512,因为例如,它在 Windows 中默认不启用。
  • @CryptoGuy 也许你可以帮我解决(几乎相同的问题,但略有不同):stackoverflow.com/questions/30794112/…
【解决方案2】:

这个问题很老,但我想我会分享我的见解。 MSDN 将CRYPT_ALGORITHM_IDENTIFIER 列为:

typedef struct _CRYPT_ALGORITHM_IDENTIFIER {
    LPSTR            pszObjId;
    CRYPT_OBJID_BLOB Parameters;
} CRYPT_ALGORITHM_IDENTIFIER, *PCRYPT_ALGORITHM_IDENTIFIER;

重要的是要注意它是LPSTR不是LPWSTR。所以字符串需要编组为ANSI。除非明确指定,.NET 会将字符串编组为 unicode。所以我们对应的struct需要额外的修饰:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
struct AlgorithmIdentifier
{
    public string ObjectId;
    public CryptoBlob Parameters;
}

CharSet 添加到StructLayout 属性中将使.NET 以所需的编码编组字符串。然后就可以直接使用了:

var algId = new AlgorithmIdentifier
{
    ObjectId = "1.2.840.113549.1.1.5" // szOID_RSA_SHA1RSA
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-15
    • 1970-01-01
    • 1970-01-01
    • 2012-02-06
    • 1970-01-01
    • 2015-12-01
    相关资源
    最近更新 更多