'Verify string signed with private key in iOS with C# code

I am working on a bluetooth based application where I create a string in Swift and sign it with RSA private key. The string is sent to a WPF app via bluetooth. The wpf app already has its public key. I want to verify the string the in WPF app. But I am not able to do it. I am getting error for algorithm type. Following is my Swift code:

func signWithPrivateKey(textToEncrypt: String) -> Data? {
    guard let privateKey: SecKey =  privateKey else {
        return nil
    }
    let algorithm: SecKeyAlgorithm = .rsaSignatureMessagePSSSHA512
    guard SecKeyIsAlgorithmSupported(privateKey, .sign, algorithm) else {
        return nil
    }
    var error: Unmanaged<CFError>?
    let data = textToEncrypt.data(using: .utf8)!
    guard let signature = SecKeyCreateSignature(privateKey,
                                                algorithm,
                                                data as CFData,
                                                &error) as Data? else {
                                                    return nil
    }
    return signature
}

C# code to verify the string:

var deferral = args.GetDeferral();

        var request = await args.GetRequestAsync();
        var reader = DataReader.FromBuffer(request.Value);

        byte[] fileContent = new byte[reader.UnconsumedBufferLength];
        reader.ReadBytes(fileContent);
        string text = Encoding.UTF8.GetString(fileContent, 0, fileContent.Length);
        Debug.WriteLine(Convert.ToBase64String(fileContent));
        String EncryptedMessage = Convert.ToBase64String(fileContent);
        Debug.WriteLine(text);

        using (var rsa = new RSACryptoServiceProvider())
        {
            var encoder = new UTF8Encoding();
            byte[] bytesToVerify = encoder.GetBytes("Guten Morgan");

            //byte[] signedBytes = Convert.FromBase64String(text);
            try
            {
                bool success = rsa.VerifyData(bytesToVerify, CryptoConfig.MapNameToOID("SHA-512"), fileContent);
                Debug.WriteLine(success);
            }catch (CryptographicException e)
            {
                Debug.WriteLine(e.Message);
            }
        }

Getting following error:
System.ArgumentNullException: 'Value cannot be null. (Parameter 'hashAlg')'

I have mentioned the algorithm type as rsaSignatureMessagePSSSHA512 in Swift app and trying to verify it with SHA-512 but getting error. Can someone please help me how to verify the signature in C#.

Edit: I have modified the WPF code as following and it is not crashing now, but I am still not able to verify it

Credential credential = CredentialManager.ReadCredential("CredentialManagerTests");
            String publicKey = credential.Password;
            Debug.WriteLine(publicKey);
            var deferral = args.GetDeferral();

            var request = await args.GetRequestAsync();
            var reader = DataReader.FromBuffer(request.Value);

            byte[] fileContent = new byte[reader.UnconsumedBufferLength];
            reader.ReadBytes(fileContent);
            string text = Encoding.UTF8.GetString(fileContent, 0, fileContent.Length);
            Debug.WriteLine(Convert.ToBase64String(fileContent));
            
            byte[] privateKeyPkcs1DER = ConvertPKCS1PemToDer(publicKey);

            using (var rsa = new RSACryptoServiceProvider())
            {
                var encoder = new UTF8Encoding();
                byte[] bytesToVerify = encoder.GetBytes("Guten Morgan");
                rsa.ImportRSAPublicKey(privateKeyPkcs1DER, out _);
                try
                {
                    bool success = rsa.VerifyData(bytesToVerify, fileContent, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1);
                    Debug.WriteLine(success);
                }
                catch (CryptographicException e)
                {
                    Debug.WriteLine(e.Message);
                }
            }

