I found a solution.
PHP generates keys with extra fields in ASN.1 format compare to CryptoAPI keys.
1. I decoded base64 key into a binary file with help of this tool: base64 decoder
2. Then I just cut from this file first 26 bytes to the next header sequence starting from something like: "30 xx xx" and saved it.
3. And encoded this file back to base64 with: base64 encoder
Now I can import public and private keys into CryptoAPI without problems with next code:
// key types
const
PKCS_RSA_PRIVATE_KEY = LPCSTR(43);
PKCS_RSA_PUBLIC_KEY = LPCSTR(19);
function ImportKey(hProv: HCRYPTPROV; KeyType: pointer; key: string): hKey;
var
BuffSize, BlobSize: longword;
buff, blob: pointer;
begin
result := 0;
buff := nil;
blob := nil;
try
if not(CryptStringToBinary(PWideChar(key), 0, 1, nil, @BuffSize, nil, nil)) then
exit;
GetMem(buff, BuffSize);
if not(CryptStringToBinary(PWideChar(key), 0, 1, buff, @BuffSize, nil, nil)) then
exit;
if not(CryptDecodeObjectEx(X509_ASN_ENCODING or PKCS_7_ASN_ENCODING,
KeyType, buff, BuffSize, 0, nil, nil, @BlobSize)) then
exit;
GetMem(blob, BlobSize);
if not(CryptDecodeObjectEx(X509_ASN_ENCODING or PKCS_7_ASN_ENCODING,
KeyType, buff, BuffSize, 0, nil, blob, @BlobSize)) then
exit;
if not(CryptImportKey(hProv, blob, BlobSize, 0, 0, @result)) then
exit;
finally
if buff <> nil then
FreeMem(buff);
if blob <> nil then
FreeMem(blob);
end;
end;