Yesterday I released another version of PowerShell PKI module v3.1.

Though, this release is not that big like v3.0. Only 1 (one!) new command is added (Get-EnterprisePKIHealthStatus) and various bug fixes (as usually). On the other hand it includes very important things which are hidden behind the scene.

The project is growing and I have to battle hard with poor design decisions I made previously. Of course, I could break everything and make it as per all guidelines. However, it is too late, 3000 downloads for the past 7 months is not a joke and I can’t simply break it.

Next sections will cover some development details, so you can scroll down to the end of post to get the right link :)

ASN.1 type system

First, I almost polished my ASN.1 parser, it is now rewritten by using more efficient code. For one function I was forced to look for some help on StackOverflow. The lesson is learned and now I have fairly efficient code where it matters most. You can ask, why I pay so much attention to that ASN.1, while even PKI administrators (not to tell about other systems administrators and PowerShell users) have a very-very little knowledge about ASN and do not use it directly. The truth is that entire Internet PKI communication system is based on ASN.1. What is your digital certificate? It is ASN.1. What is your certificate request? It is ASN.1. What is PKCS#X? It is ASN.1. An ability to read, decode, encode ASN.1 data is a “must have” for any PKI developer. CryptoAPI has a rich support of ASN.1, but .NET do not. Although I like CryptoAPI as it can do things in few lines and very quickly while managed implementation is bigger and slower, I decided to move common classes to managed code. Mostly because of unmanaged memory management. When you create CRL object, its handle is not released in normal ways and users do not release them as well.

I’m planning to extend my own ASN.1 type system support by adding classes for each universal tag. Currently, only two classes are exposed:, but there are a bit more (currently marked private):


In addition, entire ASN namespace will be removed from PKI.Core.dll library to its own assembly, because I’m actively using it in other projects.

X509Certificates namespace

I’m constantly adding new certificate/CRL extension support (both, Microsoft-specific and Internet PKI) in the X509Certificates namespace to provide ease access to extension data. Worth to mentioned that I rewrote X509CRLDistributionPointsExtension class to fully match RFC5280 specifications. Now this class can decode partitioned and non-standard (though, within RFC standard) CDP extension. Although, this extension now looks a bit complicated, a shortcut method GetURLs helps you to easily access URLs in the extension.

Check this namespace with each release, maybe you can find there something useful for you.

Another feature (planned) is to add an ability to read certificate properties when they are installed in the store. Sometimes they may have interesting details. For example, information about private key, enrollment options and so on:


Note that not all details are shown in the certificate UI window. I’m thinking about the best way to implement it, but would be a great feature


With this release, I officially published an official project development roadmap. It reflects my personal vision of module extension with added community requests I consider important or interesting.


>> PowerShell PKI v3.1 <<

Share this article:



Is there a silent install option for PSPKI?

I need PSPKI for it's ability to create the "Remote Desktop Authentication -" application policy in AD. I need to fully script this and would need to install PSPKI silently.

I tried using these other methods to create the policy with no success:

1. Certutil.exe -f -oid "Remote Desktop Authentication" 1033 3

    This only creates a local name association, not an AD object.

2. "System.Security.Cryptography.Oid" doesn't appear to have a "register" capability, it is read only

Vadims Podans

take a look at Register-ObjectIdentifier command:


That works, but the PSPKI module must be installed to use this correct? And PSPKI has no silent install that i can find.

Vadims Podans

You don't need to install entire module for that operation. You can copy PKI.Core.dll library, attach it to PowerShell session (Add-Type -Path $path\PKI.Core.dll) and run the Register static method on Oid2 class. I wrote an extended class to work with OIDs.

In your case, the command would look as: [Security.Cryptography.Oid2]::Register("","Remote Desktop Authentication","ApplicationPolicy",$true,$LocaleId,$null)


Perfect. Thanks for you help Vadims! All the PKI knowledge on this site has helped immensely.

Also, I saw that if you install PSPKI using the GUI, then copy "C:\Program Files\Sysadmins LV\PowerShell\Modules\PSPKI" folder to "C:\Windows\system32\WindowsPowerShell\v1.0\Modules\PSPKI" on a second machine, you can run "Import-Module PSPKI" to install the entire module. Is this a valid alternative to running the GUI install on every machine?

Vadims Podans

Yes, you can copy PSPKI folder to %windir%\System32\WindowsPowerShell\v1.0\Modules folder. Actually, it is what I do with the installer (when appropriate option is selected). Installer is more convenient for end users and performs required operations when you install a new version.


