Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

System.PlatformNotSupportedException: Algorithm 'RC2' is not supported on this platform. #85019

Closed
SepuWeb opened this issue Apr 18, 2023 · 20 comments

Comments

@SepuWeb
Copy link

SepuWeb commented Apr 18, 2023

Description

I'm trying to convert my Xamarin App into new .NET MAUI.

This works in Xamarin:

string path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "/cert_with_key.pfx";
byte[] rawData= File.ReadAllBytes(path);
X509Certificate2 cert = new X509Certificate2(rawData, privKeyPSW); ----->this throw the following error

{System.Security.Cryptography.CryptographicException: The certificate data cannot be read with the provided password, the password may be incorrect.
---> System.PlatformNotSupportedException: Algorithm 'RC2' is not supported on this platform.

Steps to Reproduce

  1. Create a File > New .NET MAUI App
  2. Create a pfx file with this name cert_with_key.pfx in application folder with a password
  3. And use the code in the description
  4. Excute on Android Device

Link to public reproduction project repository

no

Version with bug

7.0 (current)

Last version that worked well

Unknown/Other

Affected platforms

Android

Affected platform versions

Android from 10

Did you find any workaround?

No

Relevant log output

{System.Security.Cryptography.CryptographicException: The certificate data cannot be read with the provided password, the password may be incorrect.
 ---> System.PlatformNotSupportedException: Algorithm 'RC2' is not supported on this platform.
   at System.Security.Cryptography.PasswordBasedEncryption.CreateRC2()
   at System.Security.Cryptography.PasswordBasedEncryption.Decrypt(AlgorithmIdentifierAsn& algorithmIdentifier, ReadOnlySpan`1 password, ReadOnlySpan`1 passwordBytes, ReadOnlySpan`1 encryptedData, Span`1 destination)
   at System.Security.Cryptography.X509Certificates.UnixPkcs12Reader.DecryptSafeContents(ReadOnlySpan`1 password, ContentInfoAsn& safeContentsAsn)
   at System.Security.Cryptography.X509Certificates.UnixPkcs12Reader.DecryptAndProcessSafeContents(ReadOnlySpan`1 password, CertBagAsn[]& certBags, AttributeAsn[][]& certBagAttrs, Int32& certBagIdx, SafeBagAsn[]& keyBags, Int32& keyBagIdx)
   at System.Security.Cryptography.X509Certificates.UnixPkcs12Reader.Decrypt(ReadOnlySpan`1 password, ReadOnlyMemory`1 authSafeContents)
   at System.Security.Cryptography.X509Certificates.UnixPkcs12Reader.VerifyAndDecrypt(ReadOnlySpan`1 password, ReadOnlyMemory`1 authSafeContents)
   at System.Security.Cryptography.X509Certificates.UnixPkcs12Reader.Decrypt(SafePasswordHandle password, Boolean ephemeralSpecified)
   --- End of inner exception stack trace ---
   at System.Security.Cryptography.X509Certificates.UnixPkcs12Reader.Decrypt(SafePasswordHandle password, Boolean ephemeralSpecified)
   at System.Security.Cryptography.X509Certificates.AndroidCertificatePal.ReadPkcs12(ReadOnlySpan`1 rawData, SafePasswordHandle password, Boolean ephemeralSpecified)
   at System.Security.Cryptography.X509Certificates.AndroidCertificatePal.FromBlob(ReadOnlySpan`1 rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags)
   at System.Security.Cryptography.X509Certificates.CertificatePal.FromBlob(ReadOnlySpan`1 rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags)
   at System.Security.Cryptography.X509Certificates.X509Certificate..ctor(Byte[] rawData, String password, X509KeyStorageFlags keyStorageFlags)
   at System.Security.Cryptography.X509Certificates.X509Certificate..ctor(Byte[] rawData, String password)
   at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(Byte[] rawData, String password)
@ghost
Copy link

ghost commented Apr 18, 2023

Hi @SepuWeb. We have added the "s/needs-repro" label to this issue, which indicates that we require steps and sample code to reproduce the issue before we can take further action. Please try to create a minimal sample project/solution or code samples which reproduce the issue, ideally as a GitHub repo that we can clone. See more details about creating repros here: https://github.com/dotnet/maui/blob/main/.github/repro.md

This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

@Redth
Copy link
Member

Redth commented Apr 18, 2023

@steveisok @akoeplinger could you have a look please?

@steveisok
Copy link
Member

@SepuWeb, we made the decision to integrate directly w/ Android API's rather than rely on OpenSSL. Unfortunately, RC2 is not supported on Android as reflected in the message you are getting. My recommendation would be to use AES as that is supported.

@SepuWeb
Copy link
Author

SepuWeb commented Apr 18, 2023

Thank you for your replies. Why same code works in Xamarin? I tested it in Xamarin with many version of Android without problems. Instead in MAUI return this error, on the same device, with Android 10 and Android 13.
Are we sure the problem is really Android?

@steveisok
Copy link
Member

The same code works in Xamarin because the underlying dependencies are different. BoringSSL is used where we don't rely on Android API's as we do in .NET.

@SepuWeb
Copy link
Author

SepuWeb commented Apr 18, 2023

Ok.
In Android API documentation I found this:

https://developer.android.com/reference/javax/crypto/spec/RC2ParameterSpec

"This class specifies the parameters used with the RC2 algorithm."

How can I convert my code to use AES? I think that this information would be inserted in the manual:
https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects?source=recommendations&view=net-maui-7.0

@steveisok
Copy link
Member

Interesting. I'll reopen and have us look into it further. Thanks for the link.

@steveisok steveisok reopened this Apr 18, 2023
@ghost ghost added the untriaged New issue has not been triaged by the area owner label Apr 18, 2023
@steveisok steveisok transferred this issue from dotnet/maui Apr 18, 2023
@ghost
Copy link

ghost commented Apr 18, 2023

Tagging subscribers to this area: @dotnet/area-system-security, @bartonjs, @vcsjones
See info in area-owners.md if you want to be subscribed.

Issue Details

Description

I'm trying to convert my Xamarin App into new .NET MAUI.

This works in Xamarin:

string path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "/cert_with_key.pfx";
byte[] rawData= File.ReadAllBytes(path);
X509Certificate2 cert = new X509Certificate2(rawData, privKeyPSW); ----->this throw the following error

{System.Security.Cryptography.CryptographicException: The certificate data cannot be read with the provided password, the password may be incorrect.
---> System.PlatformNotSupportedException: Algorithm 'RC2' is not supported on this platform.

Steps to Reproduce

  1. Create a File > New .NET MAUI App
  2. Create a pfx file with this name cert_with_key.pfx in application folder with a password
  3. And use the code in the description
  4. Excute on Android Device

Link to public reproduction project repository

no

Version with bug

7.0 (current)

Last version that worked well

Unknown/Other

Affected platforms

Android

Affected platform versions

Android from 10

Did you find any workaround?

No

Relevant log output

{System.Security.Cryptography.CryptographicException: The certificate data cannot be read with the provided password, the password may be incorrect.
 ---> System.PlatformNotSupportedException: Algorithm 'RC2' is not supported on this platform.
   at System.Security.Cryptography.PasswordBasedEncryption.CreateRC2()
   at System.Security.Cryptography.PasswordBasedEncryption.Decrypt(AlgorithmIdentifierAsn& algorithmIdentifier, ReadOnlySpan`1 password, ReadOnlySpan`1 passwordBytes, ReadOnlySpan`1 encryptedData, Span`1 destination)
   at System.Security.Cryptography.X509Certificates.UnixPkcs12Reader.DecryptSafeContents(ReadOnlySpan`1 password, ContentInfoAsn& safeContentsAsn)
   at System.Security.Cryptography.X509Certificates.UnixPkcs12Reader.DecryptAndProcessSafeContents(ReadOnlySpan`1 password, CertBagAsn[]& certBags, AttributeAsn[][]& certBagAttrs, Int32& certBagIdx, SafeBagAsn[]& keyBags, Int32& keyBagIdx)
   at System.Security.Cryptography.X509Certificates.UnixPkcs12Reader.Decrypt(ReadOnlySpan`1 password, ReadOnlyMemory`1 authSafeContents)
   at System.Security.Cryptography.X509Certificates.UnixPkcs12Reader.VerifyAndDecrypt(ReadOnlySpan`1 password, ReadOnlyMemory`1 authSafeContents)
   at System.Security.Cryptography.X509Certificates.UnixPkcs12Reader.Decrypt(SafePasswordHandle password, Boolean ephemeralSpecified)
   --- End of inner exception stack trace ---
   at System.Security.Cryptography.X509Certificates.UnixPkcs12Reader.Decrypt(SafePasswordHandle password, Boolean ephemeralSpecified)
   at System.Security.Cryptography.X509Certificates.AndroidCertificatePal.ReadPkcs12(ReadOnlySpan`1 rawData, SafePasswordHandle password, Boolean ephemeralSpecified)
   at System.Security.Cryptography.X509Certificates.AndroidCertificatePal.FromBlob(ReadOnlySpan`1 rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags)
   at System.Security.Cryptography.X509Certificates.CertificatePal.FromBlob(ReadOnlySpan`1 rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags)
   at System.Security.Cryptography.X509Certificates.X509Certificate..ctor(Byte[] rawData, String password, X509KeyStorageFlags keyStorageFlags)
   at System.Security.Cryptography.X509Certificates.X509Certificate..ctor(Byte[] rawData, String password)
   at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(Byte[] rawData, String password)
Author: SepuWeb
Assignees: -
Labels:

area-System.Security

Milestone: -

@steveisok steveisok removed the untriaged New issue has not been triaged by the area owner label Apr 18, 2023
@steveisok steveisok added this to the 8.0.0 milestone Apr 18, 2023
@ghost
Copy link

ghost commented Apr 18, 2023

Tagging subscribers to 'arch-android': @steveisok, @akoeplinger
See info in area-owners.md if you want to be subscribed.

Issue Details

Description

I'm trying to convert my Xamarin App into new .NET MAUI.

This works in Xamarin:

string path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "/cert_with_key.pfx";
byte[] rawData= File.ReadAllBytes(path);
X509Certificate2 cert = new X509Certificate2(rawData, privKeyPSW); ----->this throw the following error

{System.Security.Cryptography.CryptographicException: The certificate data cannot be read with the provided password, the password may be incorrect.
---> System.PlatformNotSupportedException: Algorithm 'RC2' is not supported on this platform.

Steps to Reproduce

  1. Create a File > New .NET MAUI App
  2. Create a pfx file with this name cert_with_key.pfx in application folder with a password
  3. And use the code in the description
  4. Excute on Android Device

Link to public reproduction project repository

no

Version with bug

7.0 (current)

Last version that worked well

Unknown/Other

Affected platforms

Android

Affected platform versions

Android from 10

Did you find any workaround?

No

Relevant log output

{System.Security.Cryptography.CryptographicException: The certificate data cannot be read with the provided password, the password may be incorrect.
 ---> System.PlatformNotSupportedException: Algorithm 'RC2' is not supported on this platform.
   at System.Security.Cryptography.PasswordBasedEncryption.CreateRC2()
   at System.Security.Cryptography.PasswordBasedEncryption.Decrypt(AlgorithmIdentifierAsn& algorithmIdentifier, ReadOnlySpan`1 password, ReadOnlySpan`1 passwordBytes, ReadOnlySpan`1 encryptedData, Span`1 destination)
   at System.Security.Cryptography.X509Certificates.UnixPkcs12Reader.DecryptSafeContents(ReadOnlySpan`1 password, ContentInfoAsn& safeContentsAsn)
   at System.Security.Cryptography.X509Certificates.UnixPkcs12Reader.DecryptAndProcessSafeContents(ReadOnlySpan`1 password, CertBagAsn[]& certBags, AttributeAsn[][]& certBagAttrs, Int32& certBagIdx, SafeBagAsn[]& keyBags, Int32& keyBagIdx)
   at System.Security.Cryptography.X509Certificates.UnixPkcs12Reader.Decrypt(ReadOnlySpan`1 password, ReadOnlyMemory`1 authSafeContents)
   at System.Security.Cryptography.X509Certificates.UnixPkcs12Reader.VerifyAndDecrypt(ReadOnlySpan`1 password, ReadOnlyMemory`1 authSafeContents)
   at System.Security.Cryptography.X509Certificates.UnixPkcs12Reader.Decrypt(SafePasswordHandle password, Boolean ephemeralSpecified)
   --- End of inner exception stack trace ---
   at System.Security.Cryptography.X509Certificates.UnixPkcs12Reader.Decrypt(SafePasswordHandle password, Boolean ephemeralSpecified)
   at System.Security.Cryptography.X509Certificates.AndroidCertificatePal.ReadPkcs12(ReadOnlySpan`1 rawData, SafePasswordHandle password, Boolean ephemeralSpecified)
   at System.Security.Cryptography.X509Certificates.AndroidCertificatePal.FromBlob(ReadOnlySpan`1 rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags)
   at System.Security.Cryptography.X509Certificates.CertificatePal.FromBlob(ReadOnlySpan`1 rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags)
   at System.Security.Cryptography.X509Certificates.X509Certificate..ctor(Byte[] rawData, String password, X509KeyStorageFlags keyStorageFlags)
   at System.Security.Cryptography.X509Certificates.X509Certificate..ctor(Byte[] rawData, String password)
   at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(Byte[] rawData, String password)
Author: SepuWeb
Assignees: -
Labels:

area-System.Security, os-android, untriaged

Milestone: -

@steveisok
Copy link
Member

According to #45741, RC2 is not supported in .NET. Originally, I had thought it was an underlying Android API problem, but https://developer.android.com/reference/javax/crypto/spec/RC2ParameterSpec made me think otherwise.

Tagging @simonrozsival for awareness.

@jkoritzinsky
Copy link
Member

RC2 isn't listed on the supported ciphers on Android's documentation https://developer.android.com/reference/javax/crypto/Cipher

I think it used to support RC2 and the support was removed.

@SepuWeb
Copy link
Author

SepuWeb commented Apr 19, 2023

Ok, but I don't use RC2, I use that function: new X509Certificate2(rawData, privKeyPSW);

and the cert_with_key.pfx was created using RSA using this code:

            X509Name name = new X509Name("CN=" + CN);

            AsymmetricCipherKeyPair ackp = await Task.Run(() =>
            {
                try
                {
                  
                    RsaKeyPairGenerator rkpg = new RsaKeyPairGenerator();
                    var random = new SecureRandom();
                    var gen = new KeyGenerationParameters(random, 2048);
                    rkpg.Init(gen);
                    return rkpg.GenerateKeyPair();
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.ToString());
                    return null;
                }
            });

            //PKCS #10 Certificate Signing Request
            Pkcs10CertificationRequest csr = new Pkcs10CertificationRequest("SHA256WITHRSA", name, ackp.Public, null, ackp.Private);

            //Convert BouncyCastle CSR to .PEM file.
            StringBuilder CSRPem = new StringBuilder();
            PemWriter CSRPemWriter = new PemWriter(new StringWriter(CSRPem));
            CSRPemWriter.WriteObject(csr);
            CSRPemWriter.Writer.Flush();

            //Convert BouncyCastle Private Key to .PEM file.
            StringBuilder PrivateKeyPem = new StringBuilder();
            PemWriter PrivateKeyPemWriter = new PemWriter(new StringWriter(PrivateKeyPem));
            PrivateKeyPemWriter.WriteObject(ackp.Private);
            CSRPemWriter.Writer.Flush();

            File.WriteAllText(cert_with_key_path, PrivateKeyPem.ToString());

@bartonjs
Copy link
Member

The code you shared looks like it would have created two PEM files, something else was involved in making the PFX (perhaps an openssl pkcs12 command?)

@SepuWeb
Copy link
Author

SepuWeb commented Apr 19, 2023

Thanks @bartonjs, no, nothing else, if you look I use a Pkcs10CertificationRequest.

@bartonjs
Copy link
Member

PKCS#10 is certificate requests. PFX is PKCS#12. They're not really related (just produced by the same standards group).

Your code sample for what went wrong is loading cert_with_key.pfx; which does seem to be a real PFX (based on the callstack). Your snippet saying how you created cert_with_key.pfx doesn't actually create that file. (A cert+key PEM, or CSR+key PEM would not end up in UnixPkcs12Reader.Decrypt)

@SepuWeb
Copy link
Author

SepuWeb commented Apr 19, 2023

My fault, I got confused.
In the resources I have a .pfx file that I set up as MAUI Asset.
Before running the function written in the first post I run this:

private async Task SaveCertToDiskAsync(string fileToSave, string resName)
        {
            var resName = "certificate.pfx";
           var fileToSave = "cert_with_key.pfx";
            using var stream = await FileSystem.OpenAppPackageFileAsync(resName);
            byte[] arrByte = ReadFully(stream);

            File.WriteAllBytes(fileToSave, arrByte);
        }

        private byte[] ReadFully(Stream input)
        {
            byte[] buffer = new byte[16 * 1024];
            using (MemoryStream ms = new MemoryStream())
            {
                int read;
                while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
                {
                    ms.Write(buffer, 0, read);
                }
                return ms.ToArray();
            }
        }

@JairJr
Copy link

JairJr commented Apr 21, 2023

I have the same problem during a migration to MAUI, on Xamarin its works fine too.

@SepuWeb
Copy link
Author

SepuWeb commented Apr 21, 2023

Thank you @JairJr, do you use some plugin like BouncyCastle? or Portable Bouncy Castle?

@steveisok
Copy link
Member

Thank you @JairJr, do you use some plugin like BouncyCastle? or Portable Bouncy Castle?

Might be worth a try.

It seems that's the reason RC2 is no longer working with the Android API's. Looks like they had a bouncy castle dependency and dropped it completely.

Since there's nothing we can do on our side, I'm going to close this issue.

@JairJr
Copy link

JairJr commented May 18, 2023

Thank you @JairJr, do you use some plugin like BouncyCastle? or Portable Bouncy Castle?

I upgaded the certificate on powershell just with pfx import and export

@ghost ghost locked as resolved and limited conversation to collaborators Jun 17, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants