最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

C# to Python RSA implement - Stack Overflow

programmeradmin1浏览0评论

Just trying to rewrite this c# code to python. Server send public key(modulus, exponent), need to encrypt it with pkcs1 padding.

using (TcpClient client = new TcpClient())
{
    await client.ConnectAsync(ip, port);
    using (NetworkStream stream = client.GetStream())
    {
        await App.SendCmdToServer(stream, "auth", this.Ver.ToString().Split('.', StringSplitOptions.None));
        
        byte[] modulus = new byte[256];
        int num2 = await stream.ReadAsync(modulus, 0, modulus.Length);
        byte[] exponent = new byte[3];
        int num3 = await stream.ReadAsync(exponent, 0, exponent.Length);
        
        this.ServerRsa = RSA.Create();
        this.ServerRsa.ImportParameters(new RSAParameters()
        {
          Modulus = modulus,
          Exponent = exponent
        });

        using (MemoryStream data = new MemoryStream())
        {
          using (BinaryWriter writer = new BinaryWriter((Stream) data))
          {
            writer.Write(string1);
            writer.Write(string2);
            await App.SendDataToServer(stream, this.ServerRsa.Encrypt(data.ToArray(), RSAEncryptionPadding.Pkcs1));
          }
        }
    }
}

Everything works fine, except encrypted result by python. I've tried with rsa and pycryptodome, no luck at all, server returns reject. Tried something like this (rsa)

server_rsa = rsa.newkeys(2048)[0]
server_rsa.n = int.from_bytes(modulus, byteorder='big')
server_rsa.e = int.from_bytes(exponent, byteorder='big')
data = (string1 + string2).encode()
encrypted_data = rsa.encrypt(data, server_rsa)

or this (pycryptodome)

pubkey = construct((int.from_bytes(modulus, 'big'), int.from_bytes(exponent, 'big')))
cipher = PKCS1_v1_5.new(pubkey)
encrypted_data = cipher.encrypt(data)

Is there some special python RSA implementation, that just not working with C#, or vice versa?

Just trying to rewrite this c# code to python. Server send public key(modulus, exponent), need to encrypt it with pkcs1 padding.

using (TcpClient client = new TcpClient())
{
    await client.ConnectAsync(ip, port);
    using (NetworkStream stream = client.GetStream())
    {
        await App.SendCmdToServer(stream, "auth", this.Ver.ToString().Split('.', StringSplitOptions.None));
        
        byte[] modulus = new byte[256];
        int num2 = await stream.ReadAsync(modulus, 0, modulus.Length);
        byte[] exponent = new byte[3];
        int num3 = await stream.ReadAsync(exponent, 0, exponent.Length);
        
        this.ServerRsa = RSA.Create();
        this.ServerRsa.ImportParameters(new RSAParameters()
        {
          Modulus = modulus,
          Exponent = exponent
        });

        using (MemoryStream data = new MemoryStream())
        {
          using (BinaryWriter writer = new BinaryWriter((Stream) data))
          {
            writer.Write(string1);
            writer.Write(string2);
            await App.SendDataToServer(stream, this.ServerRsa.Encrypt(data.ToArray(), RSAEncryptionPadding.Pkcs1));
          }
        }
    }
}

Everything works fine, except encrypted result by python. I've tried with rsa and pycryptodome, no luck at all, server returns reject. Tried something like this (rsa)

server_rsa = rsa.newkeys(2048)[0]
server_rsa.n = int.from_bytes(modulus, byteorder='big')
server_rsa.e = int.from_bytes(exponent, byteorder='big')
data = (string1 + string2).encode()
encrypted_data = rsa.encrypt(data, server_rsa)

or this (pycryptodome)

pubkey = construct((int.from_bytes(modulus, 'big'), int.from_bytes(exponent, 'big')))
cipher = PKCS1_v1_5.new(pubkey)
encrypted_data = cipher.encrypt(data)

Is there some special python RSA implementation, that just not working with C#, or vice versa?

Share Improve this question edited Feb 6 at 22:25 President James K. Polk 42k27 gold badges109 silver badges144 bronze badges asked Feb 6 at 19:41 TuxTux 691 silver badge5 bronze badges 2
  • 1 not sure if I understand where the problem is but one thing to know is that the BinaryWriter, Write method writes length prefixed data to the stream. So the data.ToArray() in C# output is for sure not the same as data = (string1 + string2).encode() in Python? – Paweł Łukasik Commented Feb 6 at 20:14
  • Yeah, it was my fault. Server-side app is parcing BinaryWriter result byte sequence – Tux Commented Feb 6 at 21:35
Add a comment  | 

1 Answer 1

Reset to default 3

The PyCryptodome is a good choice for cryptographic tasks in Python. The problem is with the data formatting, you are concatenating the strings directly in Python and the BinaryWriter in C# write the lengths of the strings as prefixes.

This code show how you can do that:

import struct

data = b""
data += struct.pack(">I", len(string1.encode('utf-8')))   # add length as big-endian unsigned int
data += string1.encode('utf-8')
data += struct.pack(">I", len(string2.encode('utf-8')))
data += string2.encode('utf-8')


In the code above I encoded the length of the strings as big-endian unsigned int but as was commented by @Topaco the BinaryWriter encodes the length prefix with LEB128. So to replicate BinaryWriter you can do this:

import leb128

data = bytearray()
data += leb128.u.encode(len(string1.encode()))
data += string1.encode()
data += leb128.u.encode(len(string2.encode())) 
data += string2.encode()

I used the leb128 package that can be installed with pip install leb128. But you can create a function to do that encoding

def encode_leb128(number):
    if number == 0:
        return bytearray([0])
    
    result = bytearray()
    while number > 0:
        byte = number & 0x7f
        number >>= 7
        if number > 0:
            byte |= 0x80
        result.append(byte)
    return result

发布评论

评论列表(0)

  1. 暂无评论