ebekker / ACMESharp

An ACME client library and PowerShell client for the .NET platform (Let's Encrypt)
https://pkisharp.github.io/ACMESharp-docs/
1.21k stars 184 forks source link

Externalize JWS cryptographic functions into a Provider #128

Open ebekker opened 8 years ago

ebekker commented 8 years ago

In some cases we need to be able to control the cryptographic primitives that are used to support the JWS signing operations, for example, in #126 there is a need to use a FIPS compliant crypto provider in secure environments, or if we want to support alternate signing algorithms.

To do this cleanly, we should externalize all the crypto-related operations from the JWS operations so they can be pluggable with different providers if necessary.

bseddon commented 8 years ago

I wonder if its necessary for you to externalize the functions. You use the function SHA256.Create() to create a hash algorithm instance. You can also use this function with a string parameter that specifies the cryptographic implementation to use. For example:

SHA256.Create("System.Security.Cryptography.SHA256Cng");

which is synonymous with:

HashAlorithm.Create("System.Security.Cryptography.SHA256Cng");

This could mean that by adding an extra parameter to an existing object - say an identifier or profile - you could allow a user the ability to change the algorithm(s) to be used without too much code reorganization though you may have other reasons to want to reorganize. Of course there would still be some change to the Jws functions because at the least it would be necessary for them to access the string parameter which may mean passing an object or the string value along.

There's more discussion of this aspect of the Microsoft cryptography suite on StackOverflow

ebekker commented 8 years ago

@bseddon, thanks for digging further into this -- that led me to some alternatives for the original issue in #126.

bseddon commented 8 years ago

I added a comment to #126 to mention it seems it is possible to change the default SHA256 algorithm on-the-fly from PowerShell so a user should be able to change to the FIPS implementation themselves:

[System.Security.Cryptography.CryptoConfig]::AddAlgorithm([System.Security.Cryptography.SHA256Cng], "System.Security.Cryptography.SHA256")

A suggestion is to add a parameter called something like -FIPS to a convenient command. This would invoke the C# equivalent code so a user does not have to remember the syntax.

ebekker commented 8 years ago

Your suggestion is great, but the -FIPS flag is problematic because what it means could change (FIPS standards change over time). Also, FIPS-compliance would be more than just adjusting the JWS signing algorithm, there are specific algorithms and key sizes that would need to be used later in the process like when generating the private key and CSR.

For now, I think your solution will definitely address the original issue and anything similar in nature, and I can look down the line how to clean up the suite of crypto operations in general.

bseddon commented 8 years ago

Fair points

bseddon commented 8 years ago

Your points make me realize I have no appreciation of the places various crypto functions are used or which functions are called. How about calling them out (the functions used not where they are called) in the Wiki so if anyone else runs into this they know which defaults need to be modified?

ebekker commented 8 years ago

Most of the functions are actually all concentrated in the CertProvider base class and the derived concrete implementations such as OpenSslCliProvider.

This was necessary to be able to swap out different implementations for the cert-related operations, and these are all related to the crypto functions that are used whenever someone is dealing with any certificate request/issuance/management functions, not just ACME/Let's Encrypt (i.e. if you're dealing with any CA).

This issue is actually dealing with the underlying JWS-related operations that are used to support the ACME protocol itself, which is separated out. While cert operations rely on OpenSSL as it's primary/default provider, the JWS stuff is based on .NET framework primitives because they are simpler and more readily available in the framework.

The reason that the FIPS violation was detected for the JWS stuff in #126 is actually because it's using the native .NET/Windows crypto calls, whereas the default cert implementations are calling out to the OpenSSL CLI which I am almost sure are not checking to see if the hosting system is hardened for FIPS compliance.

I'll put a link in the FAQ to reference this ticket for any questions about which crypto functions are used in ACMESharp.