// Шифрование SOAP-запроса
class procedure TCrypto.EncryptSOAPRequest(FCryptoProvider: HCRYPTPROV; ARemoteCertPath: string; ASOAPRequest: IXMLDocument);
var
  hEphemeralKey, hAgreeKey, hSessionKey: HCRYPTKEY;
  size, keyParam,
  BufLen, DataLen, sourceDataLen: DWORD;
  pbPubCertData,
  remotePublicKeyBlob, pbSenderPublicKeyBlob,
  sessionKeyBlob,
  sessionSV, sessionKey, sessionMAC,
  SourseData,
  CipherValue, CipherData,
  publicKey,
  initVector, encryptedData: TBytes;
  keyParamAsBytes: TBytes;
  provType: DWORD;
  s: string;
  sm: TStringStream;
var
  FCertContext: PCCERT_CONTEXT;
  remotePublicKey: HCRYPTKEY;
begin
  // Получение дескриптора закрытого ключа отправителя. нам нужно для получения сертификата который вставим в запрос
  pbPubCertData := GetProviderPublicCertificate(FCryptoProvider);
  hEphemeralKey := 0; hAgreeKey := 0;  hSessionKey := 0;
  sm := TStringStream.Create;
  CryptAcquireContext(@FCryptoProvider, nil,  nil, PROV_GOST_2012_256, CRYPT_VERIFYCONTEXT);
  try
    size := SizeOf(provType);
    CheckCryptoCall(CryptGetProvParam(FCryptoProvider, PP_PROVTYPE, @provType, @size, 0));
    Assert(provType = PROV_GOST_2012_256);
    // Загрузка PUBLICKEYBLOB из сертификата, открытие файла, в котором содержится открытый ключ получателя.
    memStream := TMemoryStream.Create;
    memStream.LoadFromFile(ARemoteCertPath);    
    FCertContext := CertCreateCertificateContext(PKCS_7_ASN_ENCODING or X509_ASN_ENCODING, memStream.Memory, memStream.Size);
    // импорт информации по открытому ключу
    CryptImportPublicKeyInfoEx(FCryptoProvider, PKCS_7_ASN_ENCODING or X509_ASN_ENCODING, @FCertContext.pCertInfo.SubjectPublicKeyInfo, 0, 0, nil, @remotePublicKey);
    CryptExportKey(remotePublicKey, 0, PUBLICKEYBLOB, 0, nil, @size);
    SetLength(remotePublicKeyBlob, size);
    CryptExportKey(remotePublicKey, 0, PUBLICKEYBLOB, 0, @remotePublicKeyBlob [1], @size);
    // генерация эфемерной ключевой пары
    CheckCryptoCall(CryptGenKey(FCryptoProvider, CALG_DH_GR3410_12_256_EPHEM , CRYPT_EXPORTABLE, @hEphemeralKey));
    // Проверяем что параметры эфемерного ключа также установлены в TK26Z
    CheckCryptoCall(CryptGetKeyParam(hEphemeralKey, KP_CIPHEROID, nil, @size, 0));
    SetLength(keyParamAsBytes, size);
    CheckCryptoCall(CryptGetKeyParam(hEphemeralKey, KP_CIPHEROID, @keyParamAsBytes[0], @size, 0));
    Assert(TEncoding.ANSI.GetString(keyParamAsBytes) = '1.2.643.7.1.2.5.1.1'#0); // szOID_Gost28147_89_TC26_Z_ParamSet + #0
    // Экспорт открытого ключа в BLOB из локального закрытого.
    CheckCryptoCall(CryptExportKey(hEphemeralKey, 0, PUBLICKEYBLOB, 0, nil, @size));
    SetLength(pbSenderPublicKeyBlob, size);
    CheckCryptoCall(CryptExportKey(hEphemeralKey, 0, PUBLICKEYBLOB, 0, @pbSenderPublicKeyBlob[1], @size));
    // получаем значение открытого ключа отправителя из PUBLICKEYBLOB
    publicKey := Copy(pbSenderPublicKeyBlob, Length(pbSenderPublicKeyBlob) - 64+1, 64);
    // Получение ключа согласования импортом открытого ключа получателя зашифрованного сообщения (ФСС)
    // на локальном закрытом ключе отправителя зашифрованного сообщения.
    CheckCryptoCall(CryptImportKey(FCryptoProvider, @remotePublicKeyBlob[1], Length(remotePublicKeyBlob),
                                   hEphemeralKey, 0, @hAgreeKey));
    // Установка PRO_EXPORT алгоритма ключа согласования
    keyParam := CALG_PRO_EXPORT;
    CheckCryptoCall(CryptSetKeyParam(hAgreeKey, KP_ALGID, @keyParam, 0));
    // Создание случайного сессионного ключа, которым будет зашифровано сообщение.
    CheckCryptoCall(CryptGenKey(FCryptoProvider, CALG_G28147, CRYPT_EXPORTABLE, @hSessionKey));
    // экспорт сессионного ключа в BLOB
    CheckCryptoCall(CryptExportKey(hSessionKey, hAgreeKey, SIMPLEBLOB, 0, nil, @size));
    SetLength(sessionKeyBlob, size);
    CheckCryptoCall(CryptExportKey(hSessionKey, hAgreeKey, SIMPLEBLOB, 0, @sessionKeyBlob[1], @size));
    // Выделение из BLOB-а контенты компонент UKM, сессионного ключа, MAC. Структуру BLOB-а см. в GetResponseKeysBlobs.
    sessionSV  := Copy(sessionKeyBlob, 16+1, 8);
    sessionKey := Copy(sessionKeyBlob, 24+1, 32);
    sessionMAC := Copy(sessionKeyBlob, 56+1, 4);
    // Получение из сессионного ключа параметра вектора инициализации. Далее он прикрепляется
    // к зашифрованному сообщению (см. ниже)
    CheckCryptoCall(CryptGetKeyParam(hSessionKey, KP_IV, nil, @size, 0));
    SetLength(initVector, size);
    CheckCryptoCall(CryptGetKeyParam(hSessionKey, KP_IV, @initVector[1], @size, 0));
    // Установка режима шифрования CBC
    keyParam := CRYPT_MODE_CBC;
    CheckCryptoCall(CryptSetKeyParam(hSessionKey, KP_MODE, @keyParam, 0));
    // режим паддинга
    keyParam := ISO10126_PADDING;
    CheckCryptoCall(CryptSetKeyParam(hSessionKey, KP_PADDING, @keyParam, 0));
    //--------------------------------------------------------------------
    // Зашифрование сессионного ключа.
    //--------------------------------------------------------------------
    // Получение контента базового SOAP-запроса, который будет зашифрован перед отправкой получателю.
    SourseData :=  TEncoding.UTF8.GetBytes(ASOAPRequest.DocumentElement.XML);
    // Шифрование базового SOAP-запроса
    encryptedData := SourseData;
    BufLen:=Length(encryptedData);
    DataLen:=Length(encryptedData);
    // Вычисляем необходимый размер выходного буфера
    CryptEncrypt(hSessionKey,0,true,0,nil,@BufLen,0);
    // Выделяем память для буфера и шифруем
    SetLength(SourseData,BufLen);
    CryptEncrypt(hSessionKey,0,true,0, @encryptedData[1], @DataLen, BufLen);
    CipherData := initVector+encryptedData;
    // Формирование структуры GostR3410-KeyTransport, которая передается получателю зашифрованного сообщения
    // в служебном заголовке этого сообщения. Далее получатель на основе этой структуры формирует сессионный ключ,
    // которым дешифрует зашифрованное сообщение отправителя.
    // transportBlob при необходимости можно сохранить в бинарный файл и открыть его редактором ASN1, например,
    // 
https://lapo.it/asn1js/  - онлайн
    // 
https://www.codeproject....Articles/4910/ASN-Editor - десктоп
    CipherValue :=[$30, $81, $A9, $30, $28, 4, $20]+
     SessionKey+
     [4, 4]+
     SessionMAC+
     [$A0, $7D, 6, 9, $2A, $85, 3, 7, 1, 2, 5, 1, 1]+
     [$A0, $66, $30, $1F, 6, 8, $2A, $85, 3, 7, 1, 1, 1, 1]+
     [$30, $13, 6, 7, $2A, $85, 3, 2, 2, $24, 0]+
     [6, 8, $2A, $85, 3, 7, 1, 1, 2, 2, 3]+
     [$43, 0, 4, $40]+
     PublicKey+
     [$4, $8]+
     SessionSV;
    // Формирование структуры зашифрованного SOAP-запроса.
    SetEncryptedContent(ASOAPRequest,
                        CipherData,
                        CipherValue,
                        pbPubCertData);
  finally
    if hSessionKey <> 0 then
      CheckCryptoCall(CryptDestroyKey(hSessionKey));
    if hAgreeKey <> 0 then
      CheckCryptoCall(CryptDestroyKey(hAgreeKey));
    if hEphemeralKey <> 0 then
      CheckCryptoCall(CryptDestroyKey(hEphemeralKey));
    SetLength(sessionKeyBlob, 0);
    SetLength(pbSenderPublicKeyBlob, 0);
    SetLength(CipherValue, 0);
    SetLength(sessionSV, 0);
    SetLength(sessionKey, 0);
    SetLength(sessionMAC, 0);
    SetLength(initVector, 0);
    SetLength(encryptedData, 0);
  end;
end;
В SetEncryptedContent собираю все в xml. Все переменные TBytes кодирую в Base64 строку (например TNetEncoding.Base64.EncodeBytesToString(CipherData))
Ошибка таже.