I should be doing something else, but I got looking at the installed certificates in my system. That’s partly prompted by a desire to make a list of certificates installed on my Windows 8.1 machines, and read up on how the various browsers use these certificates (my understanding is that Firefox and Chrome have their own stores in addition (or in exclusion?) to the default Windows certificate store).
Anyways, I did the following to get a list of all the trusted CA in my certificate store:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
PS> Get-ChildItem Cert:\LocalMachine\Root Directory: Microsoft.PowerShell.Security\Certificate::LocalMachine\Root Thumbprint Subject ---------- ------- D5658EF700F9B4C0CCDB095E491EF4B84DDD4A09 CN=LONSDC01.cloudapp.net CDD4EEAE6000AC7F40C3802C171E30148030C072 CN=Microsoft Root Certificate Authority, DC=... BE36A4562FB2EE05DBB3D32323ADF445084ED656 CN=Thawte Timestamping CA, OU=Thawte Certifi... A43489159A520F0D93D032CCAF37E7FE20A8B419 CN=Microsoft Root Authority, OU=Microsoft Co... 8F43288AD272F3103B6FB1428485EA3014C0BCFE CN=Microsoft Root Certificate Authority 2011... <snip> |
I quickly got side tracked from that when I noticed the thumbprint and wondered what I could do to space it out. What I meant is: if you go to your browser and check the thumbprint/ fingerprint, it is usually a bunch of 40 characters but with spaces between every two characters. Like this: D5 65 8E ...
. In contrast the PowerShell output gave everything together. The two are same, but I needed and excuse to try something, so wondered how I could present it differently.
Initially I thought of using the -replace
operator but then I thought it might be better to -split
and -join
them. Both will make use of regular expressions I think, and that’s my ultimate goal here – to think a bit on what regular expressions I can use and remind myself on the caveats of these operators.
The -split
operator can take a regular expression as the delimiter. Whenever the expression matches, the matched characters are considered to identify the end of the sub-string, and so the part before it is returned. In my case I want to split along every two characters, so I could do something like this:
1 |
-split "[a-z0-9]{2}" |
This, however, will return no output because every block of two characters is considered as the delimiter and split off, but there then remains nothing else to output. So the result is a bunch of empty lines.
To make the delimiter show in the output I can enclose it within brackets:
1 |
-split "([a-z0-9]{2})" |
Now the output will be an empty line followed a block of two characters (the delimiter), followed by an empty line, and so on …
I can’t -join
these together with a delimiter because then the empty lines too get pulled in. Here’s an example -join
using the +
character as delimiter so you can see what happens:
1 2 |
PS> 2796BAE63F1801E277261BA0D77770028F20EEE4" -split "([a-z0-9]{2})" -join "+" +27++96++BA++E6++3F++18++01++E2++77++26++1B++A0++D7++77++70++02++8F++20++EE++E4+ |
What’s happening is that the empty objects too get sandwiched between the output we want.
Now, if only there was a way to cull out the empty objects. Why of course, that’s what the Where-Object
cmdlet can do!
Like this perhaps (I only let through non-empty objects):
1 |
PS> "2796BAE63F1801E277261BA0D77770028F20EEE4" -split "([a-z0-9]{2})" | ?{ $_ -notmatch '^$' } |
Or perhaps (I only let through objects with non-zero length):
1 |
PS> "2796BAE63F1801E277261BA0D77770028F20EEE4" -split "([a-z0-9]{2})" | ?{ $_.length -ne 0 } |
Or perhaps (I only let through non-empty objects; the \S
matches anything that’s not whitespace):
1 |
PS> "2796BAE63F1801E277261BA0D77770028F20EEE4" -split "([a-z0-9]{2})" | ?{ $_ -match '\S' } |
Using any one of these I can now properly -join
:
1 2 |
PS> ("2796BAE63F1801E277261BA0D77770028F20EEE4" -split "([a-z0-9]{2})" | ?{ $_.length -ne 0 }) -join " " 27 96 BA E6 3F 18 01 E2 77 26 1B A0 D7 77 70 02 8F 20 EE E4 |
And finally what I set out to get in the first place:
1 2 3 4 5 6 7 8 9 10 |
PS> Get-ChildItem Cert:\LocalMachine\Root | ft @{Name="Thumbprint"; Expression={($_.Thumbprint -split "([a-z0-9]{2})" | ?{ $_.length -ne 0 }) -join " " }},Subject -AutoSize Thumbprint Subject ---------- ------- D5 65 8E F7 00 F9 B4 C0 CC DB 09 5E 49 1E F4 B8 4D DD 4A 09 CN=LONSDC01.cloudapp.net CD D4 EE AE 60 00 AC 7F 40 C3 80 2C 17 1E 30 14 80 30 C0 72 CN=Microsoft Root Certifi... BE 36 A4 56 2F B2 EE 05 DB B3 D3 23 23 AD F4 45 08 4E D6 56 CN=Thawte Timestamping CA... A4 34 89 15 9A 52 0F 0D 93 D0 32 CC AF 37 E7 FE 20 A8 B4 19 CN=Microsoft Root Authori... 8F 43 28 8A D2 72 F3 10 3B 6F B1 42 84 85 EA 30 14 C0 BC FE CN=Microsoft Root Certifi... <snip> |
Update: While writing this post I discovered one more method. Only let through objects that exist (so obvious, why didn’t I think of that!):
1 |
PS> "2796BAE63F1801E277261BA0D77770028F20EEE4" -split "([a-z0-9]{2})" | ?{ $_ } |
Also check out this wiki entry for the Split()
method to the String
object. Doesn’t work with regular expressions, but is otherwise useful. Especially since it can remove empty entries by default.
Update2: See this follow-up post for a typo in my regexp above as well as an alternate (simpler!) way of doing the above.