-1

I want to encrypt a string using Rsa Sha1 encryption in python. I have C# code and I don't know how it is in python. please help me if you can!

RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(“<RSAKeyValue><Modulus>oQRshGhLf2Fh...”);
string data = "something";
 byte[] signMain = rsa.SignData(Encoding.UTF8.GetBytes(data), new
SHA1CryptoServiceProvider());
 sign = Convert.ToBase64String(signMain);
MaZaN
  • 107
  • 10
  • 1
    What have you tried or researched so far? – Klaus D. Feb 04 '19 at 11:53
  • Start with https://docs.python-guide.org/scenarios/crypto/, and go from there. To save you a little time, [this is the RSA signing section](https://cryptography.io/en/latest/hazmat/primitives/asymmetric/rsa/#signing) of the `cryptography` documentation. – Martijn Pieters Feb 04 '19 at 11:59
  • Final piece you need: `RSACryptoServiceProvider()` uses [PKCS1 padding](https://github.com/dotnet/corefx/blob/master/Documentation/architecture/cross-platform-cryptography.md#rsa). Don't use the recommended PSS padding here. – Martijn Pieters Feb 04 '19 at 12:11

1 Answers1

3

I'd use the cryptography project here. It has full RSA signing support. See the cryptography section of the Hitchhiker's Guide to Python for alternative options.

The .NET RSACryptoServiceProvider object doesn't let you set a padding algorithm, it will always use PKCS1v15, so select that padding in your Python code.

First, I'd convert that XML document to a PEM format so you can load the public key from that format. I'm not aware of any Python libraries that can load the .NET / XKMS 2.0 XML format directly:

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization

private_key_pem = b'-----BEGIN {format}-----\n...\n-----END {format}-----'
private_key = serialization.load_pem_private_key(
    private_key_pem,
    password=None,
    backend=default_backend()
)

Alternatively, with a Python XML parser you can probably feed the data from that XML document to a RSAPublicNumbers() and RSAPrivateNumbers() pair, then use the RSAPrivateNumbers.private_key() method to produce a RSA private key object to sign with. You'll have to base64-decode the XML data and convert from bytes to integer using big endian byte ordering.

You can then use the private key to do the signing:

from base64 import b64encode

from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding

data = "something"
signature = private_key.sign(data.encode('utf8'), padding.PKCS1v15(), hashes.SHA1())
signature_base64 = b64encode(signature)
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • I have following error: AttributeError: '_RSAPrivateKey' object has no attribute 'sign' @martijn-pieters – MaZaN Feb 04 '19 at 12:39
  • @MaZaN: Hrm, I'll have to see what that means, exactly. I can't reproduce that error, my `cryptography.hazmat.backends.openssl.rsa._RSAPrivateKey` has a `sign` method. – Martijn Pieters Feb 04 '19 at 12:58
  • 1
    @MaZaN: what version of `cryptography` have you got installed? The [`RSAPrivateKey.sign()` method requires version 1.4 or newer](https://cryptography.io/en/latest/hazmat/primitives/asymmetric/rsa/#cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey.sign). use `import cryptography` then `cryptography.__version__` to find out. I tested this code with 2.3.1 and 2.5 (latest). – Martijn Pieters Feb 04 '19 at 13:09