Search code examples
c#rsaprivate-key

RSA/ECB/PKCS1Padding C# Decyription Error String To PrivateKey


I'm getting an error in Private Key conversion, I can't decrypt. Error: System.InvalidCastException: Could not cast object of type 'Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair' to type 'Org.BouncyCastle.Crypto.AsymmetricKeyParameter'.

When I convert it to AsymmetricCipherKeyPair type, the type does not match in the bottom line. I am waiting for your help.

    static void Main()
        {
            var plainData = "plain_text";
            RSA publicKeyEncryptor = getRSAPublic(@"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlYB5JrwA9fMxZxTRhG0NnKRwJizMZGJNq/xFfFxaEmKp3O6vZgsZMlFTi2kSC++yR/KriGKuGgbIYrgomn7BueoooAw5KLVO9CKKtNyQgg28vdOBbnQqljA+KID0PouAD8MqpDk9opi41zeEQPOSkAUsq5sHMptG7h9cgj0mNr2c4ffNolHAhPsrZVtGYtswhtznDkG463VOKLAmDLDeY9bASUsQXFOY+Em93GHFjStgZSTIEBof6HbUqIQf2rGjuPYCQsB/94BFma58epGz12zUPwKFMuxg89wbLOCjyAkocgS9zDnwKr7DVv08GmCUVVqI6ySzbWpKhiqWQvz4hwIDAQAB");
            var plainBytes = Encoding.ASCII.GetBytes(plainData);
            string encryptedPayload = System.Convert.ToBase64String(publicKeyEncryptor.Encrypt(plainBytes, RSAEncryptionPadding.Pkcs1));
         
            RSA privateKeyDecyrpt = getRSAPrivate();
            var y = privateKeyDecyrpt.Decrypt(Encoding.ASCII.GetBytes(encryptedPayload), RSAEncryptionPadding.Pkcs1);
            Console.WriteLine(encryptedPayload);
        }
        public static RSA getRSAPublic(string publicKey)
        {
            string publicKeyPem = $"-----BEGIN PUBLIC KEY-----\r\n{ publicKey }\r\n-----END PUBLIC KEY-----\r\n";
            var pemReader = new PemReader(new StringReader(publicKeyPem));
            AsymmetricKeyParameter keyPairRaw = (AsymmetricKeyParameter)pemReader.ReadObject();
            RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaKeyParameters)keyPairRaw);
            RSA rsaObj = System.Security.Cryptography.RSA.Create();
            rsaObj.ImportParameters(rsaParams);
            return rsaObj;
        }

        public static RSA getRSAPrivate()
        {
            string privateKeyPem = @"-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAlYB5JrwA9fMxZxTRhG0NnKRwJizMZGJNq/xFfFxaEmKp3O6v
ZgsZMlFTi2kSC++yR/KriGKuGgbIYrgomn7BueoooAw5KLVO9CKKtNyQgg28vdOB
bnQqljA+KID0PouAD8MqpDk9opi41zeEQPOSkAUsq5sHMptG7h9cgj0mNr2c4ffN
olHAhPsrZVtGYtswhtznDkG463VOKLAmDLDeY9bASUsQXFOY+Em93GHFjStgZSTI
EBof6HbUqIQf2rGjuPYCQsB/94BFma58epGz12zUPwKFMuxg89wbLOCjyAkocgS9
zDnwKr7DVv08GmCUVVqI6ySzbWpKhiqWQvz4hwIDAQABAoIBAEJFR+8Gqbpcykpy
bQmxubX1Io2ZkCTzepDBbB/bZEYAHGIGIBQw2UN3z3vd4JUP9Mx14tm7PIfm987i
6YTKqZ97D/UaVgAYlt4brbbMivZLlp3i8t3+ep5G1lboCtzqw6K5Fd7kTNEVt+IX
BvYvwok68flD6GXjdQa7Oiu1ZYofxXOBg84RDWu6E6edDj/XaaX12WOYaQ4p6zDn
jyYNMiYYkKoUI1a884cN50WAAIGs0n3TxgJGXZa0n/Y3CpvuphAoHPQQs7ZyJPlP
k29gaFXdotzv1TDKk0I+eTIlonMl1EyW0wDPvfMuV7EYNNfmtmqrT3OWkOpUU8fO
9eDKhukCgYEA5nlVlTKAx5LsKI3KGRQF3jiWAaQAUKoON68Sx47fSJSv317QyZqM
qbQTLz5vSytbTyHhgIEc2dtdRbl7MYkvvzaizjPDEHEJSwlTmnzt81qGYtjNGC+j
tz6Bx5MGDE8Ax3ls60Lm0uH9TMQyJZWTepZGght5WXP5NpmzJ6zG7D0CgYEApg9S
zZyMN1rNtcz6Pqaqll33hchIQd+vh2LLKkHAoQP93oWtipxyT08yr4tQ5ke3nwjj
onIt6KR0U2aSIv9OUwXw2cSwghCIqTKmtont88WXYh9zRtnZ+U0An9r3x+fr7e8y
wpk7lFPP840pzQQjyEQ2s3woMlssqOiS6SyGMBMCgYB04KVBEypxixWN/1G05A2R
wxp3XIb4YTTykisw3khnU1fZLAkvo9ufl/1+oOfps+QLPkBQXamW5YLogAZ0eYCo
NHndnixW4yv2TJWEK8Sz+31ZFV702/vnSqCf5/RSO6JGhlJxAC10VjyROJHBs5fl
u92nz2z7qy9/u/Q5s4nxdQKBgAx6qFFVS2A5ja302nVs1vL32ssN8wgoRCubbAMf
79bp0uEvEIyTFzAIlpmEka7MgusLovepNvP9r9Q4qBDDOOKaVrA2zMDpdyun58ld
8ijYl3jDPkl7w5qtg7d/oBFAx4UY7aqcE1MhPUZjPFnwzrOVFLtGQEsQePm0iJ3H
P8pLAoGAUCC6KxGF20y0uBnSLS2q3iqAqZNO57ZLnJRAscsViNEhqn4G5OZbcANa
RsyFluCwjuKFg9yW9s6ZKzjPXsAEWTyXpayICSG4gJBRfdzUol5Sjo9JweqMhiVh
5G9uBYx3+kEpYNvJDcYK89HQ3fAcfeZ1o9sXYtwccOulSQ5euAE=
-----END RSA PRIVATE KEY-----";
            var pemReader = new PemReader(new StringReader(privateKeyPem));
            AsymmetricKeyParameter keyPairRaw = (AsymmetricKeyParameter)pemReader.ReadObject();
            RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaKeyParameters)keyPairRaw);
            RSA rsaObj = System.Security.Cryptography.RSA.Create();
            rsaObj.ImportParameters(rsaParams);
            return rsaObj;
        }

