Decrypting with RSA encryption in VB.NET

2019-02-27 07:54发布

问题:

I created a public and private key using openssl in the cmd line of a linux machine using the following commands:

openssl genrsa -out rsa_1024_priv.pem 1024
openssl rsa -pubout -in rsa_1024_priv.pem -out rsa_1024_pub.pem

Now I want to be able to decrypt data in VB.NET that was already encrypted with the public key.

I am using the method found in the MSDN documentation for decryption. I am trying to set the RSAParameters to pass in to the RSADecrypt method, but I'm not really sure what goes into each field.

Whenever I try running the code I get the following error:

System.Security.Cryptography.CryptographicException: Bad Data. at System.Security.Cryptography.CryptographicException.ThrowCryptographicExce ption(Int32 hr) at System.Security.Cryptography.Utils._ImportKey(SafeProvHandle hCSP, Int32 k eyNumber, CspProviderFlags flags, Object cspObject, SafeKeyHandle& hKey) at System.Security.Cryptography.RSACryptoServiceProvider.ImportParameters(RSA Parameters parameters) at Decryptor.Module1.RSADecrypt(Byte[] DataToDecrypt, RSAParameters RSAKeyInf o, Boolean DoOAEPPadding) in C:\Users\yhorowitz\AppData\Local\Temporary Projects \Decryptor\Module1.vb:line 30

The error is being thrown on this line RSA.ImportParameters(RSAKeyInfo) in the RSADecrypt method

This is the code I have so far:

Imports System.Security.Cryptography
Imports System.Text

Module Module1
    Dim encoder As New UTF8Encoding

    Sub Main()
        Dim MyPrivateKey As String = "" 'Removed
        Dim MyPublicKey As String = "" 'Removed
        Dim MyModulus as String = "" 'Removed

        Dim DataToDecrypt() As Byte = Convert.FromBase64String("CourNHBC55DgGtBZU6Ahtm0emywGi5hWo5/h9zD6A/NASKMpZ/A5GCU8G5TNTMgJQxVFsabbdeuNhf4VQzBuFqewuD8eD7MwpJvjmuPfrs7xcEzOrwbF549v0PHv/nfN+03winW6s3ecnv1dm0TctQgqsauEuvXu2PMVEFivqPo=")

        Dim params As RSAParameters = New RSAParameters()

        params.Exponent = Convert.FromBase64String(MyPublicKey)
        params.D = Convert.FromBase64String(MyPrivateKey)
        params.Modulus = Convert.FromBase64String(MyModulus)

        Console.WriteLine(Convert.ToString(RSADecrypt(DataToDecrypt, params, False)))
        Console.Read()
    End Sub

    Public Function RSADecrypt(ByVal DataToDecrypt() As Byte, ByVal RSAKeyInfo As RSAParameters, ByVal DoOAEPPadding As Boolean) As Byte()
        Try
            Dim decryptedData() As Byte
            'Create a new instance of RSACryptoServiceProvider.
            Using RSA As New RSACryptoServiceProvider(1024)
                RSA.ImportParameters(RSAKeyInfo)
                decryptedData = RSA.Decrypt(DataToDecrypt, DoOAEPPadding)
            End Using
            Return decryptedData
        Catch e As CryptographicException
            Console.WriteLine(e.ToString())
            Return Nothing
        End Try
    End Function
End Module

回答1:

Under the most strict of senses, the RSA algorithm requires

  • Public key (n (aka Modulus), e)
  • Private key (n, d)

And some libraries, like OpenSSL, will work with just the (n, e, d) triplet.

But Windows CAPI (and probably Windows CNG) pretty much ignores d, because it's much more efficient to do RSA using the Chinese Remainder Theorem (CRT).

So RSACryptoServiceProvider (and RSACng (net46+, netcoreapp10+), and RSAOpenSsl (netcoreapp10+)) all require a fully populated RSAParameters structure for private keys.

For public-only, you can set just Modulus and Exponent.

For private, you need to set all of the fields, and they must have the following characteristics:

  • Modulus[0] must not be 0.
  • D and Modulus must be the same number of bytes.
  • E is whatever it is, but E[0] must not be 0.
  • P, Q, DP, DQ, InverseQ must all be the same number of bytes, and that number must be exactly half the size of Modulus (round up, if it matters).

To line terms up from OpenSSL's RSA pretty-print to RSAParameters:

-----------------------------------
| OpenSSL         | RSAParameters |
-----------------------------------
| modulus         | Modulus       |
| publicExponent  | Exponent      |
| privateExponent | D             |
| prime1          | P             |
| prime2          | Q             |
| exponent1       | DP            |
| exponent2       | DQ            |
| coefficient     | InverseQ      |
-----------------------------------