Edit2: String to sent: "Guten Morgan" Signature: "G8ePlCyPeivAHPygMHXeCTszTy9EV4y6Gsku9GQJV71t+M7ATFZjxkh9u0DVjR0ei76a4dixzgXKLZLQNy/mxwrvUvolPHE0HUFAErkzfeHcrB8/QlHlEoEdt9vf34L8KNy6yVOHWC2sytgvw009EsKUr3LYb8kSkCeaCVEEEAwAELt3z/YzfnbwR0GXatlNpmaoLOXh0mEep8Xh5AHf6RhbgS0VBFSXSbz3ALbwu5DtlaIv4P1nFOP80w2NBs7HrHOMdR0PKdgiD+suErCYWKINzToKDsdO8XNaKdw3jekYBRXl6GNfAwQeADCq0MDsvptCRVZ//fzU2fXRcaYsRA==" Algo: SHA512

**Public Key: ** MIIBCgKCAQEA4lS13W+TXZhUXy5yB2NpeulCVb1ZSaReopeKrahjKmUx4NQxVXruEYCY3LpjZcSy8xiudVG3GBIMnPLtaMbc5WAYDj1M2OwnpNHdQ8SKtZ1tdA6iRjfOXGUa1n8FMIMKU5ynTSAiSoh+8gGrY0L6jTsCSdLO5ZU53LQFHSESM8JuBeNZozolb/cKb38ylercVeVpo8egoA8UqHezK23VUJ23faxMmMZDJxVn5pfFedxBTLxwU65KQY8Z4izaFjuPLoGe5JZkXyYNMcrYloDCBG5m9BFiXVkoLEDmGFGfWLMJcqL+D2CszqJ4h712ZR6LYRNtIbo/HG9KR7XCtap3QwIDAQAB.

Private Key: MIIEowIBAAKCAQEAuAoCUOejL7EBI0P4nfZQkAr8/a37SR/umJB5sUOyy2IyaWuSX1tBOco4XThTkCYj2ubgbf0fGsQ7FRgF6bwbeynhDYS7ptPkvUHF4BaSUsu2KtKkoslvl67M83ESKtOSm0s0CImw60MDlPDr/1SPhkYgSfoQ81CXytrZPkWtB/YekT2ph3PRqyOeMNl0O88Clt2mdR4dZeZWv6WGaaoP1kr8RY9iB6hrg2RdOFXixIOdo7cP3+3w9s4svnIX7RNLIIrUxJHQUYA0oxkiZ9y0peWR5mElywjkg/AFm8RxZsXjHowrqlYGkFKzPTq2/dhwId0Yit95aYVIDE5Dj9n3nQIDAQABAoIBAAFiDd9mxjqrBVuq/JjPS46xjnInlw5XH5dk6o0y+Yp+u+s/5DM0P9q70s2ciUA5kSZpesFI2C1+0QTZD95QTBKSX38XAsP/rqXfcym6cbIOltleiN8yTVTh+udPb7gDrAPfvk3cHwi9ka7SWquqCoQTTdXQe8UgU2uyVlSZ+HFpXFE55ltp4CbnFBH39Sa8pqbpwIwb2+PCFkx7xVUIJ2t1vJd2yBUjEBFJv0SiUy9DWwbXiyoqtZXtVft8Vm7xhimSDN2o6KcnXYEq2eb3UhOKI09tRsYLA3bF66bvVxvcnykuUpLHFOxhBKfD8Vsh+SWHdv6zT52gkF7KDUxDYLECgYEA25iGkCcYx+cfzIdVmIbqa662IzkgUlCdpX37tBNHjyE+72Ehw6odZ0e3iTewm/vYBI6hyCW+T/G6ksl2enjOxBH0DhaQEYLqhSGq63/XOsFsmW7tH4YmInURv4RL4KEIB8HNGLfhllJt92KsrBNzei+SjdtElQhULhw4Mle6PWUCgYEA1ox8DxPTE8HQ5Jw+7D0ut+FyYkysciMSFYpmFX5qlbMlfl0WRL4mVFv/tOBerahsCDdaaOKJKafQVbJIU8G9U0m8PAttcM4OMjexwHzT0EBdf9cNACAXQP/arJEbf8YkPr7/IwI6YGiMFzDKRqcrYMNzl9rZXQEyJGj6u4x/6dkCgYBYIWiv5eD+KXYLoazqoAro2J9kl4KvRodeaadg5/PqL4+Qhs0EN/vA/XldaqpIj9RsT8oCB5PPhdY5Hv2bvWxOKF5oYQnE3WO9tntgNFhuzj4Ffg1Qf4hCf/V1hWTma/pLEq57YyD4MXDMvh9KmCvaN8l7gSqPHV6betva6HZoOQKBgQCwZMxSsR/nrIAMlRF+tUbF08txWkylgoQJxcHshgUnkySOYgY++n8U+JahpZ7x8/juQGRKu4W+A8Tb0Dp68lywL31deJ/AEQnG69duxLJ5E5JL2wlLQxcbT8AABUWwpb2DARFPPTO1s/8JyglkUWjuo4NUJJB1UNhi6xTKQdeg8QKBgESvEWQKqvk3YCpVwCNv5C+1aAVS6Fq/sGmLlVsbQ5W6EENYDg4pq2fgghH9lcRb1BdHjFm25ikADbGWgBOG1fvrD9KsR9RY98x8XM3EQ5EJ2Y2vjQfWBA2da8nr9ETRzY00IjHCzb5AhISWIit7Itaa9H202v1zZCIUY+O/YGGX

