Hello everyone!
Yesterday I pushed new PSPKI release with version number v3.3.0. New version is even more stable and even more powerful. More technical change list is moved to dedicated article: Release notes for PSPKI v3.3.0. In this (and, possibly next) blog post I would like to outline major changes/improvements to this release.
I bet that ADCS database access is one of the most popular features people love in my module. And there are reasons: I put a lot of efforts to simplify access to CA database and provide flexible filter options. For example, get certificates that will expire in next 30 days:
PS C:\> Get-CertificationAuthority dc2* | Get-IssuedRequest -Filter "NotAfter -ge $(Get-Date)", "NotAfter -le $((Get-Dat e).AddDays(30)) RequestID : 1971 Request.RequesterName : CONTOSO\DC2$ CommonName : dc2.contoso.com NotBefore : 2018.04.26. 12:52:48 NotAfter : 2018.05.10. 12:52:48 SerialNumber : 659bb31735250f080004000007b3 CertificateTemplate : OCSP Response Signing RowId : 1971 ConfigString : dc2.contoso.com\contoso-DC2-CA Table : Request RequestID : 1965 Request.RequesterName : CONTOSO\DC2$ CommonName : contoso-DC2-CA-Xchg NotBefore : 2018.04.08. 17:36:57 NotAfter : 2018.05.13. 17:46:57 SerialNumber : 659bb31735250f080004000007ad CertificateTemplate : CAExchange RowId : 1965 ConfigString : dc2.contoso.com\contoso-DC2-CA Table : Request
The output is pretty informative, it shows most useful details about certificate to help administrators to identify them on target machines and services and take necessary actions if necessary. This presentation is developed by using PowerShell synthetic properties (via Add-Member cmdlet). However, they exist only in PowerShell. When using this object in .NET library, these properties are cleared and only basic properties remain: RequestRow Properties. I have plans to move CA database access code to C# library and this behavior may be removed due to incompatibility. In order to prepare to C# I’ve added a dictionary that holds all database row properties (columns) in this dictionary:
PS C:\> $rows[0] RequestID : 1971 Request.RequesterName : CONTOSO\DC2$ CommonName : dc2.contoso.com NotBefore : 2018.04.26. 12:52:48 NotAfter : 2018.05.10. 12:52:48 SerialNumber : 659bb31735250f080004000007b3 CertificateTemplate : OCSP Response Signing RowId : 1971 ConfigString : dc2.contoso.com\contoso-DC2-CA Table : Request Properties : {[RequestID, 1971], [Request.RequesterName, CONTOSO\DC2$], [CommonName, dc2.contoso.com], [NotB efore, 2018.04.26. 12:52:48]...} PS C:\> $rows[0].Properties Key Value --- ----- RequestID 1971 Request.RequesterName CONTOSO\DC2$ CommonName dc2.contoso.com NotBefore 2018.04.26. 12:52:48 NotAfter 2018.05.10. 12:52:48 SerialNumber 659bb31735250f080004000007b3 CertificateTemplate ...311.21.8.149510.7314491.15746959.9320746.3700693.37.1.32 CertificateTemplateOid ...15746959.9320746.3700693.37.1.32 (OCSP Response Signing)
You can find new property called Properties. It is key-value dictionary where key is column name and value is column value. This is now preferred and recommended way to access database row properties. Access syntax is simple and similar to a way how you access properties in Active Directory entries:
PS C:\> $rows[0].Properties["SerialNumber"] 659bb31735250f080004000007b3 PS C:\> $rows[0].Properties["CertificateTemplate"] 1.3.6.1.4.1.311.21.8.149510.7314491.15746959.9320746.3700693.37.1.32 PS C:\> $rows[0].Properties["NotBefore"] ceturtdiena, 2018. gada 26. aprili 12:52:48 PS C:\>
Just put square brackets and type column name in quotes. Column name matches the column name retrieved from CA database schema.
When accessing database row properties, property name is case sensitive!
I will try to keep existing presentation experience, but you may expect that it will be removed in future versions if I won’t be able to save it.
In the past, I had a MessageSignature class that was used to sign and verify digital signatures. It consist of two static methods with basic CNG support. The code itself contains a bunch of static methods and claimed CNG support.
However, after real-world evaluation several unfortunate details were discovered. Major issues were:
Eventually, it worked in “something does work, something does not and who knows what exactly works” manner. It was really old and crappy code. Other code in my library suffered from these issues. I made several attempts to solve them with minimum efforts and all failed, this piece of code was unsalvageable. After spending countless hours by smoking MSDN documentation, trial and error concepts, I finally developed new design for signing operations. With really TRUE (yes, it is bold statement) CNG and related stuff support. New design cost me around 1,500 lines of code to make it reliable from usage perspective and good from design perspective. Also, I was able to do some neat magic. New home for message signing is MessageSigner class. The usage is pretty simple:
There are few comments:
Step2: if your certificate is stored in legacy CSP, then you normally cannot use PSS padding, because it was added only in CNG key storage providers and is unavailable for legacy CSP. During MSDN documentation research I found a very interesting CryptoAPI function: NCryptTranslateHandle. The idea behind this function is to attempt to load private key from legacy CSP into CNG KSP. If this function succeeds, then you can use legacy key in any NCrypt*BlahBlahBlah function calls and support advanced features. For example, PSS padding in RSA signatures. After my tests, this function succeeds for all Microsoft legacy CSPs, so any software-based key from Microsoft legacy CSP can be translated to CNG and loaded in key storage provider. If you have custom CSP, this trick may not work.
Step4: old MessageSignature class didn’t have an option to construct final signature algorithm and caller was forced to do it for himself. Now, caller is free from this task and can pick up algorithm value from SignatureAlgorithm property.
Step5: this is a bit more sophisticated and makes sense for signed cryptography object generators. These generators create only TBS (To Be Signed) structure. In order to free them from algorithm identifier generation, an appropriate method was added.
Private key presence is checked only when calling SignData or SignHash methods. After first usage, the handle to private key is cached and no PIN prompts appear when signing other data. Private key cache is cleared after disposing the object.
Signature validation is straightforward as well:
When verifying the signature, public key is ALWAYS loaded into CNG key storage provider, thus allowing advanced capabilities, including RSASSA-PSS signature validation. Public keys are public and not tied to particular CSP/KSP (except for ECDSA keys, they are CNG-only) and can be loaded into any provider that supports particular public key algorithm.
Several versions ago I wrote an implementation to create/generate certificate revocation lists. However, due to crappy code in MessageSignature class, it never worked. After making new MessageSigner class, I was able to revisit the code and draw it again by utilizing new features. CRL generator is implemented in X509CrlBuilder class. You have two options to start from:
When using blank CRL, you can compose CRL file as per your needs. You can manually specify ThisUpdate, NextUpdate, Version and a list of revoked certificates. Issuer information is included upon hashing/signing CRL. Extensions are generated automatically.
When using existing CRL, only CRL version, CRL extensions and revoked certificate list is copied to the builder. You still can modify CRL values (except extensions, they are generated automatically). CRL extension modification will be implemented in future versions. At this moment, delta CRL generation is possible via existing Delta CRL object.
If necessary, you can set CrlNumberIncrement property to increment CRL sequential number.
That’s all for today. Other features, including API library restructuration vision will be posted in next posts.
Very cool :) Do you accept cryptocurrency donations?
> Do you accept cryptocurrency donations?
currently, I do not support any kind of donations. However, may ask in future to cover web site hosting expenses.
Post your comment:
Comments: