Topic: Microsoft CrytoAPI and RSA

Nobody knows, how function CryptDecrypt in MS CryptoAPI works?
Problem in the following: I need to cipher certain given by algorithm RSA with key length 1024 bits that then they could be decrypted through CryptoAPI. At present I have the following code (cut all superfluous):
In CryptoAPI key pair RSA is generated and the public key is exported

CryptGenKey (FProvider, AT_KEYEXCHANGE, 1024 shl 16, FUserKeyPair);
CryptExportKey (FUserKeyPair, 0, PUBLICKEYBLOB, 0, @Key [0], BlobSize);

Then preempted key shares on an exponent and the unit:

procedure ExtractPublicKey (Blob: PByte; BlobSize: Integer; E, N: TBigNum);
PubKeyHdr: TPublicKeyStruc;
RsaPubKey: TRsaPubKey;
ModSize: Integer;
if BlobSize <SizeOf (RsaPubKey) + SizeOf (PubKeyHdr) then
raise Exception. Create (' Invalid size of PUBLICKEYBLOB. ');
Move (Blob ^, PubKeyHdr, SizeOf (PubKeyHdr));
Inc (Blob, SizeOf (PubKeyHdr));
Move (Blob ^, RsaPubKey, SizeOf (RsaPubKey));
Inc (Blob, SizeOf (RsaPubKey));
ModSize: = RsaPubKey.bitlen shr 3;
if ModSize> BlobSize - SizeOf (RsaPubKey) - SizeOf (PubKeyHdr) then
raise Exception. Create (' Invalid size of PUBLICKEYBLOB. ');
E.CopyDigit (RsaPubKey.pubexp);
N.CopyBytes (Blob, ModSize);

Since in the function description CryptDecrypt it is told that it uses PKCS #1 Padding implemented it thus:

function PKCS1Padding (Data: Pointer; Size: Integer; BitLen: Integer): TBytes;
Bound: Integer;
Index: Integer;
if (BitLen mod 8> 0) or (Size + 11> BitLen shr 3) then
raise Exception. Create (' Invalid bit length or data is too large. ');
Bound: = BitLen shr 3;
SetLength (Result, Bound);
PWord (Result) ^: = $0200;
Dec (Bound, Size);
for Index: = 2 to Bound - 1 do
Result [Index]: = 1 + Byte (Random (255));
Result [Bound]: = $00;
Move (Data ^, Result [Bound + 1], Size);

C enciphering looks somehow so:

Message: string;
PubKey: TBytes;
Binary: TBytes;
MsgNum: TBigNum;
CAPI.PublicKeyExport (PubKey);//CAPI -  a wrapper over CryptoAPI
//RSA - class RSA from library uCrypto: https://github.com/arkusuma/uCrypto
ExtractPublicKey (PByte (PubKey), Length (PubKey), RSA.E, RSA.N);
Binary: = PKCS1Padding (PByte (Message), Length (Message) * SizeOf (Char), 1024);
MsgNum: = TBigNum. CreateBytes (PByte (Binary), Length (Binary));
Assert (MsgNum. Compare (RSA.N) <0, ' M must be in range of 0. N-1 ');
RSA.Encrypt (MsgNum);//inline-function for call MsgNum. PowMod (E, N);

And as a result at text decryption during this moment we receive NTE_BAD_DATA:

if not CryptDecrypt (FUserKeyPair, 0, TRUE, 0, Data, DataSize) then
RaiseLastOSErrorEx (sFailedDecryption);

Enciphering and decryption that in uCrypto that in CryptoAPI work normally if to decrypt in the same library in what it is ciphered. And here is how them to force to work among themselves? Probably somebody knows any nuances which I missed?
P.S: Enciphering is required  without CryptoAPI since as a result the data can be ciphered there where it is not present (linux, etc), at present it not working application, and the test bed where I try to understand as it generally works.


Re: Microsoft CrytoAPI and RSA

, understood, the data after PKCS1Padding () needed to be turned...


Re: Microsoft CrytoAPI and RSA

Would add...


Re: Microsoft CrytoAPI and RSA

makhaon wrote:

Would add...

There there is nothing to add, one line to change (BE = Big-Endian):

MsgNum: = TBigNum. CreateBytes>>> BE <<<(PByte (Binary), Length (Binary));

After that all works. Simply I when experimented the unit tried so to load, did not help. And it appears it was necessary to turn the message, since it on-default in Big-Endian a format.