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