2

Been going round in circles with this.

Spent a long time reading and researching. I need to sign a string with an X.509 certificate.

The following method should work but doesn't

Imports System.Security.Cryptography
Imports System.Security.Cryptography.X509Certificates
Imports System.Text

Public Class CertificateSigner
    Public Function SignStringWithCertificate(inputString As String, certificateFilePath As String, certificatePassword As String) As String
        Try
            ' Load the certificate from file
            Dim certificate As New X509Certificate2(certificateFilePath, certificatePassword)

            ' Get the private key from the certificate
            Dim privateKey As AsymmetricAlgorithm = certificate.PrivateKey

            ' Create a new instance of the RSACryptoServiceProvider class
            Dim rsaProvider As RSACryptoServiceProvider = CType(privateKey, RSACryptoServiceProvider)

            ' Convert the input string to bytes
            Dim inputBytes As Byte() = Encoding.UTF8.GetBytes(inputString)

            ' Sign the data using the private key
            Dim signatureBytes As Byte() = rsaProvider.SignData(inputBytes, CryptoConfig.MapNameToOID("SHA256"))
            ' Convert the signature to a base64-encoded string
            Dim signatureBase64 As String = Convert.ToBase64String(signatureBytes)

            Return signatureBase64
        Catch ex As Exception

            Debug.Print (ex.Message )
            ' Handle any exceptions here
            Return Nothing
        End Try
    End Function
End Class

The problems occur at rsaProvider.SignData(inputBytes, CryptoConfig.MapNameToOID("SHA256")) where the exception gives me Invalid algorithm specified.

Everything I've read says that should work.

Why is this failing please?

Vb.Net target framework is 4.6.1

Tym
  • 89
  • 2
  • 14
  • Would setting `Switch.System.Security.Cryptography.*` config flags work? As here: https://stackoverflow.com/a/56682656/1075282 – Renat Aug 14 '23 at 14:46
  • No difference, also... this is a vb.net DLL not a web application. – Tym Aug 14 '23 at 15:10
  • even changing it to ```Dim signatureBytes As Byte() = rsaProvider.SignData(inputBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)``` I get the same error ```Invalid algorithm specified.``` – Tym Aug 14 '23 at 15:18

1 Answers1

3

You cannot use SHA256 algorithm with legacy CryptoAPI 1.0 which is used by your code. Starting with .NET Framework 4.6, you can (and should) use CAPI2 capabilities, including SHA256 algorithm. You have to change the way how you obtain private key object. X509Certificate2.PrivateKey is de-facto obsolete and shall not be used anymore. Use X509Certificate2.GetRSAPrivateKey extension method to retrieve private key using CAPI2. Then your code will look like this (only relevant parts are shown):

' Get the private key from the certificate
Dim privateKey As RSA = certificate.GetRSAPrivateKey()

' Convert the input string to bytes
Dim inputBytes As Byte() = Encoding.UTF8.GetBytes(inputString)

' Sign the data using the private key
Dim signatureBytes As Byte() = privateKey.SignData(inputBytes, "SHA256", RSASignaturePadding.Pkcs1)
Crypt32
  • 12,850
  • 2
  • 41
  • 70
  • Thanks @crypt32. However, I'm getting an overload resolution error on SignData, Needed to change to Dim signatureBytes As Byte() = privateKey.SignData(inputBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1) – Tym Aug 15 '23 at 08:23