10

私は ROT13 よりも洗練されたものを探していますが、ライブラリを必要としないものを探しています (できれば、ユニットでさえなく、関数をドロップするだけです)。

ユーザーが提供したパスワードを使用して、特定の文字列を対称的に暗号化/復号化したいと考えています。ただし、.INI ファイルに格納できる必要があるという意味で、結果は文字列でなければなりません。

これを行うための簡単な機能を持っている人はいますか (delphi XE2)? 今日、Google は私の友達ではありません。

前もって感謝します


[アップデート] / [報奨金] 明確にするために (元々そうでなかった場合は申し訳ありません)、ハッシュは必要ありません。ユーザーがエントリを追加/変更/削除できるリスト ボックスがあります。プログラムを閉じたときにそれらを .INI ファイルに保存し、再起動時にリロードしたいと考えています。.INI ファイルを見ている人 (たとえば、メモ帳で開いている人) は、これらの文字列を読み取ることができないはずです。

コンポーネントをバイナリとしてストリーミングすることもできると思いますが、念のため、ユーザーが提供するパスワードを使用して文字列を暗号化します。このアプリケーションの目的では、.INI ファイルのセクション名または keyte 値が人間が判読できるかどうかは問題ではありません。データを暗号化したいだけで、ディスクに保存するときに次のようなリストが表示されます。

[config]
numEntries=3

[listbox]
0=ywevdyuvewfcyuw
1=edw
2=hr4uifareiuf
4

5 に答える 5

11

免責事項

この回答で使用されている暗号化アルゴリズムは非常に基本的なものであり、中程度から高度な暗号化スキルを持つ個人なら誰でも簡単に破ることができます。OPはライブラリを必要としない単純な対称ソリューションを求めているため、ソリューションで使用されます。

原理

このソリューションは、 XOR 暗号に基づいています。ウィキペディアから:

暗号化では、単純な XOR 暗号は加法的暗号の一種であり、次の原則に従って動作する暗号化アルゴリズムです。

AX 0 = A、

アクサ=0、

(AXB) XC = AX (BXC)、

(BXA) XA = BX 0 = B,

ここで、X は XOR 演算を示します。

パズルのピース

私が提案するソリューションは、次の基本的なルーチンに基づいています。

function XorCipher(const Key, Source: TBytes): TBytes;
var
  I: Integer;
begin
  if Length(Key) = 0 then
    Exit(Source);
  SetLength(Result, Length(Source));
  for I := Low(Source) to High(Source) do
    Result[I] := Key[I mod Length(Key)] xor Source[I];
end;

このルーチンは、キーとソース データをバイト配列として受け取り、結果の XOR されたバイト配列を返します。同じキーが両方の操作で使用される場合、情報の暗号化と復号化には同じルーチンが機能します。暗号化する場合、ソースはプレーン データであり、復号化する場合、ソースは暗号化されたデータです。

結果を文字列として格納できるようにするために、2 つの補助ルーチンを作成しました。1 つはバイト配列を 16 進数のテキスト シーケンスに変換し、もう 1 つは逆変換を実行します。

function BytesToStr(const Bytes: TBytes): string;
var
  I: Integer;
begin
  Result := '';
  for I := Low(Bytes) to High(Bytes) do
    Result := Result + LowerCase(IntToHex(Bytes[I], 2));
end;

function StrToBytes(const value: string): TBytes;
var
  I: Integer;
begin
  SetLength(Result, Length(value) div 2);
  for I := Low(Result) to High(Result) do
    Result[I] := StrToIntDef('$' + Copy(value, (I * 2) + 1, 2), 0);
end;

この基盤があれば、必要なものすべてを構築できます。便宜上、コードをテストするために、次のような他のルーチンをいくつか作成しました。

  • これは、キーをexe内に保存し、TBytes値として取得するためのものです

    function GetKey: TBytes;
    begin
      Result := TArray<Byte>.Create(
         $07, $14, $47, $A0, $F4, $F7, $FF, $48, $21, $32
       , $AF, $87, $09, $8E, $B3, $C0, $7D, $54, $45, $87
       , $8A, $A8, $23, $32, $00, $56, $11, $1D, $98, $FA
      );
    end;
    

    XorCipher ルーチン内のデータを暗号化するためにロールするため、任意の長さのキーを指定できます。

  • これは、そのキーを使用して特定の文字列を適切にエンコードするためのものです。

    function XorEncodeStr(const Source: string): string; overload;
    var
      BSource: TBytes;
    begin
      SetLength(BSource, Length(Source) * SizeOf(Char));
      Move(Source[1], BSource[0], Length(Source) * SizeOf(Char));
      Result := XorEncodeToStr(GetKey, BSource);
    end;
    
  • エンコードされた文字列を文字列に適切にデコードするための this other

    function XorDecodeStr(const Source: string): string; overload;
    var
      BResult: TBytes;
    begin
      BResult := XorDecodeFromStr(GetKey, source);
      Result := TEncoding.Unicode.GetString( BResult );
    end;
    