For an example of converted data (on a key already disclosed as a test key), see https://github.com/dotnet/corefx/blob/193d663393b75f83a447a635523a6e84454d9482/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/TestData.cs#L179-L285, which is the same as this OpenSSL dump:

$ openssl rsa -in rsa1032.key -text -noout
Private-Key: (1032 bit)
modulus:
    00:bc:ac:b1:a5:34:9d:7b:35:a5:80:ac:3b:39:98:
    eb:15:eb:f9:00:ec:b3:29:bf:1f:75:71:7a:00:b2:
    19:9c:8a:18:d7:91:b5:92:b7:ec:52:bd:5a:f2:db:
    0d:3b:63:5f:05:95:75:3d:ff:7b:a7:c9:87:2d:bf:
    7e:32:26:de:f4:4a:07:ca:56:8d:10:17:99:2c:2b:
    41:bf:e5:ec:35:70:82:4c:f1:f4:b1:59:19:fe:d5:
    13:fd:a5:62:04:af:20:34:a2:d0:8f:f0:4c:2c:ca:
    49:d1:68:fa:03:fa:2f:a3:2f:cc:d3:48:4c:15:f0:
    a2:e5:46:7c:76:fc:76:0b:55:09
publicExponent: 65537 (0x10001)
privateExponent:
    00:9e:59:25:e2:ec:6c:bb:4a:83:f3:a1:19:37:b6:
    e2:9e:8c:64:78:65:2f:dc:fa:9d:d1:78:82:97:70:
    e2:53:e2:07:05:6d:32:01:c8:41:1c:13:f5:ef:da:
    ee:99:08:46:68:ae:4e:2e:d1:6c:1b:9e:e4:c7:fd:
    6e:51:73:14:2d:c5:9f:c6:45:a4:c2:e6:65:5d:ac:
    e6:71:b3:00:de:0d:7b:b5:2d:68:a8:60:26:c1:8f:
    02:47:26:e7:71:bd:04:81:99:44:2f:03:42:70:96:
    58:ef:f6:4a:e4:2e:a4:17:32:47:ec:d2:4a:86:29:
    9e:8b:9d:11:52:00:02:c8:f5:f1
prime1:
    0e:15:30:0a:9d:34:ba:37:b6:bd:a8:31:bc:67:27:
    b2:f7:f6:d0:ef:b7:b3:3a:99:c9:af:28:cf:d6:25:
    e2:45:a5:4f:25:1b:78:4c:47:91:ad:a5:85:ad:b7:
    11:d9:30:0a:3d:52:b4:50:cc:30:7f:55:d3:1e:12:
    17:b9:ff:d7:45
prime2:
    0d:65:c6:0d:e8:b6:f5:4a:77:56:fd:1c:cb:a7:6c:
    e4:1e:f4:46:d0:24:03:1e:e9:c5:a4:09:31:b0:73:
    36:cf:ed:35:a8:ee:58:0e:19:db:85:92:cb:0f:26:
    6e:c6:90:28:eb:9e:98:e3:e8:4f:f1:a4:59:a8:a2:
    68:60:a6:10:f5
exponent1:
    0d:9d:b4:be:7e:73:0d:9d:72:a5:7b:2a:e3:73:85:
    71:c7:c8:2f:09:a7:be:b5:e9:1d:94:aa:cc:10:cc:
    be:33:02:7b:3c:70:8b:e6:8c:c8:30:71:ba:87:54:
    5b:00:78:2f:5e:4d:49:a4:59:58:86:b5:6f:93:42:
    81:08:48:72:55
exponent2:
    0c:f6:fb:dd:e1:e1:8b:25:70:af:21:69:88:3a:90:
    c9:80:9a:eb:1b:e8:7d:8c:a0:b4:bd:b4:97:fd:24:
    c1:5a:1d:36:dc:2f:29:cf:1b:7e:af:98:0a:20:b3:
    14:67:da:81:7e:e1:8f:1a:9d:69:1f:71:e7:c1:a4:
    c8:55:1e:df:31
coefficient:
    01:0c:e9:93:6e:96:fb:ad:f8:72:40:cc:41:9d:01:
    08:1b:b6:7c:98:1d:44:31:4e:58:58:3a:c7:fe:93:
    79:ea:02:72:e6:c4:c7:c1:46:38:e1:d5:ec:e7:84:
    0d:db:15:a1:2d:70:54:a4:18:f8:76:4f:a5:4c:e1:
    34:eb:d2:63:5e