Huddled Masses
The internet home of Joel "Jaykul" Bennett...
Browse: Home / PowerShell Script Repository and Code Signing

PowerShell Script Repository and Code Signing

By Joel 'Jaykul' Bennett on 03-Jul-2008

There’s been a lot of discussion on the #PowerShell IRC channel about code signing lately — mostly in response to my earlier posts (which I won’t link to here, because I should probably retract some of it after the discussions we’ve had). The discussion mostly revolves around how code signing applies to the PowerShell script repository and users’ ability to trust scripts that they download.

In order to keep the conversation going, and hopefully, include some of the Microsoft MVPs and PowerShell developers that don’t participate in the IRC channel at all, I’m going to post a summary of the conclusions we’ve drawn so far, and then outline a proposal for the repository.

In case you don’t know, PowerShell implements code-signing for scripts using x509 Certificates (basically, SSL certs with “Extended” use properties), but the signatures are just embedded in the script as a comment, much like PGP signatures in email. Depending on your settings, the engine will actually check the signature on a script before executing it, and refuse to execute it if the signature isn’t valid, for instance, if the script has been modified, or the certificate used to sign it can’t be traced to a trusted Certificate Authority.

PowerShell code-signing is inconvenient, and expensive. Scripts are only Valid if they are signed, unmodified, and the certificate traces back to a CA(Certificate Authority) that is in your Trusted Roots store (by default, basically, Microsoft’s, VeriSign, Thawte, and Comodo).

You can create your own “test” certificate (that is, one that you sign yourself), but scripts signed by that certificate will only work on that computer. This system works fine for large companies which typically have either a subscription for purchasing certificates, or their own in-house trusted CA, but not for small private developers or open source script sharing communities without financial motivation.

Because of this, to take advantage of PowerShell’s code-signing on your computer (that is, to set your ExecutionPolicy to “AllSigned” or “RemoteSigned”) you must do one of these things:

  1. Make sure that all script authors rent and use code-signing certs which cost more than $150 a year.
  2. Add a non-commercial root CA certificate (like CACert) to (all of) your computer(s), and offer your authors the option of going through the process of getting one of those instead.
  3. Create a “community” CA … and try to figure out how to make sure the certificate is secure enough to convince people to use it (yeah, ok, this was partly my idea, and it’s really a bad idea).
  1. Generate your own code-signing certificate (which can be self-signed) and just sign every script that you trust.

So far, it seems like that last option is the only one that’s going to fly, because although some developers are willing to buy certificates to sign software they’re going to sell … most scripters and sys-admins aren’t willing to buy one to share their certificates for free.

So. Here’s the base fact:

The PowerShell Code repository is a repository of user-provided code.

We can’t actually afford to audit all of the code that users submit, nor take responsibility for verifying the identity of every contributor, but we’d like to have a way to do so. The best way would be to give everyone a free CodeSigning certificate from Microsoft or one of the established CAs, but we can’t afford to do that, so here’s our proposal (although it may sound like it, none of this is written yet, I’m just trying to get some feedback on the ideas):

Rather than rely strictly on user login authentication, we will require that all (non anonymous) submissions be SIGNED, and the signing certificate (key) will be the user authentication mechanism. Essentially, any unsigned code will show up as written by “anonymous” ... and any signed code will show up with the identity from the signing certificate — the certificate must include an email address, and the first post by each key will be held back until the email address can be authenticated.

In addition to the author’s signature on a script, other users who have used the code (or read through it without finding any issues), can also sign it as a show of trust — they simply submit the exact same script as a modification, but with their signature in place of the author’s.

So users will sign scripts to say they trust them, and when you browse or search the repository, you’ll see a lists of the users who have signed each code-snippet. You can download a copy of the code with any of the signatures and verify the signature yourself…

Additionally, there will be a Get-PoshCode cmdlet which probably should:

  • Mark the downloaded scripts as ‘remote’.
  • Add the download permalink url in a comment upon download (to aid in discovering other signatures and in adding your signature).
  • Handle a cache of “trusted” key/certs and choose a trusted author (if there is one) from multiple available downloads, and ask you if you want to add any of the signers to your trusted list — particularly if there isn’t already a trusted signature available for the script.
  • Validate the signature(s) after download, and provide a report (eg: valid/invalid).
  • Offer to replace the signature (with yours) if it’s not a trusted x509 authenticode signature.

What certificate system should we use?

You may have assumed that we’re planning on using Microsoft’s code signing which is built into PowerShell, but when we were discussing this in the IRC channel, one of the things that kept coming up is that one way or another, we’re essentially creating an alternative way for people to “trust” the certificate — since we’re assuming that most of these certificates will be self-signed.

That is, if we use x509, we’ll STILL be creating an alternate way for people to say that they trust the x509 certs, and thus, using them in a way they weren’t intended. If we use PGP, we’ll basically be using them as intended, and will have peer key-signing as a trust mechanism, but we’re STILL introducing a secondary way for users to establish trust for PowerShell scripts which doesn’t integrate with the engine’s policy settings, thus making things more complicated.

Let me sum up the positive and negative sides of what I see as our two options.

x509 (aka “Authenticode”) signatures — supported by Microsoft.

  • Probably self-signed and therefore won’t “work” properly in PowerShell anyway.
  • Some of them would probably be commercial certificates issued by trusted CAs like Thawte or Comodo, giving you instant trust in the identity of the author. In that case, they would additionally be:
  • Verifiable by PowerShell natively, and therefore, they:
  • Don’t require a separate signature in order to execute when the ExecutePolicy is set to AllSigned.

PGP signatures (supported by the Open Source community and used in Debian, etc)

  • Just as (un)trustworthy as any other self-signed certificate ... except that:
  • PGP certificates (keys) are inherently user-signable. The community can vouch for each other’s identities, and create a web-of-trust for authentication purposes (which is all x509 really accomplishes anyway — you trust that Verisign makes sure that they are who they say they are, and live where they say they live).
  • Not inherently usable by PowerShell.
  • AllSigned mode requires re-signing (probably with a self-signed cert). This also means that if you have an x509 authenticode-signed script to submit, we would still need you to re-sign it with a PGP certificate when you wanted to upload it.

Final thoughts

Of course, there’s a lot of outstanding issues with this idea. But I wanted to put it out there for some broader feedback, particularly because we really are thinking about using PGP certificates since they can be counter-signed by other users, and since the general consensus opinion is that actually expecting scripters to buy code-signing certificates is just out of the question.

So the first question is, can we do PGP signing in pure .Net for a cmdlet (maybe using bouncy castle), and can we easily create a Set-PGPSignature cmdlet?

Has there been any progress on a way to do PGP signing that’s compatible with XML files (eg: ps1xml files)?

Can we do signature checking in-memory, so we can download the script with many signatures embedded and stitch them together for verification without creating multiple temporary files?

Regardless, if you trust a signature, but the signature isn’t Authenticode (PGP) or isn’t Valid (self-issued), the PowerShell security measures will require you (the end user) to sign the script in order to allow it to execute — essentially, every signed script on your system will be signed by you (or your sysadmin) and so, signing essentially becomes the administrator’s equivalent of blessing a script, and is somewhat like setting the eXecute flag on a linux script — except that you have to re-set it every time you edit the script.

We need to make signing slightly easier.

It’s a pain to find your certificate, and the built-in AuthenticodeSignature cmdlets are horrible at parsing parameters.

We need to make generating these self-signing certs trivial for non-SDK machines

It’s really pretty easy with MakeCert, but that’s not redistributable, and the Windows SDK is a ridiculously large download for someone who just wants to sign their scripts. I’ve written a script to generate code-signing certs using OpenSSL, which is redistributable, but it’s still not great.

Similar Posts:

  • The problem with calling legacy/native apps from PowerShell
  • PowerShell 3 – Finally on the DLR!
  • Working with multiple versions of PowerShell Modules
  • Parenthesis in PowerShell
  • Get-Command in PowerShell 3 (NOTE: CTP2 Bug causes module loading)

Posted in Huddled | Tagged CodeSigning, Cryptography, PowerShell, Trust

« Previous Next »

Lijit Search

Tags

.Net .Net 2008 Scripting Games Automation Bugs Design Development Funny Gadgets GeoShell GUI Huddled Masses Internet licensing Microsoft Modules My Software News Personal PInvoke Pipeline Politics PoshCode PoshConsole PowerBoots PowerShell PowerShell Functions PowerTips Rants Recommender Repository Scripting ShowUI Software Solutions Textile Tips User Group UserInterface WalkThrough WebHosting Windows 7 WordPress WPF Xml

About Huddled Masses

This is web site is dedicated to the musings of Joel Bennett (aka Jaykul) about technology, software, software development, the web, and the world.

Any resemblance of the views expressed and the views of my employer, my terminal, or the view out my window are purely coincidental. The resemblance between them and my own views is non-deterministic. The question of the existence of views in the absence of anyone to hold them is left as an exercise for the reader.

P.S.: I occasionally link to things I think are great. When I do, I occasionally find a "referral code" so I can make a little cash. I promise that I don't link to anything just because of that cash (I wouldn't cross the street for the amount of cash those links bring in, never mind write a whole blog post) ... but I do not promise that things I link to will stay great as time passes, nor that you will agree with me about their greatness!

Archives

  • April 2012
  • February 2012
  • January 2012
  • October 2011
  • August 2011
  • July 2011
  • June 2011
  • March 2011
  • February 2011
  • January 2011

Copyright © 2012 Joel Bennett.

Powered by WordPress and Hybrid.