This will work for me, thanks again Vadims.



Would this module work on v4 powershell. on server 2012,

Vadims Podans

Yes, PowerShell 3 and PowerShell 4 are fully supported. However, PowerShell 5 is not yet supported (I haven't tested).


Cmdlets for adding/removing CEP/CES don't work on 2012/R2 - checks strict for 2008R2 and removing the check from individual ps1 files doesn't help.

Additionally something wrong with setting foreground color in 2012R2:



PS C:\Windows\system32> C:\admin\AddRemoveCEP.ps1

At C:\admin\AddRemoveCEP.ps1:148 char:12

+ ("-" * 50) -ForegroundColor Green

+ ~~~~~~~~~~~~~~~~

Unexpected token '-ForegroundColor' in expression or statement.

At C:\admin\AddRemoveCEP.ps1:148 char:29

+ ("-" * 50) -ForegroundColor Green

+ ~~~~~

Unexpected token 'Green' in expression or statement.

At C:\admin\AddRemoveCEP.ps1:204 char:12

+ ("-" * 50) -ForegroundColor Green

+ ~~~~~~~~~~~~~~~~

Unexpected token '-ForegroundColor' in expression or statement.

At C:\admin\AddRemoveCEP.ps1:204 char:29

+ ("-" * 50) -ForegroundColor Green

+ ~~~~~

Unexpected token 'Green' in expression or statement.

+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException

+ FullyQualifiedErrorId : UnexpectedToken

Vadims Podans

These commands are available on Windows Server 2008 R2 only. In newer OS versions these commands are not installed, because there are built-in MS cmdlets: Install-AdcsEnrollmentPolicyWebService, Install-AdcsEnrollmentPolicyWebService, Uninstall-AdcsEnrollmentPolicyWebService and Uninstall-AdcsEnrollmentWebService. To prevent command overlap, I decided to exclude my implementation where native exist.


Is there a way to fetch the thumbprint/signature algorithm? I do not see that option from the 'Get-IssuedRequest' output so was wondering if there was a separate cmdlet for this information. I would like to see all of my SHA1 and SHA2 certificates.Thanks!

Vadims Podans

Unfortunately, there is no such option, because this information is not stored anywhere in the database. The only way is to examine SignatureAlgorithm property of each issued certificate.



Is there a way to silently install the .exe on codeplex or use an answer file?  I want to install this module on servers via config management instead of copying the module directory.  I'm trying to do an unattended complete install for all users.

Any help would be appreciated.

Vadims Podans

> Is there a way to silently install the .exe on codeplex or use an answer file?

not yet. I will try to add this option in the next release.


In case you're interested you can use ".\pspki.exe addlocal=all /qn" to silently install all features.

Kim Kruse Hansen


I am trying to install pspki 3.2.6 unattended on 3 remote PKI servers. I copy the installation exe ps pki v3.2.6 to a temp directory on the remote computer and then through a pssession call the installation program

function InstallPrereqs()


set-location 'c:\temp'

& '.\ps pki v3.2.6.exe' /qn addlocal=all allusers=1 /L*V c:\logs\pspki.log




$session = New-PSSession -cn $server -Credential $creds -Authentication Credssp

Invoke-Command -Session $session -ScriptBlock ${function:InstallPreReqs}

Remove-PSSession -session $session

I can see through procmon , that pspki starts up but it doesn install anything , nor does it create a logfile.

If I run the install command locally , then eveything works and I get a logfile.

So how do I install pspki remote ?






Vadims Podāns

I'm sorry, but I can't tell why it doesn't work in remote session. I never tested such scenario.

On the other hand, the purpose of the module is to avoid interactive logons to CA server in order to manage it. Instead, it is supposed to be installed on an admin computer with installed RSAT component. All server side commands support remote CA, so there is no big reason to install the module directly on CA server.


Hello Vadims,

I am using this package for fast revocation checking. I was doing some tests and I have this case below. Can you verify if that is the expected behaviour?

- Certificate is valid, not revoked

- Sub CA is offline

- Base CRL and Delta CRLs are expired

- OCSP revocation check fails with "certutil -verify" command

- pspki commandlet returns "Good" for the revocation response




Vadims Podāns

Please, post your question on Prject Web Site:

Post your comment:

Please, solve this little equation and enter result below. Captcha