0

RSA KeyPair を生成し、暗号化/復号化するための単純なユニットを見つけました。小さな文字列では問題なく動作しますが、大きなテキストではエラーが発生します: Bad Length.

原因は何でしょうか。これがユニットです。ここからダウンロードできるユニット 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.
4

2 に答える 2

0

一言で言えば、C#は、キーサイズの1/2よりはるかに長い平文はエラーを引き起こすと言っています。セキュリティ上の理由から、ほとんどの言語で同じである可能性があります。より長いメッセージの場合は、RSAを使用して、AESなどの対称暗号化用のキーを渡します。

于 2013-02-04T15:07:59.123 に答える
0

非対称暗号化は、データをキー サイズ未満に制限します。42 バイトの OAEP などのパディングがあります。

非対称暗号化が必要な場合、つまり鍵ペアが必要な場合は、本質的に https が行うハイブリッド暗号化を使用してください。ハイブリッド暗号システムを参照してください。

ハイブリッド暗号化では、基本的にランダム対称暗号化キーを作成し、非対称暗号化で対称キーを暗号化し、対称キーでデータを暗号化し、2 つの暗号化を一緒にパッケージ化します。

対称暗号化が必要ないのはなぜですか? はるかに高速で、基本的にあらゆるデータサイズを処理できますか? AES は暗号化の主力製品です。

于 2017-12-27T12:46:14.173 に答える