Edit3:
My below method was wrong:

private byte[] ConvertPKCS1PemToDer(string pemContents)
    {
        return Convert.FromBase64String(pemContents
            .TrimStart("-----BEGIN PUBLIC KEY-----".ToCharArray())
            .TrimEnd("-----END PUBLIC KEY-----".ToCharArray())
            .Replace("\r\n", ""));
    }

Instead of BEGIN PUBLIC KEY it was BEGIN PRIVATE KEY. I have fixed it as mentioned above but getting following error on Convert line in above function:

System.FormatException: 'The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters.'

Edit4: I have now created a new project only to test my code and have added following code:

Private key for reference:
"MIIEogIBAAKCAQEArMO9cJHbKYKkozTtqPI9fhecyiibJrvsv5KLLPlQcIi0uo6yfLD4MUFS5UbwaGATnCrLRKr27iQLWwWKxsJdEQMZDMF6EiCQSXEB2AmSEPW4NOh5kbj05cJoDrvSeac3lllsjPlOaVQSrgmiOFoJ1t98utfOJ6FCzam9DZZR7r/OwTZ0754rAp4dqwkamcTaSkW2zQhr++mw4WZZiKGJCPYKKXguGJbRTtr+dcZ4JwrvdYudCguuCVfa+1D6k0NswWEu58DELZ0XPuLu8qFiIA9MI5K/ECHXwozi8UxmDhG9NJuh+uRZZ4s7LVnkNDN8np6vhuwKNL5rP0msUciItwIDAQABAoIBAAgEaSZoyepbD2fVC3TMPB/2df9dpSUbSxrixhto541UBIPtVzQVkoi6ne2uqMu3LpAB3mKfcYvAkJDImqrkQc/tWNHbG4lCXtGIxrZoMtjKFJQ824/UAknQzpCeP7UjpHRYapEb+qW2/JJDU9oDRd2B4S+FZXdVAPJXjPutCy40IziykyhU9Fu0fwCN/ry764EyI4gtN/WgDHwc2C8B7sriW81KtB8vJW10waoot3MRBfXxxhk3wyiNputBg1KDz+O2+iUrO4p1OKdvL9S9u65MN9Klm+i03aexNrjbMHu/lxDUa6buSgfXh5+Na6PLHur/3aCqfZdpJ/OO7AxarqECgYEA4884gGubJmiq8OayGdpnaZa4L/2NEwOEnN2G09ySXuUhIyOzOJmeiw3R0BTOB0ZRzrk/Ozq3/T2z1ScUGr3a7hmgGBm3azNjJCbYZ51/XJPE7B5UhDFejZPGRT8vVnUzjYah4Eipp4hSIe79Ja17vTFTtY7bGGl11a6VaPvHuCECgYEAwiTAs60JqUIFw8qmBzWwIHybbKSS0Pc8AWdMYLVSnqiQKZVDnyypUDv14+VEMbCdW21ShMCrNK0QTWnqkV7ln91jxPNvQbSoLBTXgpxbvoxg57jg6sdtiUuPjdBBc74kV9oW1zX2saLvPOO4fjUw3z1b+6/v1SjRlhIqtQrsRdcCgYBeDgYz7zmFaB17jKPnzKZ5j8LH/ZUrTn6IDWZHPoAoMc22plyud65flvsTQCO4GS5ZfV4/5ARmx/zhelrwl4Y2W9ofWS7DUdoS6P7b+MjGvjPFkNgwI/n31hU8LdQrjAQW4IkhAp8ZDk1quTNHRRMbj6wR/8MxlwkRih0h1SImQQKBgGnuQdMH9ICNDLYzKXo/mhVvyCJ0fcNVU0F0yqDt7uGxGdAGqLn+VXf474bkvtvaAVI0iVT0B7abQ4zp4NpnDCW5V8nMBgW0/BnpWVnj1M9YqztkjhysqiDCwNZhLoVn1060KchNooh0XdM8cZszjLISOdFPwy3ssscOrIzSI+9LAoGAMDcGC5P9gVBCNd8ox5OlozNwAmHmHwpqFJcOxNx4lCE5DkT+6DEscoLMZ4LkNVzMHb0LmyhDnF24eIn/v7FRb6ZF5YzlpIdQC2tvXaJoyPwLPee7XGGr9IRkupbrNzPWVhTUYK9kJvI7SWPF2DBFK8fiC5S96USVp++kOjp/faE="
String publicKey = "MIIBCgKCAQEArMO9cJHbKYKkozTtqPI9fhecyiibJrvsv5KLLPlQcIi0uo6yfLD4MUFS5UbwaGATnCrLRKr27iQLWwWKxsJdEQMZDMF6EiCQSXEB2AmSEPW4NOh5kbj05cJoDrvSeac3lllsjPlOaVQSrgmiOFoJ1t98utfOJ6FCzam9DZZR7r/OwTZ0754rAp4dqwkamcTaSkW2zQhr++mw4WZZiKGJCPYKKXguGJbRTtr+dcZ4JwrvdYudCguuCVfa+1D6k0NswWEu58DELZ0XPuLu8qFiIA9MI5K/ECHXwozi8UxmDhG9NJuh+uRZZ4s7LVnkNDN8np6vhuwKNL5rP0msUciItwIDAQAB";
            String signature = "ntGm9Vx38l26ZSEitc1L+G6YZw3Dt4dmXoQQUjSAcKD1d4bFm8QI6CIncTBQ0+rGWUh7fr2DWQBB1OPgoZRoDs23SGvl+KTqUBo6Ym+kIK4KXwBrMt3YXNFpXuXVk36+4+oBPFhcMAwG4fIG5MnMEHqv/F+NNA71a10irB0frMpwpU/FZDGEbCnvOxGe6qIUsYt/dMbf1UT1AjKqQA0EmNqvIsU5DuHcpScb5xuV8aPJg6vPPKafLa8LbBiCA4dyxUcUYSjSaTQ6D9YoZ3Ich/dRBCyIdw9vESBSrOUGvwOmNl+5X+r2UyFN8RgYwW61M3iYdmkwJYYVUbMA69vCOA==";
            byte[] signatureBytes = Encoding.UTF8.GetBytes(signature);
            using (var rsa = new RSACryptoServiceProvider())
            {
                rsa.ImportRSAPublicKey(Convert.FromBase64String(publicKey), out _);
                var encoder = new UTF8Encoding();
                byte[] bytesToVerify = encoder.GetBytes("Guten Morgen");

                try
                {
                    bool success = rsa.VerifyData(bytesToVerify, CryptoConfig.MapNameToOID("SHA512"), signatureBytes);
                    Debug.WriteLine(success);
                }
                catch (CryptographicException e)
                {
                    Debug.WriteLine(e.Message);
                }
            }

But success variable is still false.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source