<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Huddled Masses &#187; Cryptography</title>
	<atom:link href="http://huddledmasses.org/tag/cryptography/feed/" rel="self" type="application/rss+xml" />
	<link>http://huddledmasses.org</link>
	<description>You can do more than breathe for free...</description>
	<lastBuildDate>Fri, 27 Apr 2012 05:42:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
<cloud domain='huddledmasses.org' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
		<item>
		<title>Signing PowerShell Scripts &#8211; Automatically</title>
		<link>http://huddledmasses.org/signing-powershell-scripts-automatically/</link>
		<comments>http://huddledmasses.org/signing-powershell-scripts-automatically/#comments</comments>
		<pubDate>Sun, 15 Nov 2009 05:53:56 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[Authenticode]]></category>
		<category><![CDATA[Code Signing]]></category>
		<category><![CDATA[Cryptography]]></category>
		<category><![CDATA[Digital signature]]></category>
		<category><![CDATA[FileSystemWatcher]]></category>
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://huddledmasses.org/?p=1317</guid>
		<description><![CDATA[I write a lot of PowerShell scripts, and I work on modules a lot, including ones which I load automatically in my profile. Sometimes I forget to sign those modules before I restart my console/host, and then I get errors when they&#8217;re loaded from the profile. I wrote a script to solve this problem by [...]]]></description>
			<content:encoded><![CDATA[	<p>I write a lot of PowerShell scripts, and I work on modules a lot, including ones which I load automatically in my profile.  Sometimes I forget to sign those modules before I restart my console/host, and then I get errors when they&#8217;re loaded from the profile.  I wrote a script to solve this problem by automatically signing files every time they&#8217;re edited, and I figured I&#8217;d share it below, but first let me try explaining what code signing is, and why you should care.</p>

	<h3>What is code signing?</h3>

	<p><a href="http://en.wikipedia.org/wiki/Code_signing">Code signing</a> is the process of digitally signing files to confirm the author and guarantee that the file has not been altered or corrupted.  It&#8217;s essentially the same as signing emails: it guarantees that they were actually authored by the person claiming to be the author, and that they weren&#8217;t changed after the author signed them. (For more information see <a href="http://developer.apple.com/mac/library/documentation/Security/Conceptual/CodeSigningGuide/AboutCS/AboutCS.html#//apple_ref/doc/uid/TP40005929-CH3-SW3">Apple&#8217;s explanation</a> and <a href="http://msdn.microsoft.com/en-us/library/ms537361%28VS.85%29.aspx">Microsoft&#8217;s</a>).</p>

	<h3>How does digital signing work?</h3>

	<p>Basically, digital signing is cryptography, so a full understanding of it really requires taking a 400-level college course, but <a href="http://www.instantssl.com/code-signing/code-signing-process.html">here are the basics</a>:  You take some data (binary bits) and use a well-known algorithm to calculate what is called a &#8220;hash&#8221; of the bits. This hash is mathematically-generated from the source data, and so it can be re-calculated by the receiver.  The hash is then &#8220;signed&#8221; via another algorithm: using a private key (see <a href="http://www.answers.com/topic/pki#Computer_Desktop_Encyclopedia_d_ans">Public Key Infrastructure</a> (<span class="caps">PKI</span>) for more about how these keys are managed) the signer encrypts the hash and attaches it to the file.  </p>

	<p>With public/private key encryption, data that is encrypted by the private key can be decrypted by the public key, so the encryption of the hash (and sometimes the public key, as well) is attached to the file so that the end user can re-calculate the hash and decrypt the signature to verify: a) that it was encrypted by the private key belonging to the author, and b) that the hash matches the hash that the author signed.</p>

	<h3>What&#8217;s all this about keys?</h3>

	<p>In <span class="caps">PKI</span>, the &#8220;key&#8221; is actually part of what&#8217;s called an <a href="http://en.wikipedia.org/wiki/Ssl_certificate"><span class="caps">SSL</span> certificate</a> issued to you by a Certificate Authority (CA) who verifies your identity. Verisign introduced the idea of &#8220;classes&#8221; for certificates, and you can now get free, <strong>Class 1</strong> certificates for email signing from most CA&#8217;s now (like <a href="http://www.thawte.com/secure-email/personal-email-certificates/">Thawte</a> and <a href="http://www.thawte.com/secure-email/personal-email-certificates/">Comodo</a> and <a href="http://www.startssl.com/?app=1">StartCOM</a>), where the only thing they <em>verify</em> is that the person being issued the certificate can send/receive email at that address.</p>

	<p>Of course, if you want to verify yourself as the author of <strong>code,</strong> we want to know more about you than your email address.   So to sign code, you need <em>at least</em> a <strong>Class 2</strong> certificate, for which proof of identity is required.  This typically comes in the form of providing (photos of) your passport, driver&#8217;s license and/or other photo ID to verify that you are who you claim to be, and answering a few questions on the phone to validate that you own the phone number provided&#8230; or providing tax or other documents to prove the existence of an organization and that you&#8217;re qualified to speak for them. There are also additional classes: Class 3, 4, and 5 are extended validation certificates used for servers, software signing, b2b transactions and government security.</p>

	<h3>Why should I sign PowerShell scripts?</h3>

	<p>Well, the chances are, you don&#8217;t need to.  Script signing is really a feature for corporations.  The idea is that scripts from your IT department need to be verifiable and unalterable&#8230; code-signing gives companies a way to lock down and secure PowerShell scripts: setting a global policy requiring script signing, and ensuring that all scripts produced by the corporate administrators are properly signed&#8230;</p>

	<p>As an individual, script-signing doesn&#8217;t really offer you much unless you share your computer with other administrator users.  After all, what it protects you from is  intentional or accidental altering of the script.  If there&#8217;s no one else who has access to your computer, then nobody can alter your scripts.  Of course, if someone <em>hacks</em> your computer enough to alter or create files on your hard drive and wanted to do something malicious, scripts would be a silly thing to target  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt=':)' class='wp-smiley' /> </p>

	<p>There is, however, one additional time when you might want to sign your scripts.  If you&#8217;re distributing scripts, whether via <a href="http://PoshCode.org">PoshCode.org</a>, the TechNet script gallery, or on CodePlex or the <span class="caps">MSDN</span> code gallery &#8230; signing them gives you (and your users) the assurance that <strong>you</strong> are the author, and they haven&#8217;t been altered.  In fact, the PoshCode Module which is available on <a href="http://PoshCode.org">PoshCode.org</a>, and which allows you to search and download (as well as upload) PoshCode scripts uses script signing to allow it to safely upgrade itself.  It features a <code>Get-PoshCode -Upgrade</code> command which will check for, and fetch, the latest version of the PoshCode module, and then validate it&#8217;s code signature is the same as the previous one before using it.</p>

	<p>Remember, code signing <strong>cannot</strong>:</p>

	<ul>
		<li>Guarantee that code is free of security vulnerabilities.</li>
		<li>Guarantee that a script doesn&#8217;t load unsafe or altered code during execution.</li>
	</ul>
	<ul>
		<li>Prevent copying or altering of your scripts (although PowerShell policies can prevent <em>accidental execution</em> of altered scripts).</li>
	</ul>

	<h2>How do I sign scripts?</h2>

	<p>Assuming that after skimming all of that, you want to try signing your scripts, you need a certificate. You can <a href="http://huddledmasses.org/code-signing-with-openssl-and-powershell/">generate one yourself</a> (although it&#8217;s not easy, and the signed scripts which will only work locally on your system, and won&#8217;t be trusted by anyone else) or you can get one from a public Certificate Authority (I recommend <a href="http://www.startssl.com/?app=2">StartCom/StartSSL</a> which only costs $40 for two year certificates).  </p>

	<p>Typically, your certificate will be a .pfx file which you can load using <code>Get-PfxCertificate</code>, or you might have imported it into your local certificate store using CertMgr.msc, in which case you can load it using Get-Item Cert:\CurrentUser\My\ with the thumbprint of the certificate.  In either case, you&#8217;ll have a certificate object you can pass to <code>Set-AuthenticodeSignature</code> along with the file path.</p>

	<h1>Wasn&#8217;t there supposed to be something automatic here?</h1>

	<p>Awhile back I wrote an <a href="http://poshcode.org/1473">Authenticode Script Module</a> which has wrappers for signing and testing signatures on scripts.  It uses a metadata file (which you have to create yourself) with a <code>PrivateData</code> variable that points to either the thumbprint of a certificate you&#8217;ve imported to your computer&#8217;s certificate store, or the path to a .pfx file &#8230; and allows you to sign files by just writing <code>sign .\FileToSign.ps1</code> without having to Get-PfxCertificate each time, or even remember to turn on the -TimeStampUrl feature so that your signed scripts stay signed even after the certificate expires.  That script helps a lot, but I&#8217;ve been wanting my text editor to sign the scripts automatically when I save them &#8230;</p>

	<p>I mostly use <a href="http://notepad-plus.sourceforge.net/">Notepad++</a> for editing PowerShell scripts (with a <a href="http://PoshCode.org/notepad++lexer">PowerShell Syntax lexer I helped create</a>), but after playing with the idea of writing a plugin to sign things after saving, I ended up deciding to go with something simpler: a PowerShell script to watch a folder for changes and sign any scripts I edit or save.</p>

	<p>I&#8217;ve added a function I call <code>Start-AutoSign</code> to my <a href="http://poshcode.org/1473">authenticode script module</a> which takes a path and a <code>-Recurse</code> flag and sets up a <a href="http://msdn.com/System.IO.FileSystemWatcher">System.IO.FileSystemWatcher</a> to detect saves, creates, and moves &#8230; and (re)sign the script if it needs it. Here is <code>Start-AutoSign</code> without the help docs or anything (so I can discuss it). You should just download the whole <a href="http://poshcode.org/1473">script module</a> if you want to use it  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt=':)' class='wp-smiley' /> </p>

	<div class="posh code posh" style="font-family:monospace;"><span style="color: #666699; font-weight: bold;">PARAM</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$Path</span><span style="color: #66cc66;">=</span><span style="color: #009900;">&quot;.&quot;</span>, <span style="color: #660033; font-weight: bold;">$Filter</span><span style="color: #66cc66;">=</span> <span style="color: #009900;">&quot;*.ps*&quot;</span>, <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #666699; font-weight: bold;">Switch</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$Recurse</span>, <span style="color: #660033; font-weight: bold;">$CertPath</span>, <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #666699; font-weight: bold;">Switch</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$NoNotify</span><span style="color: #333;">&#41;</span><br />
<span style="color: #666699; font-weight: bold;">if</span><span style="color: #333;">&#40;</span><span style="color: #66cc66;">!</span><span style="color: #660033; font-weight: bold;">$NoNotify</span> <span style="color: #000066;">-and</span> <span style="color: #333;">&#40;</span><span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">Module</span></span> Growl <span style="color: #000066;">-ListAvailable</span> <span style="color: #000066;">-ErrorAction</span> <span style="color: #cc66cc;">0</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Import-<span style="font-style: normal;">Module</span></span> Growl<br />
&nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Register-<span style="font-style: normal;">GrowlType</span></span> AutoSign <span style="color: #009900;">&quot;Signing File&quot;</span> <span style="color: #000066;">-ErrorAction</span> <span style="color: #cc66cc;">0</span><br />
<span style="color: #333;">&#125;</span> <span style="color: #666699; font-weight: bold;">else</span> <span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$NoNotify</span> <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$false</span> <span style="color: #333;">&#125;</span><br />
<br />
<span style="color: #660033; font-weight: bold;">$realItem</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">Item</span></span> <span style="color: #660033; font-weight: bold;">$Path</span> <span style="color: #000066;">-ErrorAction</span> Stop<br />
<span style="color: #666699; font-weight: bold;">if</span> <span style="color: #333;">&#40;</span><span style="color: #66cc66;">-</span><span style="color: #333399; font-weight: bold; font-style: italic;">not</span> <span style="color: #660033; font-weight: bold;">$realItem</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span> <span style="color: #666699; font-weight: bold;">return</span> <span style="color: #333;">&#125;</span> <br />
<br />
<span style="color: #660033; font-weight: bold;">$Action</span> <span style="color: #66cc66;">=</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$InvalidForm</span> <span style="color: #66cc66;">=</span> <span style="color: #009900;">&quot;The form specified for the subject is not one supported or known by the specified trust provider&quot;</span><br />
&nbsp; &nbsp;<br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">ForEach</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$file</span> <span style="color: #666699; font-weight: bold;">in</span> <span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">ChildItem</span></span> <span style="color: #660033; font-weight: bold;">$eventArgs</span>.<span style="color: #003366;">FullPath</span> <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">AuthenticodeSignature</span></span> <span style="color: #66cc66;">|</span> <br />
&nbsp; &nbsp; &nbsp; Where<span style="color: #66cc66;">-</span>Object <span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$_</span>.<span style="color: #003366;">Status</span> <span style="color: #000066;">-ne</span> <span style="color: #009900;">&quot;Valid&quot;</span> <span style="color: #000066;">-and</span> <span style="color: #660033; font-weight: bold;">$_</span>.<span style="color: #003366;">StatusMessage</span> <span style="color: #000066;">-ne</span> <span style="color: #660033; font-weight: bold;">$invalidForm</span> <span style="color: #333;">&#125;</span> <span style="color: #66cc66;">|</span> <br />
&nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">Select-<span style="font-style: normal;">Object</span></span> <span style="color: #000066;">-ExpandProperty</span> Path <span style="color: #333;">&#41;</span> <br />
&nbsp; &nbsp;<span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">if</span><span style="color: #333;">&#40;</span><span style="color: #66cc66;">!</span><span style="color: #660033; font-weight: bold;">$NoNotify</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Send-<span style="font-style: normal;">Growl</span></span> AutoSign <span style="color: #009900;">&quot;Signing File&quot;</span> <span style="color: #009900;">&quot;File $($eventArgs.ChangeType), signing:&quot;</span> <span style="color: #009900;">&quot;$file&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">if</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$CertPath</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Set-<span style="font-style: normal;">AuthenticodeSignature</span></span> <span style="color: #000066;">-FilePath</span> <span style="color: #660033; font-weight: bold;">$file</span> <span style="color: #000066;">-Certificate</span> <span style="color: #660033; font-weight: bold;">$CertPath</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span> <span style="color: #666699; font-weight: bold;">else</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Set-<span style="font-style: normal;">AuthenticodeSignature</span></span> <span style="color: #000066;">-FilePath</span> <span style="color: #660033; font-weight: bold;">$file</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span><br />
<span style="color: #660033; font-weight: bold;">$watcher</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">Object</span></span> IO.<span style="color: #003366;">FileSystemWatcher</span> <span style="color: #660033; font-weight: bold;">$realItem</span>.<span style="color: #003366;">Fullname</span>, <span style="color: #660033; font-weight: bold;">$filter</span> <span style="color: #000066;">-Property</span> @<span style="color: #333;">&#123;</span> IncludeSubdirectories <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$Recurse</span> <span style="color: #333;">&#125;</span><br />
<span style="color: #0066cc; font-style: italic;">Register-<span style="font-style: normal;">ObjectEvent</span></span> <span style="color: #660033; font-weight: bold;">$watcher</span> <span style="color: #009900;">&quot;Created&quot;</span> <span style="color: #009900;">&quot;AutoSignCreated$($realItem.Fullname)&quot;</span> <span style="color: #000066;">-Action</span> <span style="color: #660033; font-weight: bold;">$Action</span> <span style="color: #66cc66;">&amp;</span>gt; <span style="color: #660033; font-weight: bold;">$null</span><br />
<span style="color: #0066cc; font-style: italic;">Register-<span style="font-style: normal;">ObjectEvent</span></span> <span style="color: #660033; font-weight: bold;">$watcher</span> <span style="color: #009900;">&quot;Changed&quot;</span> <span style="color: #009900;">&quot;AutoSignChanged$($realItem.Fullname)&quot;</span> <span style="color: #000066;">-Action</span> <span style="color: #660033; font-weight: bold;">$Action</span> <span style="color: #66cc66;">&amp;</span>gt; <span style="color: #660033; font-weight: bold;">$null</span><br />
<span style="color: #0066cc; font-style: italic;">Register-<span style="font-style: normal;">ObjectEvent</span></span> <span style="color: #660033; font-weight: bold;">$watcher</span> <span style="color: #009900;">&quot;Renamed&quot;</span> <span style="color: #009900;">&quot;AutoSignChanged$($realItem.Fullname)&quot;</span> <span style="color: #000066;">-Action</span> <span style="color: #660033; font-weight: bold;">$Action</span> <span style="color: #66cc66;">&amp;</span>gt; <span style="color: #660033; font-weight: bold;">$null</span></div>

	<p>A few things to notice: first, I&#8217;m assuming you&#8217;re using <strong>my</strong> Set-AuthenticodeSignature wrapper, so by default I don&#8217;t pass it an actual certificate.  Second, in order to avoid eternally looping and re-signing the script over-and-over, you have to have a way to make sure you don&#8217;t re-sign it when it &#8220;changes&#8221; because you signed it.  The approach I took was to test and see if the signature was valid or not (and if it&#8217;s valid, then don&#8217;t sign it <em>again</em>).  Third: when you <code>Get-AuthenticodeSignature</code>, the Status codes leave much to be desired, returning the same &#8220;UnknownError&#8221; in several cases where they know <em>exactly</em> what the error is.  You can check the StatusMessage and see that they even <strong>tell</strong> you what the error was:</p>

	<ul>
		<li>The form specified for the subject is not one supported or known by the specified trust provider</li>
		<li>A certificate chain could not be built to a trusted root authority</li>
		<li>A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider</li>
	</ul>
	<ul>
		<li>A required certificate is not within its validity period when verifying against the current system clock or the timestamp in the signed file</li>
	</ul>

	<p>There may be other reasons too that I haven&#8217;t encountered yet, but the one thing we&#8217;re concerned with is the first one that the &#8220;form&#8221; isn&#8217;t supported. That means this is a file type which Set-AuthenticodeSignature can&#8217;t sign. PowerShell&#8217;s signing only works with executables, PowerShell scripts, modules, metadata, and xml files &#8230; so there&#8217;s no point trying to sign anything else.  You may also notice that in my script (by default) I&#8217;m only signing .ps* files (that is: scripts, modules, metadata and ps1xml files), and that&#8217;s because with .dll and .exe files, I would prefer to sign them as part of my build step anyway.</p>

	<p>One last thing: as with a few of my recent scripts, this one is designed to use <a href="http://GrowlForWindows.com">Growl for Windows</a> to notify you whenever it signs anything. If you don&#8217;t have the <a href="http://poshcode.org/1464">Growl module</a> available, it should just skip right over that without any problems, but you can disable it in any case with the <code>-NoNotify</code> switch.  Personally, I like seeing the popup so that I know it&#8217;s working, and know that I&#8217;m not accidentally signing something &#8230; and I love Growl for script notices because I can skin it, configure sounds, and forward the notices to other machines &#8230; or even temporarily disable them, all without having to tweak scripts.</p>

<div class="zemanta-pixie"><a class="zemanta-pixie-a" href="http://reblog.zemanta.com/zemified/3a72101f-e58c-47ed-accc-fc1c866ae964/" title="Reblog this post [with Zemanta]"><img class="zemanta-pixie-img" src="http://img.zemanta.com/reblog_e.png?x-id=3a72101f-e58c-47ed-accc-fc1c866ae964" alt="Reblog this post [with Zemanta]" /></a><span class="zem-script more-related pretty-attribution"><script type="text/javascript" src="http://static.zemanta.com/readside/loader.js" defer="defer"></script></span></div>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/signing-powershell-scripts-automatically/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>PowerShell Script Repository and Code Signing</title>
		<link>http://huddledmasses.org/powershell-script-repository-and-code-signing/</link>
		<comments>http://huddledmasses.org/powershell-script-repository-and-code-signing/#comments</comments>
		<pubDate>Fri, 04 Jul 2008 03:56:39 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[CodeSigning]]></category>
		<category><![CDATA[Cryptography]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Trust]]></category>

		<guid isPermaLink="false">http://HuddledMasses.org/powershell-script-repository-and-code-signing/</guid>
		<description><![CDATA[There&#8217;s been a lot of discussion on the #PowerShell IRC channel about code signing lately &#8212; mostly in response to my earlier posts (which I won&#8217;t link to here, because I should probably retract some of it after the discussions we&#8217;ve had). The discussion mostly revolves around how code signing applies to the PowerShell script [...]]]></description>
			<content:encoded><![CDATA[	<p>There&#8217;s been a lot of discussion on the #PowerShell <span class="caps">IRC</span> channel about code signing lately &#8212; mostly in response to my earlier posts (which I won&#8217;t link to here, because I should probably retract some of it after the discussions we&#8217;ve had). The discussion mostly revolves around how code signing applies to the PowerShell script repository and users&#8217; ability to trust scripts that they download.</p>

	<p>In order to keep the conversation going, and hopefully, include some of the Microsoft MVPs and PowerShell developers that don&#8217;t participate in the <span class="caps">IRC</span> channel at all, I&#8217;m going to post a summary of the conclusions we&#8217;ve drawn so far, and then outline a proposal for the repository.</p>

	<p>In case you don&#8217;t know, PowerShell implements code-signing for scripts using x509 Certificates (basically, <span class="caps">SSL</span> certs with &#8220;Extended&#8221; use properties), but the signatures are just embedded in the script as a comment, much like <span class="caps">PGP</span> 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&#8217;t valid, for instance, if the script has been modified, or the certificate used to sign it can&#8217;t be traced to a trusted Certificate Authority.</p>

	<blockquote>
		<p>PowerShell code-signing is inconvenient, and expensive. Scripts are only <strong>Valid</strong> if they are signed, unmodified, <em>and</em> the certificate traces back to a CA(Certificate Authority) that is in your Trusted Roots store (by default, basically, Microsoft&#8217;s, VeriSign, Thawte, and Comodo).</p>
		<p>You can create your own &#8220;test&#8221; 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.</p>
	</blockquote>

	<p>Because of this, to take advantage of PowerShell&#8217;s code-signing on your computer (that is, to set your ExecutionPolicy to &#8220;AllSigned&#8221; or &#8220;RemoteSigned&#8221;) you must do one of these things:</p>

	<ol>
		<li>Make sure that all script authors rent and use code-signing certs which cost more than $150 a year.</li>
		<li>Add a non-commercial root CA certificate (like <a href="http://CACert.org">CACert</a>) to (all of) your computer(s), and offer your authors the option of going through the process of getting one of those instead.</li>
		<li>Create a &#8220;community&#8221; CA &#8230; 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&#8217;s <em>really</em> a bad idea).</li>
	</ol>
	<ol>
		<li>Generate your own code-signing certificate (which can be self-signed) and just sign every script that you trust.</li>
	</ol>

	<p>So far, it seems like that last option is the only one that&#8217;s going to fly, because although some developers are willing to buy certificates to sign software they&#8217;re going to sell &#8230; most scripters  and sys-admins aren&#8217;t willing to buy one to share their certificates for free.<span id="more-562"></span></p>

	<p>So. Here&#8217;s the base fact:</p>

	<h3>The <a href="http://PoshCode.org"><b>Po</b>wer<b>Sh</b>ell Code repository</a> is a repository of user-provided code.</h3>

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

	<p><span class="em2">Rather than rely strictly on user login authentication, we will require that all (non anonymous) submissions be <span class="caps">SIGNED</span>, and the signing certificate (key) will be the user authentication mechanism.</span>  Essentially, any unsigned code will show up as written by &#8220;anonymous&#8221; ... and any signed code will show up with the identity from the signing certificate &#8212; 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.</p>

	<p>In addition to the <em>author&#8217;s</em> 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 &#8212; they simply submit the exact same script as a modification, but with their signature in place of the author&#8217;s.  </p>

	<p>So users will sign scripts to say they trust them, and when you browse or search the repository, you&#8217;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&#8230;</p>

	<h3>Additionally, there will be a <code>Get-PoshCode</code> cmdlet which probably should:</h3>

	<ul>
		<li>Mark the downloaded scripts as &#8216;remote&#8217;.</li>
		<li>Add the download permalink url in a comment upon download (to aid in discovering other signatures and in adding <em>your</em> signature).</li>
		<li>Handle a cache of &#8220;trusted&#8221; 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 &#8212; particularly if there isn&#8217;t already a trusted signature available for the script.</li>
		<li>Validate the signature(s) after download, and provide a report (eg: valid/invalid).</li>
	</ul>
	<ul>
		<li>Offer to replace the signature (with yours) if it&#8217;s not a trusted x509 authenticode signature.</li>
	</ul>

	<h2>What certificate system should we use?</h2>

	<p>You may have assumed that we&#8217;re planning on using Microsoft&#8217;s code signing which is built into PowerShell, but when we were discussing this in the <span class="caps">IRC</span> channel, one of the things that kept coming up is that one way or another, we&#8217;re essentially creating an alternative way for people to &#8220;trust&#8221; the certificate &#8212; since we&#8217;re assuming that most of these certificates will be self-signed. </p>

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

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

	<h3>x509 (aka &#8220;Authenticode&#8221;) signatures &#8212; supported by Microsoft.</h3>

	<ul>
		<li>Probably self-signed and therefore won&#8217;t &#8220;work&#8221; properly in PowerShell anyway.</li>
		<li>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:</li>
		<li>Verifiable by PowerShell natively, and therefore, they: </li>
	</ul>
	<ul>
		<li>Don&#8217;t require a separate signature in order to execute when the <code>ExecutePolicy</code> is set to <strong>AllSigned</strong>.</li>
	</ul>

	<h3><span class="caps">PGP</span> signatures (supported by the Open Source community and used in Debian, etc)</h3>

	<ul>
		<li>Just as (un)trustworthy as any other <span class="em1">self-signed certificate</span> ... except that:</li>
		<li><span class="caps">PGP</span> certificates (keys) are inherently user-signable. The community can vouch for each other&#8217;s identities, and create a web-of-trust for authentication purposes (which is all x509 really accomplishes anyway &#8212; you trust that Verisign makes sure that they are who they say they are, and live where they say they live).</li>
		<li>Not inherently usable by PowerShell.</li>
	</ul>
	<ul>
		<li>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 <span class="caps">PGP</span> certificate when you wanted to upload it.</li>
	</ul>

	<h2>Final thoughts</h2>

	<p>Of course, there&#8217;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 <span class="caps">PGP</span> 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.</p>

	<p>So the first question is, can we do <span class="caps">PGP</span> signing in pure .Net for a cmdlet (maybe using <a href="http://www.bouncycastle.org/csharp/index.html">bouncy castle</a>), and can we easily create a Set-PGPSignature cmdlet? </p>

	<p>Has there been any progress on a way to do <span class="caps">PGP</span> signing that&#8217;s compatible with <span class="caps">XML</span> files (eg: ps1xml files)? </p>

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

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

	<h5>We need to make signing slightly easier.</h5>

	<p>It&#8217;s a pain to find your certificate, and the built-in AuthenticodeSignature cmdlets are <strong>horrible</strong> at parsing parameters.</p>

	<h5>We need to make generating these self-signing certs trivial for non-<span class="caps">SDK</span> machines</h5>

	<p>It&#8217;s really pretty easy with MakeCert, but that&#8217;s not redistributable, and the Windows <span class="caps">SDK</span> is a ridiculously large download for someone who just wants to sign their scripts.  I&#8217;ve written a script to <a href="http://huddledmasses.org/code-signing-with-openssl-and-powershell/#more-551">generate code-signing certs</a> using OpenSSL, which <em>is</em> redistributable, but it&#8217;s still not great.</p>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/powershell-script-repository-and-code-signing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