INI ファイルの書き込み

INI ファイルを読み書きする場所からアクセスできるこのルーチンを使用すると、次のように簡単に読み書きできます。

procedure TForm1.SaveIni;
var
  Ini: TIniFile;
  I: Integer;
begin
  Ini := TIniFile.Create('.\config.ini');
  try
    Ini.WriteInteger('config', 'NumEntries', ListBox1.Items.Count);
    for I := 0 to ListBox1.Items.Count - 1 do
      Ini.WriteString('listbox', IntToStr(I), XorEncodeStr(listbox1.Items[I]));
  finally
    Ini.Free;
  end;
end;

procedure TForm1.LoadIni;
var
  Ini: TIniFile;
  Max, I: Integer;
begin
  ListBox1.Items.Clear;
  Ini := TIniFile.Create('.\config.ini');
  try
    Max := Ini.ReadInteger('config', 'NumEntries', 0);
    for I := 0 to Max - 1 do
      ListBox1.Items.Add(
        XorDecodeStr(Ini.ReadString('listbox', IntToStr(I), ''))
      );
  finally
    Ini.Free;
  end;
end;

これは、ソリューションをテストするためだけに記述されているため、すぐに使用できるコードではありませんが、堅牢にするための出発点でもあります。

注意事項

これは強力な暗号化方式ではないため、非常に機密性の高い情報を保存するためにこれに依存しないでください。1 つの弱点は、キーがプレーンな形式で exe 内に含まれていることです。これに取り組むことはできますが、主な弱点はアルゴリズム自体です。

この問題の例を以下に示します。Unicode Delphi 文字列を UTF-16 形式でエンコードしているため、各文字の 2 番目のバイトは通常ゼロです (東部または非ラテン アルファベットの国にいる場合を除く)。 )、エンコードされた保存済み文字列でキーの繰り返しの正確なバイトを見つけることができます。エンコードされたデータの単純な 16 進数表現を使用しないことで、これを目立たなくすることができます (たとえば、既にここで提案されているように、base64 を使用してエンコードします)。

AnsiStrings を使用して、キーのこの部分が明らかにならないようにするか、偶数位置に明示的なゼロ バイト (またはその他の定数バイト) を指定してキーをコーディングできます。

ソフトウェアのユーザーが暗号化について教育を受けていない場合、これは何でも機能しますが、実際には、中程度の知識と優れたスキルを持つ人なら誰でも、データを分析することでキーを取得できます. ユーザーがエンコードされていない値を知っている場合は、簡単になります。

于 2013-01-22T09:36:57.950 に答える
10

これは Tinifile の代替です。
ReadString と WriteString はオーバーライドされます。これらは内部で Read/WriteFloat、Read/WriteInteger などに使用されます。

文字列は暗号化され、HEX 文字列として保存されます。

デモの使用法:

