I need to hash input data with SHAKE256 (found SeriesOne.CORE package for this) and then generate a digital signature for it based on RSA algorithm.
The problem is that the default RSACryptoServiceProvider does not support any of the SHA3 hashing functions. Methods like RSACryptoServiceProvider.SignHash(), RSACryptoServiceProvider.VerifyData() and RSACryptoServiceProvider.VerifyHash() require hashing algorithm specification. Is there any workaround or maybe I miss something?
.NET currently does not natively support SHA-3 (and thus also not the SHA3 variant SHAKE256), see e.g. here.
Therefore, the native C# methods for signing/verifying do not work either (even the
SignHash()method throws a runtime exception if the already hashed data is passed, the digest is specified via the OID, and RSASSA-PKCS1-v1_5 is used, i.e. if no explicit hashing would be required at all: The specified OID (2.16.840.1.101.3.4.2.12) does not represent a known hash algorithm).Ultimately, therefore, not only the hashing, but for the entire signing process a third-party provider must be used. One possibility is BouncyCastle (as suggested in Maarten Bodewes' comment). For .NET6 BouncyCastle.NetCore should be applied.
For RSASSA-PKCS1-v1_5 the
RsaDigestSignerclass is to be used with the following in mind:RSADigestSignerclass does not take the SHAKE digests into account, so theRSADigestSigner(Digest digest)ctor will not work and theRSADigestSigner(Digest digest, ASN1ObjectIdentifier digestOid)ctor must be used, i.e. the OID (2.16.840.1.101.3.4.2.12) must be explicitly specified. This can be done either withnew DerObjectIdentifier("2.16.840.1.101.3.4.2.12")or withNistObjectIdentifiers.IdShake256. The DER encoding of theDigestInfovalue is thus3031300D060960864801650304020C05000420(which differs from the SHA56 value only in the 15th byte with 0x0c instead of 0x01, s. RFC8017).A possible implementation is:
For RSASSA-PSS the
PssSignerclass is to be used. The following implementation applies SHAKE256 for PSS and MGF1 digest, and as salt length 32 bytes (but there are also constructors to set the parameters explicitly):