Delphi Windows Crypto Api错误长度

Delphi Windows Crypto Api错误长度,delphi,cryptoapi,Delphi,Cryptoapi,我找到了一个生成RSA密钥对和加密/解密的简单单元。它在小字符串上运行良好,但在较大的文本上我得到错误:错误的长度 原因可能是什么,这是你可以下载的装置,装置wcrypt2 在Delphi 2010上测试 unit Crypt_RSA; interface uses Windows, Classes, SysUtils, WCrypt2; function RSAGenerateKeys(var PrivateKey, PublicKey: String): Boolean; func

我找到了一个生成RSA密钥对和加密/解密的简单单元。它在小字符串上运行良好,但在较大的文本上我得到错误:错误的长度

原因可能是什么,这是你可以下载的装置,装置wcrypt2

在Delphi 2010上测试

unit Crypt_RSA;

interface

uses
  Windows, Classes, SysUtils, WCrypt2;

function RSAGenerateKeys(var PrivateKey, PublicKey: String): Boolean;
function RSAEncrypt(Source, Key: String): String;
function RSADecrypt(Source, Key: String): String;

implementation

function RSAGenerateKeys(var PrivateKey, PublicKey: String): Boolean;
const
  RSA1024BIT_KEY = $04000000;

var
  RSA: HCRYPTPROV;
  HKeyPair: HCRYPTKEY;
  Pair: TStringStream;
  buflen: DWORD;

  function SetKey(BlobDef: Cardinal; var Key: String): Boolean;
  begin
    Result := Bool(CryptExportKey(HKeyPair, 0, BlobDef, 0, nil, @buflen));
    if Result then
    begin
      Pair.SetSize(buflen);
      Result := Bool(CryptExportKey(HKeyPair, 0, BlobDef, 0, PByte(Pair.Memory), @buflen));
    end;

    Key := Pair.ReadString(buflen);
    Pair.Seek(0, soBeginning);
  end;

begin
  Pair := TStringStream.Create;

  Result := Bool(CryptAcquireContext(@RSA, nil, nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT));
  if Result then
    Result := Bool(CryptGenKey(RSA, AT_KEYEXCHANGE, RSA1024BIT_KEY or CRYPT_EXPORTABLE, @HKeyPair));

  if Result then
    Result := SetKey(PRIVATEKEYBLOB, PrivateKey);
  if Result then
    Result := SetKey(PUBLICKEYBLOB, PublicKey);

  CryptDestroyKey(HKeyPair);
  CryptReleaseContext(RSA, 0);
  FreeAndNil(Pair);
end;

function RSAEncrypt(Source, Key: String): String;
var
  KeyPair: TStringStream;
  RSA: HCRYPTPROV;
  HPair: HCRYPTKEY;
  DDataSize, EDataSize: DWORD;

begin
  Result := '';
  KeyPair := TStringStream.Create(Key);
  if CryptAcquireContext(@RSA, nil, nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) then
  try
    if CryptImportKey(RSA, PByte(KeyPair.Memory), KeyPair.Size, 0, 0, @HPair) then
    try
      EDataSize := SizeOf(Source);
      if CryptEncrypt(HPair, 0, true, 0, nil, @EDataSize, 0) then
      begin
        Result := Source;
        SetLength(Result, EDataSize);
        DDataSize := Length(Source) * SizeOf(Char);
        if not(CryptEncrypt(HPair, 0, True, 0, PByte(PChar(Result)), @DDataSize, EDataSize)) then
          Result := '';
      end;
    finally
      CryptDestroyKey(HPair);
    end;
  finally
  CryptReleaseContext(RSA, 0);
  end;
  FreeAndNil(KeyPair);
end;

function RSADecrypt(Source, Key: String): String;
var
  KeyPair: TStringStream;
  RSA: HCRYPTPROV;
  HPair: HCRYPTKEY;
  EDataSize: DWORD;

begin
  KeyPair := TStringStream.Create(Key);
  Result := '';
  if CryptAcquireContext(@RSA, nil, nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) then
  try
    if CryptImportKey(RSA, PByte(KeyPair.Memory), KeyPair.Size, 0, 0, @HPair) then
    try
      Result := Source;
      EDataSize := Length(Result);
      if not Bool(CryptDecrypt(HPair, 0, True, 0, PByte(PChar(Result)), @EDataSize)) then
        EDataSize := 0;
      SetLength(Result, EDataSize div SizeOf(Char));
    finally
      CryptDestroyKey(HPair);
    end;
  finally
    CryptReleaseContext(RSA, 0);
  end;
  FreeAndNil(KeyPair);
end;

end.

简言之,C#表示明文长度远远超过密钥大小的1/2将导致错误。出于安全目的,大多数语言可能都是这样。对于较长的消息,请使用RSA传递对称加密(如AES)的密钥。

非对称加密将数据限制在小于密钥大小的范围内,还有填充(如42字节的OAEP)

如果必须使用非对称加密(即需要密钥对),请使用混合加密,这基本上就是https所做的。看

对于混合加密,基本上创建一个随机对称加密密钥,使用非对称加密加密对称密钥,使用对称密钥加密数据,并将这两种加密打包在一起


你为什么不想要对称加密?它速度更快,基本上可以处理任意大小的数据?AES是加密的主力。

我不想要对称加密我应该做什么您可以将密钥大小增加到2048位。但这仍然等于256个8位字符,请记住,大于该大小的1/2会抛出错误。因此,如果密钥大小为2048位,您可以发送大约128个字符长的消息。如果对多条消息重复使用密钥,则可能会影响安全性。我对常见做法的理解是,使用非对称建立连接并共享对称密钥,然后使用对称加密处理会话的其余部分,这会更快,而且不会受到纯文本大小限制的影响。会话不需要仅使用混合加密。虽然答案的基本内容是正确的,但有几个部分是错误的,如果有更正,这将是一个更好的答案。