在签名 XML 上验证签名
Validate signature on signed XML
我已成功修改 this code to sign and validate the signature on an XML file. But I am having trouble then validating the signature on a machine that doesn't have the cert installed. I found this Microsoft 参考以在 C# 中执行此操作,但这似乎还需要安装证书。或者 "Key Container" 只是一个用相同证书签名的可执行文件?有人可以使用 PowerShell 而不是 C# 为我指点资源吗,因为我的 C# 技能很弱!
似乎可以在 XML 上验证签名而无需安装证书。手指交叉。
I am having trouble then validating the signature on a machine that doesn't have the cert installed.
有道理!
public 密钥签名验证的基础是......好吧,public 密钥 部分用于签署某些东西 - 和证书是一种非常常见的验证和分发 public 密钥的方式!
因此,您要么需要 public 使证书(没有私钥)可用,要么将 public 密钥 material 与签名文档一起导出并发送。
我们可以更新 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
}
这里有 2 点需要注意:
- 第二个参数现在采用
X509Certificate2
对象而不是原始密钥容器
- 我们在包含证书的文档中的签名信息中添加了一个
KeyInfoX509Data
子句
现在证书是签名文档的一部分,收件人可以轻松地以编程方式验证签名和 public 密钥:
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
[,则对证书本身的信任验证不会影响验证例程的结果=19=]
我已成功修改 this code to sign and validate the signature on an XML file. But I am having trouble then validating the signature on a machine that doesn't have the cert installed. I found this Microsoft 参考以在 C# 中执行此操作,但这似乎还需要安装证书。或者 "Key Container" 只是一个用相同证书签名的可执行文件?有人可以使用 PowerShell 而不是 C# 为我指点资源吗,因为我的 C# 技能很弱! 似乎可以在 XML 上验证签名而无需安装证书。手指交叉。
I am having trouble then validating the signature on a machine that doesn't have the cert installed.
有道理!
public 密钥签名验证的基础是......好吧,public 密钥 部分用于签署某些东西 - 和证书是一种非常常见的验证和分发 public 密钥的方式!
因此,您要么需要 public 使证书(没有私钥)可用,要么将 public 密钥 material 与签名文档一起导出并发送。
我们可以更新 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
}
这里有 2 点需要注意:
- 第二个参数现在采用
X509Certificate2
对象而不是原始密钥容器 - 我们在包含证书的文档中的签名信息中添加了一个
KeyInfoX509Data
子句
现在证书是签名文档的一部分,收件人可以轻松地以编程方式验证签名和 public 密钥:
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
[,则对证书本身的信任验证不会影响验证例程的结果=19=]