Digitally Signing Scripts
A signed script includes a digital signature as a block comment within the file. You need to be using the WSH 5.6 or later XML format, because it contains a specific element for storing the certificate. Take Listing 28.1 as an example.
Script Signer
This script signs another script for you. Just run it with the appropriate command-line parameters shown, or run it with no parameters to receive help on the correct usage.
Listing 28.1. Signer.vbs. This script signs another one.
<job>
<runtime>
<named name="file" helpstring="The script file to sign"
required="true" type="string" />
<named name="cert" helpstring="The certificate name"
Required="true" type="string" />
<named name="store" helpstring="The certificate store"
Required="false" type="string" />
</runtime>
<script language="vbscript">
Dim Signer, File, Cert, Store
If Not WScript.Arguments.Named.Exists("cert") Or _
Not WScript.Arguments.Named.Exists("file") Then
WScript.Arguments.ShowUsage()
WScript.Quit
End If
Set Signer = CreateObject("Scripting.Signer")
File = WScript.Arguments.Named("file")
Cert = WScript.Arguments.Named("cert")
If WScript.Arguments.Named.Exists("store") Then
Store = WScript.Arguments.Named("store")
Else
Store " "
End If
Signer.SignFile(File, Cert, Store)
</script>
</job>
Script Signer-Explained
This script is stored in an XML format, which describes its command-line parameters. That's what the first block of XML does.
<job>
<runtime>
<named name="file" helpstring="The script file to sign"
required="true" type="string" />
<named name="cert" helpstring="The certificate name"
Required="true" type="string" />
<named name="store" helpstring="The certificate store"
Required="false" type="string" />
</runtime>
Then, the actual script begins. It checks first to see that both the "cert" and "file" command-line arguments were provided; if they weren't, the script displays the help information and exits.
<script language="vbscript">
Dim Signer, File, Cert, Store
If Not WScript.Arguments.Named.Exists("cert") Or _
Not WScript.Arguments.Named.Exists("file") Then
WScript.Arguments.ShowUsage()
WScript.Quit
End If
Assuming everything was provided, the script creates a new Scripting.Signer object and passes it the file and certificate command-line arguments.
Set Signer = CreateObject("Scripting.Signer")
File = WScript.Arguments.Named("file")
Cert = WScript.Arguments.Named("cert")
If a specific certificate store is specified, that's passed to the Signer objects, too.
If WScript.Arguments.Named.Exists("store") Then
Store = WScript.Arguments.Named("store")
Else
Store " "
End If
Finally, the Signer's SignFile method is called to actually sign the target script file. The file is opened, and its signature is written to a comment block.
Signer.SignFile(File, Cert, Store)
</script>
</job>
Note that anyone can get into the file and modify its signature. However, the signature no longer matches the script, and it cannot pass the trust test conducted by WSH. Similarly, any changes to the script's code, after it is signed, fail the trust test.
|