Jean-Yves Moschetto's blog

Tip and tricks on Microsoft products

NAVIGATION - SEARCH

How to sign XML file with PowerShell

      Hi,

It often happened in my developments to have to protect my sources, and be sure that the configuration XML file I used, was not modified by some people.

For that, the idea if to sign my configuration XML file, and later the program which has to read the file to first check XML signature.

Of course, you first need a "Code Signing" certificate

Param ([string]$CommandLine)
[void][reflection.assembly]::Load('System.Security, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')
function Sign-XML
{
 Param ( [xml]$xml, [system.Security.Cryptography.RSA]$rsaKey )
 
 [System.Security.Cryptography.xml.SignedXml]$signedXml = $NULL
 $signedXml = New-Object System.Security.Cryptography.Xml.SignedXml -ArgumentList $xml
 $signedXml.SigningKey = $rsaKey
 
 $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]$xmlSignatur = $signedXml.GetXml()
 #Add signature to end of xml file
 $xml.DocumentElement.AppendChild($xml.ImportNode($xmlSignatur, $true))
 
 if ($xml.FirstChild -is [system.xml.XmlDeclaration])
 {
  $xml.RemoveChild($xml.FirstChild);
 }
 $xml
}
function Verify-XmlSignature
{
 Param (
  [xml]$checkxml,
  [system.Security.Cryptography.RSA]$Key
 )
 
 [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]))
 $check = $signedXml.CheckSignature($key)
 return $check
}
$SignerSubject = 'E=jeanyves.moschetto@yoursystems.eu, CN=Jean-Yves Moschetto, OU=Carib Infra, O=YourSystems, L=LILLE, S=NORD, C=FR'
$SigningCert = Get-ChildItem -Path cert:\CurrentUser\My -CodeSigningCert | Where-Object { $_.Subject -eq "$SignerSubject" }

$Source = [System.IO.FileInfo]$CommandLine
$Destination = "$($Source.DirectoryName)\$($Source.BaseName).signed$($Source.Extension)"
#DO ENCRYPT FILE HERE
[xml]$XMLsource = Get-content -Path $Source.FullName
Sign-XML -xml $XMLsource -rsaKey $SigningCert.PrivateKey
$XMLsource.Save($Destination)

#DO TEST DECRYPT FILE HERE - Function to be taken in program for which to protect xml
[xml]$XMLdestination = Get-content -Path $Destination 
$Result = Verify-XmlSignature -checkxml $XMLdestination -Key $SigningCert.PublicKey.Key

This is beyond the result of a signed XML file. We can clearly see the added section "Signature"

<config>
 <authorizedDomains>dom2016.local</authorizedDomains>
  <myXmlToProtect> .../... </myXmlToProtect>
 <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
  <SignedInfo>
   <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
   <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
   <Reference URI="">
    <Transforms>
     <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
    </Transforms>
    <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
    <DigestValue>p8RycsG2slzKpRT3csRiWGGraLo=</DigestValue>
   </Reference>
  </SignedInfo>
  <SignatureValue>L6vbZ6U6amSeAKV0EmjmBbon68nS9IEmipKtS7bYL+IwRfsZcQvAlkKlfLSJd0CnxEyrU5abmFEuFw4sViENXNEKJj04/Ra3yF8QnJgwfC9aerkq9dFMNbfS68Iztexcvy1wQYw7uIDSiQoP7oPI2WbTfIljGLyX5UnMc7kh/pzFtFS6tV60MlRwPLTBF6p5b42ymCs8VmwPxpClcA2jFklRleHdHK7hnntmVHH/ie0hFz76SA9lUGmJ0i1UeegzPuGHEJXQ8DPn2FMY5UDKAydfTSWiOanobJdMfbB6KZibVFst69DoXRBsvLFgTg/yBsgCT3p9XuIPaM45u818rg==</SignatureValue>
 </Signature>
</config>

Add comment