uses CryptingIni;
{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
 ini:TCryptingIni;
begin
    ini:=TCryptingIni.Create('C:\temp\test.ini');
    ini.UseInternalVersion(1234);
    ini.WriteFloat('Sect','Float',123.456);
    ini.WriteString('Sect2','String','How to encode');
    ini.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
 ini:TCryptingIni;
begin
    ini:=TCryptingIni.Create('C:\temp\test.ini');
    ini.UseInternalVersion(1234);
    Showmessage(FloatToStr(ini.ReadFloat('Sect','Float',0)));
    Showmessage(ini.ReadString('Sect2','String',''));
    Showmessage(ini.ReadString('SectUnkknow','Showdefault','DEFAULT'));
    ini.Free;
end;

UseInternalVersion による内部暗号化方式を使用するか、
Procedure SetCryptingData(aEncryptProc, aDecryptProc: CryptingProc; aKey: Word);で独自の手順を提供することができます。

unit CryptingIni;

// 2013 by Thomas Wassermann
interface

uses
  Windows, SysUtils, Variants, Classes, inifiles;

type

  CryptingProc = Function(const InString: String; Key: Word): String;

  TCryptingIni = Class(TInifile)
    function ReadString(const Section, Ident, Default: string): string; override;
    procedure WriteString(const Section, Ident, Value: String); override;
  private
    FEncryptProc: CryptingProc;
    FDecryptProc: CryptingProc;
    FKey: Word;
  public
    Procedure SetCryptingData(aEncryptProc, aDecryptProc: CryptingProc; aKey: Word);
    Procedure UseInternalVersion(aKey: Word);
  End;

implementation

const
  c1 = 52845;
  c2 = 22719;

Type
  TByteArray = Array [0 .. 0] of byte;

Function AsHexString(p: Pointer; cnt: Integer): String;
var
  i: Integer;
begin
  Result := '';
  for i := 0 to cnt do
    Result := Result + '$' + IntToHex(TByteArray(p^)[i], 2);
end;

Procedure MoveHexString2Dest(Dest: Pointer; Const HS: String);
var
  i: Integer;
begin
  i := 1;
  while i < Length(HS) do
  begin
    TByteArray(Dest^)[i div 3] := StrToInt(Copy(HS, i, 3));
    i := i + 3;
  end;
end;

function EncryptV1(const s: string; Key: Word): string;
var
  i: smallint;
  ResultStr: string;
  UCS: WIDEString;
begin
  Result := s;
  if Length(s) > 0 then
  begin
    for i := 1 to (Length(s)) do
    begin
      Result[i] := Char(byte(s[i]) xor (Key shr 8));
      Key := (smallint(Result[i]) + Key) * c1 + c2
    end;
    UCS := Result;
    Result := AsHexString(@UCS[1], Length(UCS) * 2 - 1)
  end;
end;

function DecryptV1(const s: string; Key: Word): string;
var
  i: smallint;
  sb: String;
  UCS: WIDEString;
begin
  if Length(s) > 0 then
  begin
    SetLength(UCS, Length(s) div 3 div 2);
    MoveHexString2Dest(@UCS[1], s);
    sb := UCS;
    SetLength(Result, Length(sb));
    for i := 1 to (Length(sb)) do
    begin
      Result[i] := Char(byte(sb[i]) xor (Key shr 8));
      Key := (smallint(sb[i]) + Key) * c1 + c2
    end;
  end
  else
    Result := s;
end;

{ TCryptingIni }

function TCryptingIni.ReadString(const Section, Ident, Default: string): string;
begin
  if Assigned(FEncryptProc) then
    Result := inherited ReadString(Section, Ident, FEncryptProc(Default, FKey))
  else
    Result := inherited ReadString(Section, Ident, Default);
  if Assigned(FDecryptProc) then
    Result := FDecryptProc(Result, FKey);
end;

procedure TCryptingIni.SetCryptingData(aEncryptProc, aDecryptProc: CryptingProc; aKey: Word);
begin
  FEncryptProc := aEncryptProc;
  FDecryptProc := aDecryptProc;
  FKey := aKey;
end;

procedure TCryptingIni.UseInternalVersion(aKey: Word);
begin
  FKey := aKey;
  FEncryptProc := EncryptV1;
  FDecryptProc := DecryptV1;
end;

procedure TCryptingIni.WriteString(const Section, Ident, Value: String);
var
  s: String;
begin
  if Assigned(FEncryptProc) then
    s := FEncryptProc(Value, FKey)
  else
    s := Value;
  inherited WriteString(Section, Ident, s);
end;

end.
于 2013-01-22T10:21:30.033 に答える
7

ハッシュと対称暗号化/復号化の両方に優れた機能を備えたDelphi Encryption Compendiumを使用しています。ユニットに分割されていますが、外部ライブラリを必要とせず、非常に高速です。

コードでの使用方法は次のとおりです。

function Encrypt(const AStr: string): string;
begin
  Result := AStr;
  with TCipher_Gost.Create do
    try
      Init(THash_SHA1.KDFx('Encryption Key', '', Context.KeySize));
      Result := EncodeBinary(Result, TFormat_HEX);
    finally
      Free;
    end;
end;

function Decrypt(const AStr: string): string;
begin
  Result := AStr;
  with TCipher_Gost.Create do
    try
      Init(THash_SHA1.KDFx('Encryption Key', '', Context.KeySize));
      Result := DecodeBinary(Result, TFormat_HEX);
    finally
      Free;
    end;
end;

GOST の代わりに任意のTCipher_*クラスを使用できます。

于 2013-01-19T07:20:02.167 に答える
5

まず、ここで使用してから使用しているwincryptユニットについては、 このリンクを参照してください。

これが暗号化のために行うことは、入力された文字列を取得し(INIを使用しているので、とにかくすべて単一の文字列ですよね?)、入力されたパスワードに基づいてWinCrypt 3DESを実行します。これにより、バイナリが生成されます。 、Base64で実行します。復号化のために、私はプロセスを逆にします。間違ったパスワードは復号化時にゴミを生成しますが、私がテストした量では、パスワードが両方のステップで正しい限り、正しく機能しているようです。もちろん、クリーンアップを忘れたかもしれませんが、そうであれば簡単に修正できます。

function DecryptStringW(instr, pwd: WideString): WideString;
// password based decryption of a string using WinCrypt API, WideString version
  var
    Key: TCryptKey;
    Hash: TCryptHash;
    Prov: TCryptProv;
    DataLen, skip, Flags: DWord;
    DataBuf: Pointer;
    outstr: WideString;
  begin
    CryptAcquireContext(Prov, nil, nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
    CryptCreateHash(Prov, CALG_SHA, nil, 0, hash);
    CryptHashData(hash, @pwd[1], Length(Pwd), 0);
    CryptDeriveKey(Prov, CALG_3DES, hash, 0, key);
    CryptDestroyHash(hash);

    CryptStringToBinaryW(pointer(instr), Length(instr), CRYPT_STRING_BASE64, nil, DataLen, skip, Flags);
    GetMem(databuf, DataLen);
    try
      CryptStringToBinaryW(pointer(instr), Length(instr), CRYPT_STRING_BASE64, DataBuf,
           DataLen, skip, Flags);
      CryptDecrypt(Key, nil, True, 0, DataBuf, Datalen);
      SetLength(outstr, datalen);
      Move(DataBuf^, outstr[1], DataLen);
      CryptReleaseContext(Prov, 0);
      Result := outstr;
    finally
      FreeMem(databuf);
    end;
 end;

 function EncryptStringW(instr, pwd: WideString): WideString;
 // password based encryption of a string, WideString version
   var
    Key: TCryptKey;
    Hash: TCryptHash;
    Prov: TCryptProv;
    DataLen, bufsize: DWord;
    databuf: PByte;
    outstr: WideString;
  begin
    CryptAcquireContext(Prov, nil, nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
    CryptCreateHash(Prov, CALG_SHA, nil, 0, hash);
    CryptHashData(hash, @pwd[1], Length(Pwd), 0);
    CryptDeriveKey(Prov, CALG_3DES, hash, 0, key);
    CryptDestroyHash(hash);
    bufsize := 0;
    DataLen := 0;
    CryptEncrypt(Key, nil, True, 0, nil, bufsize, Length(instr));
    GetMem(databuf, bufsize);
    try
      Move(instr[1], databuf^, Length(instr));
      DataLen := Length(instr);
      CryptEncrypt(Key, nil, True, 0, databuf, DataLen, bufsize);
      CryptReleaseContext(Prov, 0);
      CryptBinaryToStringW(databuf, DataLen, CRYPT_STRING_BASE64 or
              CRYPT_STRING_NOCRLF, nil, bufsize);
      SetLength(outstr, bufsize);
      CryptBinaryToStringW(databuf, DataLen, CRYPT_STRING_BASE64 or
              CRYPT_STRING_NOCRLF, @outstr[1], bufsize);
     // result, kill the three characters after the final one the base64 returns    ($D$A$0)
     // CRYPT_STRING_NOCRLF seems to mean nothing on XP, it might on other systems
     // you will need to change to the commented line if you are on Vista, 7, or 8
      Result := Copy(outstr, 1, Length(outstr) - 3);
     // Result := Outstr;
    finally
      FreeMem(databuf);
    end;
  end;

  function DecryptStringA(instr, pwd: AnsiString): AnsiString;
  // password based decryption of a string using WinCrypt API, ANSI VERSION.
    var
      Key: TCryptKey;
      Hash: TCryptHash;
      Prov: TCryptProv;
      DataLen, skip, Flags: DWord;
      DataBuf: Pointer;
      outstr: AnsiString;
    begin
      CryptAcquireContext(Prov, nil, nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
      CryptCreateHash(Prov, CALG_SHA, nil, 0, hash);
      CryptHashData(hash, @pwd[1], Length(Pwd), 0);
      CryptDeriveKey(Prov, CALG_3DES, hash, 0, key);
      CryptDestroyHash(hash);

      CryptStringToBinaryA(pointer(instr), Length(instr), CRYPT_STRING_BASE64, nil, DataLen, skip, Flags);
      GetMem(databuf, DataLen);
      try
        CryptStringToBinaryA(pointer(instr), Length(instr), CRYPT_STRING_BASE64, DataBuf, DataLen, skip, Flags);
        CryptDecrypt(Key, nil, True, 0, DataBuf, Datalen);
        SetLength(outstr, datalen);
        Move(DataBuf^, outstr[1], DataLen);
        CryptReleaseContext(Prov, 0);
        Result := outstr;
      finally
        FreeMem(databuf);
      end;
   end;

  function EncryptStringA(instr, pwd: AnsiString): AnsiString;
   // password based encryption of a string, ANSI version
    var
      Key: TCryptKey;
      Hash: TCryptHash;
      Prov: TCryptProv;
      DataLen, bufsize: DWord;
      databuf: PByte;
      outstr: AnsiString;
   begin
     CryptAcquireContext(Prov, nil, nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
     CryptCreateHash(Prov, CALG_SHA, nil, 0, hash);
     CryptHashData(hash, @pwd[1], Length(Pwd), 0);
     CryptDeriveKey(Prov, CALG_3DES, hash, 0, key);
     CryptDestroyHash(hash);
     DataLen := 0;
     bufsize := 0;
     CryptEncrypt(Key, nil, True, 0, nil, bufsize, Length(instr));
     GetMem(databuf, bufsize);
     try
       Move(instr[1], databuf^, Length(instr));
       DataLen := Length(instr);
       CryptEncrypt(Key, nil, True, 0, databuf, DataLen, bufsize);
       CryptReleaseContext(Prov, 0);
       CryptBinaryToStringA(databuf, DataLen, CRYPT_STRING_BASE64 or
              CRYPT_STRING_NOCRLF, nil, bufsize);
       SetLength(outstr, bufsize);
       CryptBinaryToStringA(databuf, DataLen, CRYPT_STRING_BASE64 or
              CRYPT_STRING_NOCRLF, @outstr[1], bufsize);
     // result, kill the three characters after the final one the base64 returns    ($D$A$0)
     // CRYPT_STRING_NOCRLF seems to mean nothing on XP, it might on other systems
     // you will need to change to the commented line if you are on Vista, 7, or 8
      Result := Copy(outstr, 1, Length(outstr) - 3);
     // Result := Outstr;
    finally
       FreeMem(databuf);
    end;
  end;

簡単な使用例:

 procedure TForm1.Button1Click(Sender: TObject);
   var
     password1: AnsiString;
   begin
     password1 := 'Test1';
     Edit2.Text := EncryptStringA(Edit1.Text, password1);
   end;

 procedure TForm1.Button2Click(Sender: TObject);
   var
     password1: AnsiString;
   begin
     password1 := 'Test1';
     Label1.Caption := DecryptStringA(Edit2.Text, password1);
   end;

 procedure TForm1.Button3Click(Sender: TObject);
   var
     password1: WideString;
   begin
     password1 := 'Test1';
     Edit2.Text := EncryptStringW(Edit1.Text, password1);
   end;

 procedure TForm1.Button4Click(Sender: TObject);
   var
     password1: WideString;
   begin
     password1 := 'Test1';
     Label1.Caption := DecryptStringW(Edit2.Text, password1);
   end;

それが誰かを助けることを願っています。

「Edit1」を入力として使用します。暗号化の正しい出力ANSI:3 + Pp7o8aErc =暗号化の正しい出力WideString:HijzDYgRr / Y =

編集:WideStringバージョンも投稿しました。XE3デモをダウンロードして、見て遊んだ。このコードはTurboDelphi2006およびDelphi3と同様に機能するため、問題が発生した場合は、CRYPT_STRING_NOCRLFを尊重しないWindows XP Base64実装についてコメントした行を確認してください。これは、Windowsを使用している場合はこれを正しく機能させるには、行を変更する必要があります。とにかく、OPの表明された意図のために、エンコードされたテキストに$ 13$10が表示されないようにします。

于 2013-01-22T15:47:00.310 に答える
1

base64 は非常に優れたエンコーダーであり、文字列の結果と標準があります。

{**************************************************************}
{                  Base 64 - by David Barton                   }
{--------------------------------------------------------------}

 const
  B64: array[0..63] of byte= (65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,
    81,82,83,84,85,86,87,88,89,90,97,98,99,100,101,102,103,104,105,106,107,108,
    109,110,111,112,113,114,115,116,117,118,119,120,121,122,48,49,50,51,52,53,
    54,55,56,57,43,47);

function B64Encode(pInput: pointer; pOutput: pointer; Size: longint): longint;
var
  i, iptr, optr: integer;
  Input, Output: PByteArray;
begin
  Input:= PByteArray(pInput); Output:= PByteArray(pOutput);
  iptr:= 0; optr:= 0;
  for i:= 1 to (Size div 3) do
  begin
    Output^[optr+0]:= B64[Input^[iptr] shr 2];
    Output^[optr+1]:= B64[((Input^[iptr] and 3) shl 4) + (Input^[iptr+1] shr 4)];
    Output^[optr+2]:= B64[((Input^[iptr+1] and 15) shl 2) + (Input^[iptr+2] shr 6)];
    Output^[optr+3]:= B64[Input^[iptr+2] and 63];
    Inc(optr,4); Inc(iptr,3);
  end;
  case (Size mod 3) of
    1: begin
         Output^[optr+0]:= B64[Input^[iptr] shr 2];
         Output^[optr+1]:= B64[(Input^[iptr] and 3) shl 4];
         Output^[optr+2]:= byte('=');
         Output^[optr+3]:= byte('=');
       end;
    2: begin
         Output^[optr+0]:= B64[Input^[iptr] shr 2];
         Output^[optr+1]:= B64[((Input^[iptr] and 3) shl 4) + (Input^[iptr+1] shr 4)];
         Output^[optr+2]:= B64[(Input^[iptr+1] and 15) shl 2];
         Output^[optr+3]:= byte('=');
       end;
  end;
  Result:= ((Size+2) div 3) * 4;
end;


function Base64Encode(const Value: AnsiString): AnsiString;
begin
  SetLength(Result,((Length(Value)+2) div 3) * 4);
  B64Encode(@Value[1],@Result[1],Length(Value));
end;


function B64Decode(pInput: pointer; pOutput: pointer; Size: longint): longint;
var
  i, j, iptr, optr: integer;
  Temp: array[0..3] of byte;
  Input, Output: PByteArray;
begin
  Input:= PByteArray(pInput); Output:= PByteArray(pOutput);
  iptr:= 0; optr:= 0;
  Result:= 0;
  for i:= 1 to (Size div 4) do
  begin
    for j:= 0 to 3 do
    begin
      case Input^[iptr] of
        65..90 : Temp[j]:= Input^[iptr] - Ord('A');
        97..122: Temp[j]:= Input^[iptr] - Ord('a') + 26;
        48..57 : Temp[j]:= Input^[iptr] - Ord('0') + 52;
        43     : Temp[j]:= 62;
        47     : Temp[j]:= 63;
        61     : Temp[j]:= $FF;
      end;
      Inc(iptr);
    end;
    Output^[optr]:= (Temp[0] shl 2) or (Temp[1] shr 4);
    Result:= optr+1;
    if (Temp[2]<> $FF) and (Temp[3]= $FF) then
    begin
      Output^[optr+1]:= (Temp[1] shl 4) or (Temp[2] shr 2);
      Result:= optr+2;
      Inc(optr)
    end
    else if (Temp[2]<> $FF) then
    begin
      Output^[optr+1]:= (Temp[1] shl 4) or (Temp[2] shr 2);
      Output^[optr+2]:= (Temp[2] shl 6) or  Temp[3];
      Result:= optr+3;
      Inc(optr,2);
    end;
    Inc(optr);
  end;
end;

function Base64Decode(const Value: AnsiString): AnsiString;
begin
  SetLength(Result,(Length(Value) div 4) * 3);
  SetLength(Result,B64Decode(@Value[1],@Result[1],Length(Value)));
end;

このサンプルで使用できます:

エンコード:

procedure TForm1.btn1Click(Sender: TObject);
begin
  edt1.Text := Base64Encode(edt1.Text)  ;
end;

デコード:

procedure TForm1.btn1Click(Sender: TObject);
begin
  edt1.Text := Base64Decode(edt1.Text)  ;
end;
于 2013-01-19T07:58:11.957 に答える