0

我找到了一个用于生成 RSA KeyPair 和加密/解密的简单单元。它适用于小字符串,但在较大的文本上我得到错误:错误长度。

可能是什么原因,这里是单位,单位 wcrypt2 你可以在这里下载

在德尔福 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.
4

2 回答 2

0

简而言之,C# 说明文比密钥大小的 1/2 长得多会导致错误。出于安全目的,大多数语言可能都是相同的。对于较长的消息,使用 RSA 传递密钥以进行对称加密,例如 AES。

于 2013-02-04T15:07:59.123 回答
0

非对称加密将数据限制为小于密钥大小,存在诸如 OAEP 之类的 42 字节的填充。

如果您必须进行非对称加密,即需要一个密钥对,请使用混合加密,这基本上就是 https 所做的。请参阅混合密码系统

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

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

于 2017-12-27T12:46:14.173 回答