0

I am rewriting the codes written in C# with Python. In a part of the C# program, a string is signed with the RSA algorithm and sent to an API. I have rewritten all parts of the C# program in Python, including the string signature section The output in the signature of the C# program is the same as the signature of the Python program But the APi in question does not confirm the signature generated by Python, even though the signature string in C# and Python is exactly the same.

I would be grateful if someone could help me And whether the output of the RSA algorithm for signature is the same or changes for the same string at each time of encryption (signature)?

In Python, I use the following

from Cryptodome. Signature import pkcs1_15
from Cryptodome. Hash import SHA256
from Cryptodome.PublicKey import RSA
import base64
...

I rewrote the signature of a string that is in C# programming language in Python language (with RSA algorithm and key length of 2048) and it showed me the output of the same string from both programs (C# and Python). When I send this signature string to an API, it does not receive an error and accepts the signature generated with C#, but it receives an error with the signature generated in Python and does not accept the signature.

What I expected was that since the signature output from both programming languages is the same (the same strings), the desired API should not have any problem with it. Is my view wrong?

C#

public static string SignData(String stringToBeSigned, string privateKey)
    {

        var pem = "-----BEGIN PRIVATE KEY-----\n" + privateKey + "\n-----END PRIVATE KEY-----";      
        PemReader pr = new PemReader(new StringReader(pem));
        AsymmetricKeyParameter privateKeyParams = (AsymmetricKeyParameter)pr.ReadObject();
        RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaPrivateCrtKeyParameters)privateKeyParams);

        RSACryptoServiceProvider csp = new RSACryptoServiceProvider();
        csp.ImportParameters((RSAParameters)rsaParams);

        var dataBytes = Encoding.UTF8.GetBytes(stringToBeSigned);
        return Convert.ToBase64String(csp.SignData(dataBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
    }

python :

key = RSA.import_key(open('rsa.private').read())
h = SHA256.new(normalize.encode('utf-8'))
signature = pkcs1_15.new(key).sign(h)
base64_bytes = base64.b64encode(signature)
base64_signature = base64_bytes.decode('ascii')
print(base64_signature)
President James K. Polk
  • 40,516
  • 21
  • 95
  • 125
Advaita
  • 1
  • 1
  • This makes no sense: if both codes generate the *same* signature, why would one be successfully verified and the other not? Either the signatures are different or one is changed afterwards. Post the C# code and the Python code and test data (sample key pair, message and signature of both codes). – Topaco Jan 23 '23 at 11:54
  • 1
    Regarding your question, whether the same signature is generated for the same data when repeated: There are two different padding schemes for RSA signing: PKCS#1 v1.5 and PSS. PKCS#1 v1.5 is deterministic (i.e. always the same signature is generated), PSS is not (i.e. always different signatures are generated), s. [RFC8017, sec. 8. Signature Scheme with Appendix](https://www.rfc-editor.org/rfc/rfc8017#section-8) – Topaco Jan 23 '23 at 11:57
  • @Topaco Yes definitely, both production signatures are the same – Advaita Jan 23 '23 at 12:50
  • If both codes produce the same signature (and according to the code this is the case for the same data) and the signature of one code is successfully verified and that of the other code is not, this means that one of the two signatures is changed before verification (possibly unintentionally, wrong encoding, etc.) and/or that different messages or keys are used during verification (mix-up or unintentional changing of the data). – Topaco Jan 23 '23 at 13:26
  • Also make sure you are using the same RSA version everywhere. The key in C# is in PKCS#8 format, make sure the key in the file `rsa.private` is the same format (does not have `BEGIN RSA PRIVATE KEY`, note the extra `RSA`), and that your library supports it. When I take on a project like this, I make it work on the command line with openssl first, to act as a referee. Also have a look at [this answer by Topaco](https://stackoverflow.com/a/65966678/591064). – ixe013 Jan 23 '23 at 14:16

0 Answers0