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 , BlobSize); ...
Then preempted key shares on an exponent and the unit:
procedure ExtractPublicKey (Blob: PByte; BlobSize: Integer; E, N: TBigNum); var PubKeyHdr: TPublicKeyStruc; RsaPubKey: TRsaPubKey; ModSize: Integer; begin 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); end;
function PKCS1Padding (Data: Pointer; Size: Integer; BitLen: Integer): TBytes; var Bound: Integer; Index: Integer; begin 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); end;
C enciphering looks somehow so:
var 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)); try 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.