Solution

  • The code essentially contains casting-related bugs that are most easily identified during debugging by determining the object types:

    I'm getting an error in Private Key conversion, I can't decrypt. Error: System.InvalidCastException: Could not cast object of type 'Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair' to type 'Org.BouncyCastle.Crypto.AsymmetricKeyParameter'.

    You can't import the private key 1:1 like the public key, because both have different formats. The PemReader returns a different object type in the case of the private key, namely AsymmetricCipherKeyPair, which you cannot cast into an AsymmetricKeyParameter. This is what the error message says. So it must be:

    AsymmetricCipherKeyPair keyPairRaw = (AsymmetricCipherKeyPair)pemReader.ReadObject();
    

    When I convert it to AsymmetricCipherKeyPair type, the type does not match in the bottom line.

    You need to modify this line as well. Here you have to pass a keyPairRaw.Private that must be cast to RsaPrivateCrtKeyParameters:

    RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaPrivateCrtKeyParameters)keyPairRaw.Private);
    

    With these changes the import of the private key works.


    Another bug is in the decryption. The ciphertext is Base64 encoded during encryption, therefore it must be Base64 decoded during decryption and not ASCII encoded, i.e. correct is:

    var decrypted = privateKeyDecyrpt.Decrypt(Convert.FromBase64String(encryptedPayload), RSAEncryptionPadding.Pkcs1);
    

    Keep in mind that the options for importing keys in .NET are highly dependent on the version. There are versions where you can import PEM keys out-of-the-box (e.g. as of .NET 5), so that BouncyCastle is not needed.