We recently started to sign every ORF PE binaries digitally—you know, trust, integrity and all. For signing the files, we use Microsoft’s signcode that offers a command-line interface for Authenticode signing. All we need is to pass the .SPC file (Software Publisher Certificate), the .PVK file (Private Key), the binary file and maybe the public timestamp service URL of Verisign. It is quite simple:
signcode -v spc mycert.spc -v mycert.pvk -t http://timestamp.verisign.com/scripts/timstamp.dll mybinary.exe
Alas, it quickly turned out that signcode does not play very nice with build scripts. The private key is password-protected and signcode does not support specifying the password as a parameter. Instead, it prompts for the password in a dialog every time a file is signed. Apparently, I am not the only one who think it is a problem.
The best solution I found on the Microsoft newsgroups is to find the password dialog window by its title and send the password as keyboard messages. I do not know what you say, but simulating user input makes me hiccup and also anything that pops up a dialog can hardly be called ‘unattended’.
By further research, now for an API, I found that Microsoft’s CAPICOM 2 can do the signing very easily and also allows specifying the private key password. It wants a .PFX (PKCS #12 certificate) file instead of an .SPC and .PVK, but Microsoft offers another utility call pvkimprt that can combine the .SPC and .PVK into a .PFX as:
pvkimprt -pfx mycert.spc mycert.pfk
This will invoke a wizard for making the .PFX export. Once you have the .PFX, you can continue with signing. The following JScript code snippet demonstrates using CAPICOM 2 for code signing:
var Signer = new ActiveXObject("CAPICOM.Signer");
Signer.Load("mycert.pfx", "mypassword");
var SignedCode = new ActiveXObject("CAPICOM.SignedCode");
SignedCode.FileName = 'filetosign.exe';
SignedCode.Description = 'Here Be Dragons';
SignedCode.Sign(Signer);
By adding the following line the above code, you can also timestamp the file.
SignedCode.Timestamp('http://timestamp.verisign.com/scripts/timstamp.dll');
And that’s all.
SECURITY WARNING: It is quite obvious that signcode lacks the password option for security reasons. Microsoft is absolutely right about private key security—your code signing certificate and password are worth a lot more than the few hundred bucks you paid for them, so you really want to store it securely. Hardcoding the password into a script is definitely not secure, but probably you could make use of the above when you have to sign a couple of files at once.