我已成功修改this code以便在XML文件上签名并验证签名。但是我在没有安装证书的计算机上验证签名时遇到麻烦。我发现this是在C#中进行此操作的Microsoft参考,但这似乎也需要安装Cert。还是“密钥容器”只是使用同一证书签名的可执行文件?因为我的C#技能很弱,所以有人可以使用PowerShell而不是C#指向我的资源吗! 似乎无需安装证书即可验证XML上的签名。手指交叉。
答案 0 :(得分:1)
然后在未安装证书的计算机上验证签名时遇到麻烦。
这很有道理!
公钥签名验证的基础是……好吧,用于签名的任何密钥的公钥部分-证书是认证和分发公钥的一种超通用方式!
因此,您要么需要公开提供证书(没有私钥),要么将公钥材料导出并发送到签名的文档旁边。
我们可以更新Sign-XML
例程,将证书本身复制到xml文档中的签名blob中,如下所示:
function Sign-XML {
param(
[xml]$xml,
[System.Security.Cryptography.X509Certificates.X509Certificate2]$certificate
)
[System.Security.Cryptography.xml.SignedXml]$signedXml = $NULL
$signedXml = New-Object System.Security.Cryptography.Xml.SignedXml -ArgumentList $xml
# Grab the PrivateKey from the cert - fail if not present
if(-not $certificate.HasPrivateKey){
throw 'Private Key not passed to Sign-XML, cannot sign document'
return
}
$signedXml.SigningKey = $certificate.PrivateKey
# Add a KeyInfo blob to the SignedXml element
# KeyInfo blob will hold the certificate and therefore the public key
$keyInfo = New-Object System.Security.Cryptography.Xml.KeyInfo
$keyInfo.AddClause((New-Object System.Security.Cryptography.Xml.KeyInfoX509Data -ArgumentList $certificate))
$signedXml.KeyInfo = $keyInfo
$Reference = New-Object System.Security.Cryptography.Xml.Reference
$Reference.Uri = ""
$env = New-Object System.Security.Cryptography.Xml.XmlDsigEnvelopedSignatureTransform
$Reference.AddTransform($env);
$signedXml.AddReference($Reference)
$signedXml.ComputeSignature()
[System.Xml.XmlElement]$xmlSignature = $signedXml.GetXml()
#Add signature to end of xml file
[void]$xml.DocumentElement.AppendChild($xml.ImportNode($xmlSignature, $true))
if ($xml.FirstChild -is [system.xml.XmlDeclaration]) {
[void]$xml.RemoveChild($xml.FirstChild);
}
$xml
}
这里要注意的两件事:
X509Certificate2
对象,而不是原始密钥容器KeyInfoX509Data
子句现在,证书是已签名文档的一部分,收件人可以轻松地以编程方式验证签名和公钥:
function Verify-XmlSignature {
Param (
[xml]$checkxml,
[switch]$Force
)
# Grab signing certificate from document
$rawCertBase64 = $signed.DocumentElement.Signature.KeyInfo.X509Data.X509Certificate
if(-not $rawCertBase64){
throw 'Unable to locate signing certificate in signed document'
return
}
$rawCert = [convert]::FromBase64String($rawCertBase64)
$signingCertificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList @(,$rawCert)
[System.Security.Cryptography.Xml.SignedXml]$signedXml = New-Object System.Security.Cryptography.Xml.SignedXml -ArgumentList $checkxml
$XmlNodeList = $checkxml.GetElementsByTagName("Signature")
$signedXml.LoadXml([System.Xml.XmlElement] ($XmlNodeList[0]))
return $signedXml.CheckSignature($signingCertificate, $Force)
}
将$Force
传递给CheckSignature()
的第二个参数意味着,如果用户指定-Force