【问题标题】:Signature verification on CSR always returns false (even if signature is valid)CSR 上的签名验证始终返回 false(即使签名有效)
【发布时间】:2017-01-22 12:02:04
【问题描述】:

有人可以帮我解决以下问题吗:)

这篇文章与我在以下 URL 创建的初始帖子有关

Checking the signature of a CSR (X.509 certificate signing request)

但是,我想将这篇文章分开,因为我正在尝试另一种方法。

“目标”是“验证”CSR(PKCS#10 base64 格式的 X509 证书签名请求是否具有有效签名),这意味着从 CSR 获取公钥并验证签名是否正常(例如检查摘要使用证书中保存的公钥解密签名后匹配,而不仅仅是检查哈希是否格式正确)

最初我认为我可以简单地使用 X509enrollment.CX509CertificateRequestPkcs10 COM 对象的 ChecjSignature 方法(请参阅我在上述 URL 上的初始帖子)

然而,我最初帖子的贡献者指出,即使 CSR 未签名或包含不属于签名的公钥,我使用的方法(特别是用于 SHA1 签名验证)也会通过。换句话说,它只是确认摘要(哈希)而不是签名有效。

我应该指出我不是开发人员,但我可以使用 PowerShell 并了解 C# 的概念,因此我进行了一些挖掘,试图找到一个合适的 TYPE,它有一个方法可以用来验证 CSR 上的签名,(因为我找不到贡献者在我的原始帖子中提到的 KeySignature 方法)

因此,经过一番挖掘,我编写了以下 PowerShell 代码,但当我知道 CSR 有效且已签名 SHA1 时总是返回 FALSE

<# contents of CSR file 
-----BEGIN NEW CERTIFICATE REQUEST-----
MIID9zCCAt8CAQAwHTEbMBkGA1UEAwwSd3d3MDEuZmFicmlrYW0uY29tMIIBIjAN
BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlQdqVHQgzd1uJ9MFb935Vfyg1Y1m
ZXn4OMwJudOhEzx7m1+4C8lDOXn5hglHG0FFad+KkLok/GcAzdc2iwBOholJ2MYP
XCnfkJLYXHLRj+CKRvhCHWJOXkQQQ0apdXh1MhiDBD/BIKqmMm54XLFhZqjQiNeI
VHFb9GS06Ps/xuOWzqY54xSM/047nzYNU50FrTHuBCiqtJtHpKtdrCWyhWi7was0
noCx/XGm6g8nVnzPTQCSeAPp6mSt4kSMtdoVZYg1n5pmMW+QYAero/UWrbNp1Wlk
pUH4s96H6pUrbF7RIkXpCwWocxBHAXVcMst2HYvwstAETxvqeKTOvVEEAQIDAQAB
oIIBkzAcBgorBgEEAYI3DQIDMQ4WDDEwLjAuMTQzOTMuMjBCBgkrBgEEAYI3FRQx
NTAzAgEJDA9ERVNLVE9QLU41OEkzMzEMFERFU0tUT1AtTjU4STMzMVx1c2VyDAdj
ZXJ0cmVxMHIGCisGAQQBgjcNAgIxZDBiAgEBHloATQBpAGMAcgBvAHMAbwBmAHQA
IABSAFMAQQAgAFMAQwBoAGEAbgBuAGUAbAAgAEMAcgB5AHAAdABvAGcAcgBhAHAA
aABpAGMAIABQAHIAbwB2AGkAZABlAHIDAQAwgboGCSqGSIb3DQEJDjGBrDCBqTAO
BgNVHQ8BAf8EBAMCBaAweAYJKoZIhvcNAQkPBGswaTAOBggqhkiG9w0DAgICAIAw
DgYIKoZIhvcNAwQCAgCAMAsGCWCGSAFlAwQBKjALBglghkgBZQMEAS0wCwYJYIZI
AWUDBAECMAsGCWCGSAFlAwQBBTAHBgUrDgMCBzAKBggqhkiG9w0DBzAdBgNVHQ4E
FgQUBMisP2saqKPzBdEj1TyUC4jQR78wDQYJKoZIhvcNAQEFBQADggEBADCBGPbL
mGx89pgELT/wwZmdDuN3ci+3oaA1wfUHgqVmIXLbadnx41Z1j/30tZKxO7YE86b6
Sx7jXFusiH+sAseAqWkgF00vJ2RDNaTE8iDn/cQlxELtUxYn75F7jVmWMgUgAIH6
CLjf34ssNp+9tywKl1/72QC0ixaL4qoaJaLF2ezPB/UZ3rVV5FHsonAnd5oDiKwz
lws0e3zf3EZpcd2FzgxTqhYAEYFdvCBHvjSCvHg0x7L1e2J3pPRMKv6nSN9wfvxM
UC72lcn9skWOrnpCt24vn1E3BI16QWD27xZpx4z+LfbJwKGkf987vIcIipRZCAco
dcvCmbzEjf1/xso=
-----END NEW CERTIFICATE REQUEST-----
#>

#get contents of CSR file as a Base64 String (e.g. the -raw parameter returns string rather than array)
$CSR = Get-Content c:\TEMP\csr.txt -raw

#create an instance of the X509enrollment.CX509CertificateRequestPkcs10 class COM object
$RequestComObj = New-Object -ComObject X509enrollment.CX509CertificateRequestPkcs10 

#decode the CSR (returns COM object)
$RequestComObj.InitializeDecode($CSR,6)

#get public key from CSR COM object (returns Base64 string)
$PublicKey = $RequestComObj.PublicKey.EncodedKey()

#get public key from CSR COM object (returns Base64 string)
$Signature = $RequestComObj.Signature()

#convert CSR Base64 string to Byte array
$CSRBytes = [Byte[]][Char[]]$CSR

#convert PublicKey Base64 string to Byte Array
$PublicKeyBytes = [Byte[]][Char[]]$PublicKey

#convert Singature Base64 string to Byte Array 
$SignatureBytes = [Byte[]][Char[]]$Signature

#create an instance of the System.Security.Cryptography.RSACryptoServiceProvider class
$RSACryptoServiceProvider = [System.Security.Cryptography.RSACryptoServiceProvider]::Create()

$RSACryptoServiceProvider
#get the OID for the SHA1 algirithm 
$SHA1_OID = [System.Security.Cryptography.CryptoConfig]::MapNameToOID('SHA1')

#attempt to verify signature of CSR
$RSACryptoServiceProvider.VerifyData($CSRBytes,$SHA1_OID,$SignatureBytes)

阅读关于 System.Security.Cryptography.RSACryptoServiceProvider TYPE 的 MSDN 文章,其中指出 VerifyData 方法用于验证使用 SignData 签名的数据 方法,因此,我认为我的代码总是返回 FALSE 的原因可能是因为 CSR 没有在第一个实例中使用此 SignData 方法进行签名,而是使用其他一些方法。

因此,有人可以帮助我,并告诉我如何验证 CSR 上的签名是否有效,例如使用 CSR 中的公钥检查签名是否有效(例如用公钥解密签名,并比较哈希)

提前谢谢大家 __AUser

【问题讨论】:

    标签: signature pki verify


    【解决方案1】:

    我不想评论您在代码中所做的所有事情,因为这是错误的,根本没有必要。 IX509CertificateRequestPkcs10 接口包含您应该使用的CheckSignature。所以,你的整个代码是四行代码:

    #get contents of CSR file as a Base64 String (e.g. the -raw parameter returns string rather than array)
    $CSR = Get-Content c:\TEMP\csr.txt -raw
    
    #create an instance of the X509enrollment.CX509CertificateRequestPkcs10 class COM object
    $RequestComObj = New-Object -ComObject X509enrollment.CX509CertificateRequestPkcs10 
    #decode the CSR (returns COM object)
    $RequestComObj.InitializeDecode($CSR,6)
    
    #validate signature
    $signatureIsValid = $false
    try {
        $RequestComObj.CheckSignature(0x1)
        $signatureIsValid = $true
    } catch { }
    

    $signatureIsValid 将保持签名有效性状态。

    【讨论】:

    • 您好 Crypt32,非常感谢您抽出宝贵时间回复
    • 对不起,我想补充一下,最初我使用的是 CheckSignature 方法,但我在上一篇文章中被告知:stackoverflow.com/questions/41765074/… 这不一定会检查签名,因为它允许 Null,因此只是一个哈希而不是一个签名的哈希也将作为有效的传递,因此我正在寻找一个替代方案(我可能误解了)来回复我以前的帖子。你能帮我澄清一下吗?再次感谢
    • 如果您有一个未签名的 CSR 并且您尝试使用 $RequestComObj.InitializeDecode($CSR,6) 进行解码,实际上考虑它(尚未尝试过)我认为它会失败解码为它没有被签名并且 CSR 应该被签名,如果是这种情况,那么回复 CheckSignature(0x1) 是可以的。无论如何我离题再次感谢您的帮助:)
    • $RequestComObj.InitializeDecode($CSR,6) 将解码签名和未签名的请求。当您将0x1 标志传递给CheckSignature 时,如果签名无效或为空签名,它将抛出异常。
    猜你喜欢
    • 2019-11-28
    • 1970-01-01
    • 1970-01-01
    • 2019-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-17
    相关资源
    最近更新 更多