python RSA使用c#中的Private Key BLOBs

c#代码:
RSACryptoServiceProvider.ImportCspBlob

using System;
using System.Security.Cryptography;

namespace ApplicationDecrypt
{
	// Token: 0x02000004 RID: 4
	public class RSAUtil
	{
		// Token: 0x0600000B RID: 11 RVA: 0x00002466 File Offset: 0x00000666
		public byte[] DecryptByBytes(byte[] byteEntry, string strPrivateKey)
		{
			RSACryptoServiceProvider rsacryptoServiceProvider = new RSACryptoServiceProvider();
			rsacryptoServiceProvider.ImportCspBlob(Convert.FromBase64String(strPrivateKey));
			return rsacryptoServiceProvider.Decrypt(byteEntry, false);
		}
	}
}

links
https://learn.microsoft.com/en-us/windows/win32/seccrypto/rsa-schannel-key-blobs#private-key-blobs
https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-publickeystruc
https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-rsapubkey

python

import struct

"""
PRIVATEKEYBLOB  0x7 The key is a public/private key pair.
CALG_RSA_KEYX	0x0000a400

typedef struct _PUBLICKEYSTRUC {
  BYTE   bType;
  BYTE   bVersion;
  WORD   reserved;
  ALG_ID aiKeyAlg;
} BLOBHEADER, PUBLICKEYSTRUC;


typedef struct _RSAPUBKEY {
  DWORD magic;
  DWORD bitlen;
  DWORD pubexp;
} RSAPUBKEY;
Set to RSA1 (0x31415352) for public keys and to RSA2 (0x32415352
"""
class PUBLICKEYSTRUC():
    def __init__(self, datas: bytes) -> None:
        self.s = struct.Struct('<B B H I')
        self.bType, self.bVersion, self.reserved, self.aiKeyAlg = self.s.unpack(
            datas[:self.s.size])

    def __str__(self) -> str:
        return 'PUBLICKEYSTRUC:\nbType:%#02x bVersion:%#02x reserved:%#04x aiKeyAlg:%#08x' % (self.bType, self.bVersion, self.reserved, self.aiKeyAlg)

    def __len__(self) -> int:
        return self.s.size


class RSAPUBKEY(object):
    def __init__(self, datas: bytes):
        self.s = struct.Struct('<I I I')
        X = self.s.unpack(datas[:self.s.size])
        self.magic, self.bitlen, self.pubexp = X

    def __str__(self) -> str:
        return 'RSAPUBKEY:\nmagic:%#08x bitlen:%#08x pubexp:%#08x' % (self.magic, self.bitlen, self.pubexp)

    def __len__(self) -> int:
        return self.s.size


class NUMBS():
    def __init__(self, n_sz: int, datas: bytes) -> None:
        n1 = n_sz//8
        n2 = n_sz//16
        numbstruct = struct.Struct(
            '<{}s{}s{}s{}s{}s{}s{}s'.format(n1, n2, n2, n2, n2, n2, n1))
        numbs = numbstruct.unpack(datas)
        self.modulus = int.from_bytes(numbs[0], 'little')
        self.prime1 = int.from_bytes(numbs[1], 'little')
        self.prime2 = int.from_bytes(numbs[2], 'little')
        self.exponent1 = int.from_bytes(numbs[3], 'little')
        self.exponent2 = int.from_bytes(numbs[4], 'little')
        self.coefficient = int.from_bytes(numbs[5], 'little')
        self.privateExponent = int.from_bytes(numbs[6], 'little')

    def __str__(self) -> str:
        return 'modulus:%d\nprime1:%d\nprime2:%d\nexponent1:%d\nexponent2:%d\ncoefficient:%d\nprivateExponent:%d\n' % (self.modulus, self.prime1, self.prime2, self.exponent1, self.exponent2, self.coefficient, self.privateExponent)


class PRIVATEKEYBLOB():
    def __init__(self, datas: bytes) -> None:
        self.publickeystruc = PUBLICKEYSTRUC(datas)
        # print(self.publickeystruc)
        rsapubkey_offset = len(self.publickeystruc)
        self.rsapubkeystruc = RSAPUBKEY(datas[rsapubkey_offset:])
        # print(self.rsapubkeystruc)
        numbs_offset = rsapubkey_offset+len(self.rsapubkeystruc)
        self.numbs = NUMBS(self.rsapubkeystruc.bitlen, datas[numbs_offset:])

        self.modulus = self.numbs.modulus
        self.pubexp = self.rsapubkeystruc.pubexp
        self.privateExponent = self.numbs.privateExponent

    def __str__(self) -> str:
        return 'n:%d\ne:%d\nd:%d' % (self.numbs.modulus, self.rsapubkeystruc.pubexp, self.numbs.privateExponent)


'''
PUBLICKEYSTRUC  publickeystruc ;
RSAPUBKEY       rsapubkey;
BYTE            modulus[rsapubkey.bitlen/8];
'''
class PUBLICKEYBLOB():
    def __init__(self,datas: bytes) -> None:
        self.publickeystruc = PUBLICKEYSTRUC(datas)
        # print(self.publickeystruc)
        rsapubkey_offset = len(self.publickeystruc)
        self.rsapubkeystruc = RSAPUBKEY(datas[rsapubkey_offset:])
        numbs_offset = rsapubkey_offset+len(self.rsapubkeystruc)
        numbstruct = struct.Struct('<{}s'.format(self.rsapubkeystruc.bitlen//8))
        self.modulus = int.from_bytes(numbstruct.unpack(datas[numbs_offset:])[0],'little') 

        self.pubexp = self.rsapubkeystruc.pubexp
    def __str__(self) -> str:
        return 'PUBLICKEYBLOB:\n\tmodulus:%d\n\tpubexp:%d'%(self.modulus,self.pubexp)
"""
 RSA.construct
        rsa_components (tuple):
            A tuple of integers, with at least 2 and no
            more than 6 items. The items come in the following order:

            1. RSA modulus *n*.
            2. Public exponent *e*.
            3. Private exponent *d*.
               Only required if the key is private.
            4. First factor of *n* (*p*).
               Optional, but the other factor *q* must also be present.
            5. Second factor of *n* (*q*). Optional.
            6. CRT coefficient *q*, that is :math:`p^{-1} \text{mod }q`. Optional.
"""

"""

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5 as PKCS1_cipher

#公钥
blob=PUBLICKEYBLOB(pk)
public_key = RSA.construct((blob.modulus, blob.pubexp))
cipher = PKCS1_cipher.new(public_key)
encinfo = cipher.encrypt(msg)

#私钥
blob = PRIVATEKEYBLOB(keyblob)
print(blob)
private_key = RSA.construct((blob.modulus, blob.pubexp, blob.privateExponent))
cipher = PKCS1_cipher.new(private_key)
msg = cipher.decrypt(encinfo[::-1], 0)

CryptDecrypt(), (s. Remarks) uses the little endian format, i.e. the ciphertext must be reversed.
The required padding is not OAEP, but PKCS#1 v1.5 padding.



"""

how-to-correctly-decrypt-data-in-python-using-rsa-private-key-blob-from-windows

posted @ 2023-02-06 10:51  DirWangK  阅读(177)  评论(0编辑  收藏  举报