Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi JPK-CryptoAPI RSA 256/ECB/PKCS#1使用证书中的公钥进行一次性密码加密(解决方案)_Delphi_Delphi 2010_Solution_Cryptoapi - Fatal编程技术网

Delphi JPK-CryptoAPI RSA 256/ECB/PKCS#1使用证书中的公钥进行一次性密码加密(解决方案)

Delphi JPK-CryptoAPI RSA 256/ECB/PKCS#1使用证书中的公钥进行一次性密码加密(解决方案),delphi,delphi-2010,solution,cryptoapi,Delphi,Delphi 2010,Solution,Cryptoapi,波兰政府(MF-财政部)最近实施了SAF-T(标准审计文件Tax/pl:JPK-Jednolity Plik Kontrolny)。我很难以正确的方式实现此解决方案的一个关键部分。此部分将使用从MF提供的证书文件加载的公钥,使用MS CryptoAPI中的RSA 256/ECB/PKCS#1算法对发送到Azure云存储的用于加密文件的用户生成密码进行加密。我的工作解决方案是(使用): 希望这可能对某人有所帮助,再见。我的工作解决方案是(使用): 希望这可能会对某人有所帮助,再见。必须将“Fill

波兰政府(MF-财政部)最近实施了SAF-T(标准审计文件Tax/pl:JPK-Jednolity Plik Kontrolny)。我很难以正确的方式实现此解决方案的一个关键部分。此部分将使用从MF提供的证书文件加载的公钥,使用MS CryptoAPI中的RSA 256/ECB/PKCS#1算法对发送到Azure云存储的用于加密文件的用户生成密码进行加密。

我的工作解决方案是(使用):


希望这可能对某人有所帮助,再见。

我的工作解决方案是(使用):

希望这可能会对某人有所帮助,再见。

必须将“FillChar(rsa,len+512,0)”更改为“FillChar(rsa[0],len+512,0)”,以使其正常工作。我用它来加密可以在SQL Server中解密的字符串。该证书在TSQL中生成,带有“创建证书”和“备份证书…”导出。。。归档”。该文件具有DER格式,因此我将“CryptStringToBinaryA()”替换为“Move(cert.Memory^,derCert[1],cert.Size)”不需要reverse()。必须将“FillChar(rsa,len+512,0)”更改为“FillChar(rsa[0],len+512,0)”,才能正常工作。我用它来加密可以在SQL Server中解密的字符串。该证书在TSQL中生成,带有“创建证书”和“备份证书…”导出。。。归档”。该文件具有DER格式,因此我将“CryptStringToBinaryA()”替换为“Move(cert.Memory^,derCert[1],cert.Size)”不需要反向()。
unit CryptoAPI_RSA;
// The MIT License (MIT)
// 
// Copyright (c) 2016 Grzegorz Molenda
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
interface

uses
  SysUtils,
  Classes;

function CryptoAPI_Encrypt_RSA(const Input: TBytes; const cert: TMemoryStream): String;

implementation

uses
  Windows,
  StrUtils,
  JwaWinCrypt,
  JwaWinError,
  EncdDecd;

type
  ERSAEncryptionError = class(Exception);

function WinError(const RetVal: BOOL; const FuncName: String): BOOL;
var
  dwResult: Integer;
begin
  Result:=RetVal;
  if not RetVal then begin
    dwResult:=GetLastError();
    raise ERSAEncryptionError.CreateFmt('Error [x%x]: %s failed.'#13#10'%s', [dwResult, FuncName, SysErrorMessage(dwResult)]);
  end;
end;

procedure reverse(var p: TBytes; len: Integer);
var
  i, j: Integer;
  temp: Byte;
begin
  i:=0;
  j:=len - 1;
  while i < j do begin
    temp:=p[i];
    p[i]:=p[j];
    p[j]:=temp;
    Inc(i);
    Dec(j);
  end;
end;

function CryptoAPI_Encrypt_RSA(const Input: TBytes; const cert: TMemoryStream): String;
var
  derCert: AnsiString;
  derCertLen: Cardinal;
  hProv: HCRYPTPROV;
  certContext: PCCERT_CONTEXT;
  certPubKey: HCRYPTKEY;
  len: LongWord;
  rsa: TBytes;
  ins: TMemoryStream;
  ous: TStringStream;
begin
  Result:='';
  if (cert <> Nil) and (cert.Size > 0) then begin
    SetLength(derCert, 4096);
    FillChar(derCert[1], 4096, 0);
    // Convert from PEM format to DER format - removes header and footer and decodes from base64
    WinError(CryptStringToBinaryA(PAnsiChar(cert.Memory), cert.Size, CRYPT_STRING_BASE64HEADER, @derCert[1], derCertLen, Nil), 'CryptStringToBinaryA');
    SetLength(derCert, derCertLen);
    try
      // Get the certificate context structure from a certificate.
      certContext:=CertCreateCertificateContext(X509_ASN_ENCODING or PKCS_7_ASN_ENCODING, @derCert[1], derCertLen);
      WinError(certContext <> Nil, 'CertCreateCertificateContext');
      try
        hProv:=0;
        WinError(CryptAcquireContext(hProv, Nil, Nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT), 'CryptAcquireContext'); // flag CRYPT_VERIFYCONTEXT - for backward compatibility with win2003server (and probably with win10pro+)
        try
          // Get the public key information for the certificate.
          certPubKey:=0;
          WinError(CryptImportPublicKeyInfo(hProv, X509_ASN_ENCODING or PKCS_7_ASN_ENCODING,
                                            @certContext.pCertInfo.SubjectPublicKeyInfo, certPubKey), 'CryptImportPublicKeyInfo');
          len:=Length(Input);
          if len > 0 then begin
            SetLength(rsa, len + 512);
            FillChar(rsa, len + 512, 0);
            try
              CopyMemory(@rsa[0], @Input[0], len);
              // encrypt our Input buffer
              WinError(CryptEncrypt(certPubKey, 0, True, 0, @rsa[0], len, len + 512), 'CryptEncrypt');
              SetLength(rsa, len);
              // IMPORTANT !!!
              // .Net RSA algorithm is BIG-ENDIAN,
              // CryptoAPI is LITTLE-ENDIAN, 
              // so reverse output before sending to Azure Cloud Storage
              reverse(rsa, len);
              ins:=TMemoryStream.Create;
              try
                ins.Write(rsa[0], len);
                ins.Position:=0;
                ous:=TStringStream.Create;
                try
                  EncodeStream(ins, ous);
                  ous.Position:=0;
                  Result:=ous.DataString;
                  Result:=ReplaceStr(Result, #13#10, '');
                finally
                  ous.Free;
                end;
              finally
                ins.Free;
              end;
            finally
              SetLength(rsa, 0);
            end;
          end;
        finally
          WinError(CryptReleaseContext(hProv, 0), 'CryptReleaseContext');
        end;
      finally
        CertFreeCertificateContext(certContext);
      end;
    finally
      SetLength(derCert, 0);
    end;
  end;
end;

end.
var
  cf: TMemoryStream;
  input: TBytes;
  output: String;
begin
  if Edit1.Text = '' then
    Exit;
  Memo1.Clear;
  cf:=TMemoryStream.Create;
  try
    cf.LoadFromFile('cert.pem'); // certificate with public key
    input:=TEncoding.Default.GetBytes(Edit1.Text);
    try
      output:=CryptoAPI_Encrypt_RSA(input, cf);
    finally
      SetLength(input, 0);
    end;
    Memo1.Lines.Text:=output;
  finally
    cf.Free;
  end;
end;