Everyone should encrypt their emails … especially geeks, who can be expected to understand how little effort it would take for a rogue sysadmin or clever hacker to sniff your email on it’s way to it’s intended destination.

Incidentally, if you’re a geek and you don’t know that, you should try running WireShark while you download and send emails…

Anyway. The point of this email is to point out that Comodo (one of the biggest SSL Certificate vendors, and one who’s trust certificates are pre-installed on Windows) is giving away free secure email certificates which you can use in Outlook, Thunderbird, or whatever your favorite email client is. They’re actually on the recommendation list from Microsoft, but inexplicably listed under “other” office versions (they work fine in Outlook 2007, just to be clear).

All you need to do now is run off and sign up and then tell all your friends and family to do the same thing.

The cool thing about the way authenticode signatures are implemented is that even if a script is signed with a self-issued certificate, you can still tell if the script has been tampered with… Check this out:

[1]:ls SCRIPTS:\UnknownCert\Sample*.ps1,SCRIPTS:\TrustedCert\Sample*.ps1 | gas

Directory: SCRIPTS:\UnknownCert\

SignerCertificate Status Path
————————- ——— ——
0DA3A2A2189CD74AE371E6C57504FEB9A59BB22E UnknownError Sample.ps1
0DA3A2A2189CD74AE371E6C57504FEB9A59BB22E HashMismatch SampleBAD.ps1

Directory: SCRIPTS:\TrustedCert\

SignerCertificate Status Path
————————- ——— ——
B658C20AAD070B9FF105C69BBC47ADCF56FD5576 Valid Sample.ps1
B658C20AAD070B9FF105C69BBC47ADCF56FD5576 HashMismatch SampleBAD.ps1

As you can see, in the case of a UNTRUSTED, but correct, signature, you get the UnknownError status. If you checked the output object, it has a StatusMessage which says “A certificate chain could not be built to a trusted root authority”. If the script has been altered (as in my SampleBAD.ps1 scripts) then the signature is incorrect, you get the HashMismatch status, and the corresponding StatusMessage is: “The contents of file SCRIPTS:\TrustedCert\SampleBAD.ps1 may have been tampered because the hash of the file does not match the hash stored in the digital signature. The script will not execute on the system…”

One odd thing is that the messages are inaccurate about not executing the script: if you have your execution policy set to Unrestricted, the signatures aren’t checked at all, and if you have it set to RemoteSigned they are only checked for remote scripts. Furthermore: if you do have your execution policy set to AllSigned, neither the UnknownError nor the HashMismatch script will execute — only the one Valid scripts will.

So what?

The bottom line is: you can verify that nothing has happened to the script — even if you don’t trust the person who signed it nor the person, group, or company that issued a certificate to them. Why does this matter? Well, I recently wrote a post about generating self-signed code-signing certificates which can be used for signing PowerShell scripts, and if you chose to distribute scripts signed with one of those certificates, nobody would be able to verify the root CA(Certificate Authority) and so the signatures would never come out as valid.

Is there any usefulness in this? Well, I guess that depends on your perspective, but basically, I think that if I published my scripts signed and tell you on my blog what my certificate thumbprint is … that you’d be more able to trust those scripts than you are now (when they’re not signed at all). Of course, I could go one step further, and publish my own self-signed root CA certificate so you could choose to trust that …

I was recently having a conversation about the future of the PowerShell Script Repository and it involved some discussion of whether it would be safe to use the Repository Scripts to download dependencies automatically… The answer, obviously, is no.

But it started me thinking again about scripts being signed. If you had already chosen to run a script provided by me (which was signed by a certificate you couldn’t verify), maybe you’d be willing to trust other scripts signed by the same certificate, so we could automatically download them. Well, maybe even then you wouldn’t want to trust it, but lets assume that you were running a copy of the PowerShell Script Repository internally at your company …

Would you use automatic dependency downloading?

We could easily have a function that takes the script name and verifies that you have that script available — and if not, it could fetch the script from your designated repository and verify that the signature is valid even if the certificate isn’t signed by a root certificate authority you trust.

Of course, such automatically downloaded scripts would need to be marked as “Remote” so if you had your Execution Policy set to AllSigned or Remote Signed, then the script would only run if you had trusted it’s author (and you wouldn’t even be offered the option if you hadn’t trusted the CA(Certificate Authority) that issued his script. In that case you would need to review the script and re-sign it yourself — or manually remove the “remote” bit.

Imagine something like this:


# Get-Paste.ps1
function Get-Paste {
   Resolve-Dependency Get-Webfile
   # lots of code here that uses the Get-Webfile function ...
   Get-Webfile http://HuddledMasses.org/
}
 

When you tried to execute Get-Paste, it would check for Get-Webfile, and if it couldn’t find it, would attempt to download it (presumably this would involve asking your permission, and placing it in some specific location that was in your PATH, so that the script could find it when it tried to execute it on the next line).

Or maybe, an Apt-Get?

Perhaps instead of this mechanism, we could use the new embeddable “Data Language” to provide a list of dependencies, like: DATA Dependencies { scripts = Get-WebFile } and run a Resolve-Dependencies function against each script before trying to execute it — this way, if you downloaded a script from the repository using Get-Paste, it could automatically Resolve-Dependencies and offer to download the other scripts at the same time.

The fact is that doing this correctly will require some major reworking of the script repository to allow tracking new versions of scripts better, and to let the script repository track dependencies explicitly so that you don’t have to download the whole script to find out what it’s dependencies are, but this could be done, if people are actually interested in it.

A web of trust?

Ad I’m thinking about this, I’m wondering again about the possibility of creating an informal web-of-trust style code-signing certificate tree. The idea would be that the Script Repository would have a CA certificate of it’s own, and would issue code-signing certificates to PowerShell developers cheaply (free?) by skipping over some of the usual verification steps. In an ideal world, Microsoft would issue the PowerShell Community a “SubCA” certificate signed by their root — in the interests of promoting code signing for PowerShell …

However, if we couldn’t get a SubCA certificate for “free” or cheap, we could simply generate and self-sign our own, and publish it on the Script Repository website, requiring users to download and import it into their trusted roots if they wanted to use trust permissions. Regardless of whether they chose to trust it or not, they could still verify the scripts were valid, which is better than what we have now — the rest would be up to the user.

Of course, if we were issuing certificates that were self-signed anyway, we could go a step further and sign SubCAs and distribute them to, say, the Microsoft PowerShell MVPs and trusted community leaders after verifying email addresses and physical mailing addresses etc … trusting them further to issue (less trusted) code-signing certificates to additional developers.

Call to action

All of this is extra work for the people maintaining the script repository web site (right now, that’s me), but it might be worth it if it makes it easier to use the script repository, easier to trust the scripts on it, and easier to verify that an author is who he says he is … what do you think?

  1. Should we put in the work to set up a web of trust or should we leave it up to individual developers to self-sign and generate their certificates (and publish their public roots on their websites or something)?
  2. Should we just leave it at that (scripters can sign their scripts if they feel like it), or should we push and promote script signing? As an incomplete example of promoting code-signing, I mean:
    1. We can use certificates as the primary (or only) way for authors to identify themselves (that is: no log-ins, unsigned scripts are marked “anonymous” ... but we track the thumbprints and allow you to browse scripts signed by the same author, etc).
    2. We can include the signature thumbprint with the short descriptions output on the search results and from the scripts which interact with repository.
    3. We can restrict “latest version” updates to only scripts which are signed, and optionally to new versions signed by the same certificate.
  3. Is there any point (or hope) in trying to get a signed CA certificate? Can Microsoft help us out? Do any of you work at a certificate authority?