Re: CryptoAPI and private key /not public/ encryption with CryptEncrypt - can not use CryptHash* functions

From: Przemek Wasylko (wasylek_at_remove-me.megapolis.pl)
Date: 12/31/04


Date: Fri, 31 Dec 2004 02:15:38 +0100


"Alun Jones [MSFT]" <alunj@online.microsoft.com> wrote in message
news:OLJMTfc7EHA.3504@TK2MSFTNGP12.phx.gbl...

>
> I would guess that the most frequent answer would be "why would you do
> that?"
>

Well, I can tell you why would I do that. For one simple reason: .NET
implementation of RSACryptoServiceProvider is seriously flawed in way that
it disables me setting custom CSP parameters, eg PP_*PIN parameters. I would
like to use that class in conjunction with some kind of custom CSP and Smart
Card device to perfom xml signing _on_ device by means of using SignedXml
class. My code is supposed to run under NT Service process and, you must
agree, server side application can't show dialog box in order to request pin
that is needed to perform private key operations. I would like to silently
sign thousands of XML messages daily. But developers of
RSACryptoServiceProvider simply forgot to expose underlying CSP Handle for
applcilactions that would make use of it. CspParameters class gives no help
either: it allows to set several CSP params but it does not expose any
method to set all the provider & key parameters described in CryptoAPI (eg
WinCrypt.h). Shame on you MS, shame on you, that makes that class only a toy
not a really usable stuff. My further research went to SignedXml class and
RSAPKCS1SignatureFormatter class - the both take AsymmetricAlgorithm class
instance as a parameter. I would like to derive from RSA class (can't derive
from RSACryptoServiceProvider because it is sealed, grrr MS) but RSA class
lacks needed methods, because SignHash method is defined in
RSACryptoServiceProvider but not in RSA class, where I think, it should be.
What does SignHash do according to MSDN ? 'Computes the signature for the
specified hash value by encrypting it with the private key.' Whoa, that is
what I need to implement, but why declaration of that method is missing from
RSA class ? And guess what RSAPKCS1SignatureFormatter does when computing
signature ? It checks whether supplied AsymmetricAlgorithm instance is of
type RSACryptoServiceProvider. If that is true SignHash method is called.
Otherwise AsymmetricAlgorithm class instance is casted to RSA type and
DecryptValue(byte[]) method is called, where byte[] array represents
computed hash. As you can see DecryptValue is not given any parameter that
would tell which hash algorithm was used. I don't know why DecryptValue() is
called - maybe the intention of .NET Framework developers was to signal
implementer that private key operation is needed - for me not putting
SignHash method in base RSA class sounds like design flaw. And the last
note: RSACryptoServiceProvider does not implement DecryptValue() method.

But, as you said, performing private key encryption in CryptoAPI is not
possible.

I managed to get CSP handle using Reflection - that is not too elegant.

Just see class hierarchy
http://msdn.microsoft.com/library/en-us/cpref/html/frlrfsystemsecuritycryptographyrsacryptoserviceproviderclasstopic.asp

Best regards
Przemek