PoshCode Logo PowerShell Code Repository

New-CodeSigningCert (modification of post by view diff)
embed code: <script type="text/javascript" src="http://PoshCode.org/embed/1049"></script>download | new post

Generates a self-signed certificate authority and a code-signing certificate using OpenSSL
Shows how to import certificates to the current user and local machine stores using System.Security.Cryptography.X509Certificates.X509Store

Please READ the intro comments, and consider deleting your Certificate Authority Private key if you can’t be 100% sure you can secure it.

  1. ## New-CodeSigningCert.ps1
  2. ########################################################################################################################
  3. ## Does the setup needed to self-sign PowerShell scripts ...
  4. ## Generates a "test" self-signed root Certificate Authority
  5. ## And then generates a code-signing certificate (and signs it with the CA certificate)
  6. ## OPTIONALLY (specify -import or -importall) imports the certificates to the store(s)
  7. ########################################################################################################################
  8. ## NOTE: Uses OpenSSL (because it's xcopy redistributable -- wake up Microsoft)
  9. ##       In order for this to work you should KEEP the script in the folder with OpenSsl.exe
  10. ## Also, it is VERY important that you properly provide passwords and the locale data...
  11. ## You can obviously reorder the parameters however you like, and hard-code some of the values in the parameters, but
  12. ## you need to make sure that if you use this to generate multiple certificates, that you preserve all of the certs
  13. ## and keep track of all your passwords so you don't lock yourself out of any of them.
  14. ########################################################################################################################
  15. ## Usage:
  16. ## \\Server\PoshCerts\New-CodeSigningCert.ps1 $pwd\Certs "Joel Bennett" Jaykul@HuddledMasses.org HuddledMasses.org Mystery Rochester "New York" US -importall -OpenSSLLocation C:\Users\Joel\Documents\WindowsPowershell\PoshCerts\bin -CAPassword MyCleverRootPassword -CodeSignPassword EvenMoreCleverPasswords
  17. ##
  18. ## If I hard-coded the company/dept/etc ... I could use this to generate certs for all my devs:
  19. ##
  20. ## \\Server\PoshCerts\New-CodeSigningCert.ps1 $pwd\Certs "Mark Andreyovich" FakeEmail@Xerox.net -CAPassword MyCleverRootPassword -CodeSignPassword MarksPassword
  21. ## \\Server\PoshCerts\New-CodeSigningCert.ps1 $pwd\Certs "Jesse Voller" FakeEmail2@Xerox.net -CAPassword MyCleverRootPassword -CodeSignPassword JessesPassword
  22. ##
  23. ## For the signed scripts to work, I just  have to -import on the devices where the scripts need to run:
  24. ##
  25. ## \\Server\PoshCerts\New-CodeSigningCert.ps1 $pwd\Certs "Jesse Voller" -import
  26. ## \\Server\PoshCerts\New-CodeSigningCert.ps1 $pwd\Certs "Mark Andreyovich" -import
  27. ## \\Server\PoshCerts\New-CodeSigningCert.ps1 $pwd\Certs "Joel Bennett" -import
  28. ##
  29. ## On the developers' workstations, I need to use Get-PfxCertificate to sign, or else run -importall
  30. ## That will load the codesigning cert in their "my" store, and will only require the password for the initial import
  31. ##
  32. ## \\Server\PoshCerts\New-CodeSigningCert.ps1 $pwd\Certs "Joel Bennett" -importall -CodeSignPassword MyCodeSignPassword
  33. ########################################################################################################################
  34. ## History
  35. ##  1.0 - Initial public release
  36. ##  1.1 - Bug fix release to make it easier to use...
  37. ##  1.2 - Bug fix to get the ORG and COMMON NAME set correctly -- Major whoops!
  38. ##
  39. Param(
  40. $CertStorageLocation = (join-path (split-path $Profile) "Certs"),
  41. $UserName       = (Read-Host "User name")
  42.  
  43. , $email        
  44. , $company      
  45. , $department  
  46. , $city        
  47. , $state        
  48. , $country      
  49.  
  50. , $RootCAName   = "Self-Signed-Root-CA"
  51. , $CodeSignName = "$UserName Code-Signing"
  52. , $alias        = "PoshCert",
  53.  
  54.  
  55. [string]$keyBits = 4096,
  56. [string]$days = 365,
  57. [string]$daysCA = (365 * 5),
  58.  
  59. [switch]$forceNew = $false,
  60. [switch]$importall = $false,
  61. [switch]$import = ($false -or $importall),
  62.  
  63. ## we ask you to specify the CA password and your codesign password
  64. ## You can leave these null when importing on end-user desktops
  65. $CAPassword = $null,
  66. $CodeSignPassword = $null,
  67.  
  68. ## You really shouldn't pass these unless you know what you're doing
  69. $OpenSSLLocation = $null,
  70. $RootCAPassword = $Null,
  71. $CodeSignCertPassword = $null
  72. )
  73.  
  74.  
  75. function Get-UserEmail {
  76.    if(!$script:email) {
  77.       $script:email = (Read-Host "Email address")
  78.    }
  79.    return $script:email
  80. }
  81.  
  82. function Get-RootCAPassword {
  83.    if(!$script:RootCAPassword) {
  84.       if(!$script:CAPassword) {
  85.          $script:CAPassword = ((new-object System.Management.Automation.PSCredential "hi",(Read-Host -AsSecureString "Root CA Password")).GetNetworkCredential().Password)
  86.       }
  87.  
  88.       ## Then down here we calculate large passwords to actually use:
  89.       ## This works as long as you keep the same company name and root ca name
  90.       $script:RootCAPassword = [Convert]::ToBase64String( (new-Object Security.Cryptography.PasswordDeriveBytes ([Text.Encoding]::UTF8.GetBytes($CaPassword)), ([Text.Encoding]::UTF8.GetBytes("$company$RootCAName")), "SHA1", 5).GetBytes(64) )
  91.    }
  92.    return $script:RootCAPassword
  93. }
  94.  
  95. function Get-CodeSignPassword {
  96.    if(!$script:CodeSignCertPassword) {
  97.    
  98.       if(!$script:CodeSignPassword) {
  99.          $script:CodeSignPassword = ((new-object System.Management.Automation.PSCredential "hi",(Read-Host -AsSecureString "Code Signing Password")).GetNetworkCredential().Password)
  100.       }
  101.       ## This works as long as you keep the same PFX password and email address
  102.       $script:CodeSignCertPassword = ([Convert]::ToBase64String( (new-Object Security.Cryptography.PasswordDeriveBytes ([Text.Encoding]::UTF8.GetBytes($CodeSignPassword)), ([Text.Encoding]::UTF8.GetBytes((Get-UserEmail))), "SHA1", 5).GetBytes(64) ))
  103.    }
  104.    return $script:CodeSignCertPassword
  105. }
  106.  
  107. function Get-SslConfig {
  108. Param (
  109.    $keyBits,
  110.    $Country    = (Read-Host "Country (2-Letter code)"),
  111.    $State      = (Read-Host "State (Full Name, no intials)"),
  112.    $city       = (Read-Host "City"),
  113.    $company    = (Read-Host "Company Name (or Web URL)"),
  114.    $orgUnit    = (Read-Host "Department (team, group, family)"),
  115.    $CommonName,
  116.    $email = (Read-Host "Email Address")
  117. )
  118. @"
  119. # OpenSSL example configuration file for BATCH certificate generation
  120. # This definition stops the following lines choking if HOME isn't  defined.
  121. HOME                       = .
  122. RANDFILE                   = $($ENV::HOME)/.rnd
  123.  
  124. # To use this configuration with the "-extfile" option of the "openssl x509" utility
  125. # name here the section containing the X.509v3 extensions to use:
  126. #extensions             = code_sign
  127.  
  128. ####################################################################
  129. [ req ]
  130. default_bits               = {0}
  131. default_keyfile            = privkey.pem
  132. distinguished_name      = req_distinguished_name
  133. #attributes                   = req_attributes
  134. x509_extensions    = v3_ca  # The extentions to add to the self signed cert
  135. # req_extensions     = v3_ca  # Other extensions to add to a certificate request?
  136.  
  137. ## Passwords for private keys could be specified here, instead of on the commandline
  138. # input_password = secret
  139. # output_password = secret
  140.  
  141. ## Set the permitted string types...
  142. ## Some software crashes on BMPStrings or UTF8Strings, so we'll stick with
  143. string_mask = nombstr
  144.  
  145. [ req_distinguished_name ]
  146. countryName                           = Country Name (2 letter code)
  147. countryName_default             = {1}
  148. countryName_min                 = 2
  149. countryName_max                 = 2
  150.  
  151. stateOrProvinceName             = State or Province Name (full name)
  152. stateOrProvinceName_default     = {2}
  153.  
  154. localityName                    = Locality Name (eg, city)
  155. localityName_default = {3}
  156.  
  157. 0.organizationName              = Organization Name (eg, company)
  158. 0.organizationName_default      = {4}
  159.  
  160. # we can do this but it is not usually needed
  161. #1.organizationName             = Second Organization Name (eg, company)
  162. #1.organizationName_default     = World Wide Web Pty Ltd
  163.  
  164. organizationalUnitName                = Organizational Unit Name (eg, section)
  165. organizationalUnitName_default  = {5}
  166.  
  167. commonName                      = Common Name (eg, YOUR name)
  168. commonName_default = {6}
  169. commonName_max                  = 64
  170.  
  171. emailAddress                    = Email Address
  172. emailAddress_default = {7}
  173. emailAddress_max                = 64
  174.  
  175. # SET-ex3                       = SET extension number 3
  176.  
  177. # [ req_attributes ]
  178. # challengePassword             = A challenge password
  179. # challengePassword_min         = 4
  180. # challengePassword_max         = 20
  181. # unstructuredName              = An optional company name
  182.  
  183. [ v3_ca ]
  184. ## Extensions for a typical CA
  185.  
  186. ## PKIX recommendations:
  187. subjectKeyIdentifier=hash
  188. authorityKeyIdentifier=keyid:always,issuer:always
  189. ## PKIX suggests we should include email address in subject alt name
  190. # subjectAltName=email:copy
  191. ## But really they want it *only* there or the certs are "deprecated"
  192. # subjectAltName=email:move
  193. ## And the issuer details
  194. # issuerAltName=issuer:copy
  195.  
  196.  
  197. ## This is what PKIX recommends
  198. basicConstraints = critical,CA:true
  199. ## some broken software chokes on critical extensions, so you could do this instead.
  200. #basicConstraints = CA:true
  201.  
  202. ## For a normal CA certificate you would want to specify this.
  203. ## But it will cause problems for our self-signed certificate.
  204. # keyUsage = cRLSign, keyCertSign
  205.  
  206. ## You might want the netscape-compatible stuff too
  207. # nsCertType = sslCA, emailCA
  208.  
  209. [ code_sign ]
  210. # These extensions are added when we get a code_signing cert
  211. ## PKIX recommendations:
  212. subjectKeyIdentifier=hash
  213. authorityKeyIdentifier=keyid,issuer
  214.  
  215. ## PKIX suggests we should include email address in subject alt name
  216. # subjectAltName=email:copy
  217. ## But really they want it *only* there or the certs are "deprecated"
  218. # subjectAltName=email:move
  219. ## And the issuer details
  220. # issuerAltName=issuer:copy
  221.  
  222. # This goes against PKIX guidelines but some CAs do it and some software
  223. # requires this to avoid interpreting an end user certificate as a CA.
  224. basicConstraints=CA:FALSE
  225.  
  226. # If nsCertType is omitted, the certificate can be used for anything *except* object signing.
  227. # We just want to allow everything including object signing:
  228. nsCertType = server, client, email, objsign
  229. # This is the vital bit for code-signing
  230. extendedKeyUsage       = critical, serverAuth,clientAuth,codeSigning
  231.  
  232. # This is typical in keyUsage for a client certificate.
  233. keyUsage = nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment
  234.  
  235. # This will be displayed in Netscape's comment listbox.
  236. nsComment                       = "OpenSSL Generated Certificate"
  237.  
  238. [ crl_ext ]
  239. # CRL extensions.
  240. # Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
  241.  
  242. # issuerAltName=issuer:copy
  243. authorityKeyIdentifier=keyid:always,issuer:always
  244. "@ -f $keyBits,$Country,$State,$city,$company,$orgUnit,$CommonName,$email
  245. }
  246.  
  247. if(!$OpenSSLLocation) {
  248.    ## You should be running the script from the OpenSsl folder
  249.    $OpenSSLLocation = Split-Path $MyInvocation.MyCommand.Path
  250.    Write-Debug "OpenSSL: $OpenSSLLocation"
  251. }
  252. if( Test-Path $OpenSslLocation ) {
  253.    ## The OpenSslLoction needs to actually have OpenSsl in it ...
  254.    $files = ls (Join-Path $OpenSSLLocation "*.[de][lx][el]") -include libeay32.dll,ssleay32.dll,OpenSSL.exe # libssl32.dll,
  255.    if($files.count -lt 3) {
  256.       THROW "You need to configure a location where OpenSSL can be run from"
  257.    }
  258. } else { THROW "You need to configure a location where OpenSSL can be run from" }
  259.  
  260. ## Don't touch these
  261. [string]$SslCnfPath = (join-path (Convert-Path $CertStorageLocation) PoshOpenSSL.config)
  262. New-Alias OpenSsl (join-path $OpenSSLLocation OpenSSL.exe)
  263.  
  264. if( !(Test-Path $CertStorageLocation) ) {
  265.    New-Item -type directory -path $CertStorageLocation | Push-Location
  266.    $forceNew = $true
  267. } else {
  268.    Push-Location $CertStorageLocation
  269. }
  270.  
  271. Write-Debug "SslCnfPath: $SslCnfPath"
  272. Write-Debug "OpenSsl: $((get-alias OpenSsl).Definition)"
  273.  
  274. ## Process the CSR and generate a pfx file
  275. if($forceNew -or (@(Test-Path "$CodeSignName.crt","$CodeSignName.pfx") -contains $false)) {
  276.  
  277.    ## Generate the private code-signing key and a certificate signing request (csr)
  278.    if($forceNew -or (@(Test-Path "$CodeSignName.key","$CodeSignName.csr") -contains $false)) {
  279.  
  280.       ## Generate the private root CA key and convert it into a self-signed certificate (crt)
  281.       if($forceNew -or (@(Test-Path "$RootCAName.key","$RootCAName.crt") -contains $false)) {
  282.  
  283.          ## Change configuration before -batch processing root key
  284.          $CommonName = "$company Certificate Authority"
  285.          $orgUnit = "$department Certificate Authority"
  286.          $email = Get-UserEmail
  287.          Set-Content $SslCnfPath (Get-SslConfig $keyBits $Country $State $city $company $orgUnit $CommonName $email) ## My special config file
  288.  
  289.          OpenSsl genrsa -out "$RootCAName.key" -des3 -passout pass:$(Get-RootCAPassword) $keyBits
  290.          OpenSsl req -new -x509 -days $daysCA -key "$RootCAName.key" -out "$RootCAName.crt" -passin pass:$(Get-RootCAPassword) -config $SslCnfPath -batch
  291.       }
  292.  
  293.       ## Change configuration before -batch processing code-signing key
  294.       $CommonName = "$UserName"
  295.       $orgUnit = "$department"
  296.       $email = Get-UserEmail
  297.       Set-Content $SslCnfPath (Get-SslConfig $keyBits $Country $State $city $company $orgUnit $CommonName $email) ## My special config file
  298.  
  299.       OpenSsl genrsa -out "$CodeSignName.key" -des3 -passout pass:$(Get-CodeSignPassword) $keyBits
  300.       OpenSsl req -new -key "$CodeSignName.key" -out "$CodeSignName.csr" -passin pass:$(Get-CodeSignPassword) -config $SslCnfPath -batch
  301.    }
  302.  
  303.    ## Use the root CA key to process the CSR and sign the code-signing key in one step...
  304.    OpenSsl x509 -req -days $days -in "$CodeSignName.csr" -CA "$RootCAName.crt" -CAcreateserial -CAkey "$RootCAName.key" -out "$CodeSignName.crt" -setalias $alias -extfile $SslCnfPath -extensions code_sign -passin pass:$(Get-RootCAPassword)
  305.    ## Combine the signed certificate and the private key into a single file and specify a new password for it ...
  306.    OpenSsl pkcs12 -export -out "$CodeSignName.pfx" -inkey "$CodeSignName.key" -in "$CodeSignName.crt" -passin pass:$(Get-CodeSignPassword) -passout pass:$script:CodeSignPassword
  307. }
  308.  
  309. Pop-Location
  310.  
  311. if($import) {
  312.    ## Now we need to import the certificates to the computer so we can use them...
  313.    ## Sadly, the PowerShell Certificate Provider is read-only, so we need to do this by hand
  314.    
  315.    trap {
  316.       if($_.Exception.GetBaseException() -is [UnauthorizedAccessException]) {
  317.          write-error "Cannot import certificates as 'Root CA' or 'Trusted Publisher' except in an elevated console."
  318.          continue
  319.       }
  320.    }
  321.    
  322.    ## In order to be able to use scripts signed by these certs
  323.    ## The root cert that signed the code-signing certs must be loaded into the "Root" store
  324.    $lm = new-object System.Security.Cryptography.X509certificates.X509Store "root", "LocalMachine"
  325.    $lm.Open("ReadWrite")
  326.    $lm.Add( (Get-PfxCertificate "$CertStorageLocation\$RootCAName.crt") )
  327.    if($?) {
  328.       Write-Host "Successfully imported root certificate to trusted root store" -fore green
  329.    }
  330.    $lm.Close()
  331.  
  332.    ## In order to avoid the "untrusted publisher" prompt
  333.    ## The public code-signing cert must be loaded into the "TrustedPublishers" store
  334.    $tp = new-object System.Security.Cryptography.X509certificates.X509Store "TrustedPublisher", "LocalMachine"
  335.    $tp.Open("ReadWrite")
  336.    $tp.Add( (Get-PfxCertificate "$CertStorageLocation\$CodeSignName.crt") )
  337.    if($?) {
  338.       Write-Host "Successfully imported code-signing certificate to trusted publishers store" -fore green
  339.    }
  340.    $tp.Close()
  341.  
  342.    if($importall) {
  343.       ## It's a good practice to go ahead and put our private certificates in "OUR" store too
  344.       ### Otherwise we have to load it each time from the pfx file using Get-PfxCertificate
  345.       ##### $cert = Get-PfxCertificate "$CodeSignName.pfx"
  346.       ##### Set-AuthenticodeSignature -Cert $cert -File Test-Script.ps1
  347.       $my = new-object System.Security.Cryptography.X509certificates.X509Store "My", "CurrentUser"
  348.       $my.Open( "ReadWrite" )
  349.       Get-CodeSignPassword
  350.       $my.Add((Get-PfxCertificate "$CertStorageLocation\$CodeSignName.pfx"))      #$script:CodeSignPassword, $DefaultStorage)
  351.       if($?) {
  352.          Write-Host "Successfully imported code-signing certificate to 'my' store" -fore yellow
  353.       }
  354.       $my.Close()
  355.    }
  356. }
  357.  
  358. # SIG # Begin signature block
  359. # MIILCQYJKoZIhvcNAQcCoIIK+jCCCvYCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
  360. # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
  361. # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUunVl0UTZlvAjOS219sL9EUT4
  362. # EE6gggbgMIIG3DCCBMSgAwIBAgIJALPpqDj9wp7xMA0GCSqGSIb3DQEBBQUAMIHj
  363. # MQswCQYDVQQGEwJVUzERMA8GA1UECBMITmV3IFlvcmsxEjAQBgNVBAcTCVJvY2hl
  364. # c3RlcjEhMB8GA1UEChMYaHR0cDovL0h1ZGRsZWRNYXNzZXMub3JnMSgwJgYDVQQL
  365. # Ex9TY3JpcHRpbmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MTcwNQYDVQQDEy5odHRw
  366. # Oi8vSHVkZGxlZE1hc3Nlcy5vcmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MScwJQYJ
  367. # KoZIhvcNAQkBFhhKYXlrdWxASHVkZGxlZE1hc3Nlcy5vcmcwHhcNMDkwMzE1MTkx
  368. # OTE5WhcNMTAwMzE1MTkxOTE5WjCBqzELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5l
  369. # dyBZb3JrMRIwEAYDVQQHEwlSb2NoZXN0ZXIxITAfBgNVBAoTGGh0dHA6Ly9IdWRk
  370. # bGVkTWFzc2VzLm9yZzESMBAGA1UECxMJU2NyaXB0aW5nMRUwEwYDVQQDEwxKb2Vs
  371. # IEJlbm5ldHQxJzAlBgkqhkiG9w0BCQEWGEpheWt1bEBIdWRkbGVkTWFzc2VzLm9y
  372. # ZzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPfqxOG9TQN+qZjZ6KfM
  373. # +zBK0YpjeyPL/cFgiGBhiIdYWTBtkbZydFr3IiERKRsUJ0/SKFbhf0C3Bvd/neTJ
  374. # qiZjH4D6xkrfdLlWMmmSXXqjSt48jZp+zfCAIaF8K84e9//7lMicdVFE6VcgoATZ
  375. # /eMKQky4JvphJpzDHYPLxLJQrKd0pjDDwspjdX5RedWkzeZBG7VfBnebLWUzgnMX
  376. # IxRQKfFCMryQDP8weceOnJjfJEf2FYmdpsEg5EKKKbuHsQCMVTxfteKdPvh1oh05
  377. # 1GWyPsvEPh4auJUT8pAVvrdxq+/O9KW/UV01UxjRYM1vdklNw8g7mkJTrrHjSjl7
  378. # tuugCnJjt5kN6v/OaUtRRMR68O85bSTVGOxJGCHUKlyuuTx9tnfIgy4siFYX1Ve8
  379. # xwaAdN3haTon3UkWzncHOq3reCIVF0luwRZu7u+TnOAnz2BRlt+rcT0O73GN20Fx
  380. # gyN2f5VGBbw1KuS7T8XZ0TFCspUdgwAcmTGuEVJKGhVcGAvNlLx+KPc5dba4qEfs
  381. # VZ0MssC2rALC1z61qWuucb5psHYhuD2tw1SrztywuxihIirZD+1+yKE4LsjkM1zG
  382. # fQwDO/DQJwkdByjfB2I64p6mk36OlZAFxVfRBpXSCzdzbgKpuPsbtjkb5lGvKjE1
  383. # JFVls1SHLJ9q80jHz6yW7juBAgMBAAGjgcgwgcUwHQYDVR0OBBYEFO0wLZyg+qGH
  384. # Z4WO8ucEGNIdU1T9MB8GA1UdIwQYMBaAFN2N42ZweJLF1mz0j70TMxePMcUHMAkG
  385. # A1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgTwMCoGA1UdJQEB/wQgMB4GCCsGAQUF
  386. # BwMBBggrBgEFBQcDAgYIKwYBBQUHAwMwCwYDVR0PBAQDAgTwMCwGCWCGSAGG+EIB
  387. # DQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTANBgkqhkiG9w0BAQUF
  388. # AAOCAgEAmKihxd6KYamLG0YLvs/unUTVJ+NW3jZP16R28PpmidY/kaBFOPhYyMl2
  389. # bBGQABe7LA5rpHFAs0F56gYETNoFk0qREVvaoz9u18VfLb0Uwqtnq0P68L4c7p2q
  390. # V3nKmWjeI6H7BAyFuogxmMH5TGDfiqrrVSuh1LtPbkV2Wtto0SAxP0Ndyts2J8Ha
  391. # vu/2rt0Ic5AkyD+RblFPtzkCC/MLVwSNAiDSKGRPRrLaiGxntEzR59GRyf2vwhGg
  392. # oAXUqcJ/CVeHCP6qdSTM39Ut3RmMZHXz5qY8bvLgNYL6MtcJAx+EeUhW497alzm1
  393. # jInXdbikIh0d/peTSDyLbjS8CPFFtS6Z56TDGMf+ouTpEA16otcWIPA8Zfjq+7n7
  394. # iBHjeuy7ONoJ2VDNgqn9B+ft8UWRwnJbyB85T83OAGf4vyhCPz3Kg8kWxY30Bhnp
  395. # Fayc6zQKCpn5o5T0/a0BBHwAyMfr7Lhav+61GpzzG1KfAw58N2GV8KCPKNEd3Zdz
  396. # y07aJadroVkW5R+35mSafKRJp5pz20GDRwZQllqGH1Y/UJFEiI0Bme9ecbl2vzNp
  397. # JjHyl/jLVzNVrBI5Zwb0lCLsykApgNY0yrwEqaiqwcxq5nkXFDhDPQvbdulihSo0
  398. # u33fJreCm2fFyGbTuvR61goSksAvLQhvijLAzcKqWKG+laOtYpAxggOTMIIDjwIB
  399. # ATCB8TCB4zELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMRIwEAYDVQQH
  400. # EwlSb2NoZXN0ZXIxITAfBgNVBAoTGGh0dHA6Ly9IdWRkbGVkTWFzc2VzLm9yZzEo
  401. # MCYGA1UECxMfU2NyaXB0aW5nIENlcnRpZmljYXRlIEF1dGhvcml0eTE3MDUGA1UE
  402. # AxMuaHR0cDovL0h1ZGRsZWRNYXNzZXMub3JnIENlcnRpZmljYXRlIEF1dGhvcml0
  403. # eTEnMCUGCSqGSIb3DQEJARYYSmF5a3VsQEh1ZGRsZWRNYXNzZXMub3JnAgkAs+mo
  404. # OP3CnvEwCQYFKw4DAhoFAKB4MBgGCisGAQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJ
  405. # KoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQB
  406. # gjcCARUwIwYJKoZIhvcNAQkEMRYEFGPa+3yKeAOuG8MGktIPE98U9IQyMA0GCSqG
  407. # SIb3DQEBAQUABIICACukiWmmkw/T3q/IukaKIIO4/jJLng9v52P60RViKwJn7TOZ
  408. # C6Qcov2zO8/LBm8oIlY+kQil8MXqA3+5D7TGtFfYpyzoUh+Nwks1C9KAMWeRBKAL
  409. # b3H6CVX0H5nRh9PLa2a4WxbYHM6IxCOa/Z8clH4veAZbs5Zq5mtjLV14u8PszAYM
  410. # 4P/H0sXHMZYb9nj0vKjsZdxOlM0g6JHqUszE40tND/5dFuzdr3Tyu/aC6/j/ZFGZ
  411. # jdyaM88kE88qAU9Bs2M18LsSUJx6GsdlXwDD4eCBRH59+QtAnQZB4HUL5KkF53DG
  412. # J0WtRuI+wWmeMU9nNtDMQgSGJev0LVEJ2Ui+UsVA+RvWH04VCBrzlXi2TLzS9bCQ
  413. # 5Fo/t/czCbC4m/WrXQyYNDoHtI/fXE2ctSPq2QQaDF9Bu65MuMGzWa3iFSFmq0uA
  414. # nYivtHSlgyqhPBBmu8fspePkye7PzYoH2Gpykp17R5fBx+rQriKjTkZcGNdAGdQY
  415. # j7SEC93e0KjtZRQA+ABxmVacmNrO6NGbMN2Zd8Pheham1T38V3aWjKvq2d94iUfh
  416. # dgqvWhSu6zw0yE/NaJPTKnixN0j+up/Y7jSO9Cytvl4TNWJkFjDp+u0exl4s6eQ5
  417. # cspbWHwWyYWyg7e0YaclbL7mPygvjxQDWOWgMN9cddvHCq8fiq6VPNTJqeLB
  418. # SIG # End signature block

Submit a correction or amendment below (
click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:


Remember me