uses Windows, Classes, SysUtils; function BlobToString(P: PByte; Size: DWORD): String; begin Result := ''; while Size > 0 do begin Result := Result + IntToHex(P^,2); Inc(P,1); Size := Size - 1; end; end; procedure ProtectString(const Source: String; var Dest: String; const Description: String; const Entropy: String; LocalMachine: Boolean); var DataIn: DATA_BLOB; OptionalEntropy: DATA_BLOB; POptionalEntropy: PDATA_BLOB; DataOut: DATA_BLOB; {$IFDEF Unicode} WDescription: String; {$ELSE} WDescription: WideString; {$ENDIF} Flags: DWORD; MemorySource: TMemoryStream; MemoryEntropy: TMemoryStream; begin MemorySource := nil; MemoryEntropy := nil; try MemorySource := TMemoryStream.Create; MemoryEntropy := TMemoryStream.Create; { DataIn } with MemorySource do begin Write(PChar(Source)^,Length(Source) * SizeOf(Char)); DataIn.cbData := Size; DataIn.pbData := Memory; end; { OptionalEntropy } if Entropy = '' then begin POptionalEntropy := nil; end else begin with MemoryEntropy do begin Write(PChar(Entropy)^,Length(Entropy) * SizeOf(Char)); OptionalEntropy.cbData := Size; OptionalEntropy.pbData := Memory; end; POptionalEntropy := @OptionalEntropy; end; { Description } WDescription := Description; { Flags } Flags := 0; if LocalMachine = True then begin Flags := CRYPTPROTECT_LOCAL_MACHINE; end; { DataOut } FillChar(DataOut,SizeOf(DataOut),0); { Protect data } if CryptProtectData(@DataIn,PWideChar(WDescription),POptionalEntropy,nil, nil,Flags,@DataOut) = False then begin RaiseLastOSError; end; { Result } Dest := BlobToString(DataOut.pbData,DataOut.cbData); { Free allocated memory } LocalFree(HLOCAL(DataOut.pbData)); finally MemorySource.Free; MemoryEntropy.Free; end; end;
Source、Description、Entropyに文字列を渡すとDestに暗号化されたデータが16進文字列化されて格納されます。
復号化も同様に
function StringToBlob(const S: String; Stream: TStream): Boolean; var Index: Integer; Data: Byte; L: Integer; begin Index := 1; L := Length(S); while Index <= L do begin try Data := StrToInt('$' + Copy(S,Index,2)); except Result := False; Exit; end; Stream.Write(Data,SizeOf(Data)); Index := Index + 2; end; Result := True; end; function UnprotectString(const Source: String; var Dest: String; var Description: String; const Entropy: String): Boolean; var DataIn: DATA_BLOB; OptionalEntropy: DATA_BLOB; POptionalEntropy: PDATA_BLOB; DataOut: DATA_BLOB; PDescription: PWideChar; MemorySource: TMemoryStream; MemoryEntropy: TMemoryStream; begin MemorySource := nil; MemoryEntropy := nil; try MemorySource := TMemoryStream.Create; MemoryEntropy := TMemoryStream.Create; { DataIn } if StringToBlob(Source,MemorySource) = False then begin Result := False; Exit; end; with MemorySource do begin DataIn.cbData := Size; DataIn.pbData := Memory; end; { OptionalEntropy } if Entropy = '' then begin POptionalEntropy := nil; end else begin with MemoryEntropy do begin Write(PChar(Entropy)^,Length(Entropy) * SizeOf(Char)); OptionalEntropy.cbData := Size; OptionalEntropy.pbData := Memory; end; POptionalEntropy := @OptionalEntropy; end; { DataOut } FillChar(DataOut,SizeOf(DataOut),0); { Unprotect data } if CryptUnprotectData(@DataIn,PDescription,POptionalEntropy,nil, nil,0,@DataOut) = False then begin Result := False; Exit; end; { Result } SetString(Dest,PChar(DataOut.pbData),DataOut.cbData div SizeOf(Char)); { Description } Description := PDescription; { Free allocated memory } LocalFree(HLOCAL(DataOut.pbData)); LocalFree(HLOCAL(PDescription)); Result := True; finally MemorySource.Free; MemoryEntropy.Free; end; end;Source、Entropyに文字列を渡すとDest、Descriptionに復号化された文字列が格納されます。 蛇足ですが、自システムのパスワードはSHAなど(MD5はいまさらな気も)何らかの形でハッシュして保存しておき、入力も同様の方法でハッシュして結果の一致を確認する、という手法が一般的です。
0 件のコメント:
コメントを投稿