2011-07-23 45 views
8

我有一個字符串 - 一個母板的序列號(只有數字和字母)。如何加密/解密,並具有普通視圖:只能從A到Z的字母以及從0到9的數字。用戶必須向我發送字符串,我必須迴應。德爾福:簡單的字符串加密

我可以加密但不可讀的字符。

謝謝!

+1

請澄清你的問題。它看起來像是在詢問一個加密方案,它會爲您提供一個人性化的「ASCII」字符串。如果是這樣,那麼使用任何ol'加密方案,但Base64對字符串進行編碼。 –

+0

對不起!我需要一個人類可見的字符串 – maxfax

回答

12

最好的方法是加密然後編碼字符串。

檢查此示例,該示例使用JWSCL庫加密字符串,Indy在base64中進行編碼和解碼。

{$APPTYPE CONSOLE} 

uses 
    ExceptionLog, 
    Classes, 
    JwaWinType, 
    JwaWinCrypt, 
    IdCoderMIME, 
    SysUtils; 

function CryptString(Const Input: string; password : AnsiString; Encrypt: Boolean) : string; 
const 
    BufferSize=1024*1024; 
var 
    StreamSource : TStringStream; 
    StreamDest : TStringStream; 
    CRYPTPROV  : HCRYPTPROV; 
    CRYPTHASH  : HCRYPTHASH; 
    CRYPTKEY  : HCRYPTKEY; 
    Buffer  : LPBYTE; 
    BytesIn  : DWORD; 
    Final   : Boolean; 

    Encoder  : TIdEncoderMIME; 
    Decoder  : TIdDecoderMIME; 
    DestStream : TStringStream; 
begin 
    CryptAcquireContext(CRYPTPROV, nil, nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); 
    try 
     //create a valid key based in the password 
     if not CryptCreateHash(CRYPTPROV, CALG_SHA1, 0, 0, CRYPTHASH) then RaiseLastOSError; 
     try 
     if not CryptHashData(CRYPTHASH, @Password[1], Length(Password), 0) then RaiseLastOSError; 
     if not CryptDeriveKey(CRYPTPROV, CALG_RC4, CRYPTHASH, 0, CRYPTKEY) then RaiseLastOSError; 
     finally 
     CryptDestroyHash(CRYPTHASH); 
     end; 

     StreamSource := TStringStream.Create(Input); 
     StreamSource.Position:=0; 
     StreamDest := TStringStream.Create; 
     try 
     GetMem(Buffer, BufferSize); 
     try 

      if not Encrypt then 
      begin 
      //decode the string using base64 
      Decoder := TIdDecoderMIME.Create(nil); 
      try 
       DestStream := TStringStream.Create; 
       try 
       StreamDest.Position:=0; 
       Decoder.DecodeBegin(DestStream); 
       Decoder.Decode(StreamSource); 
       Decoder.DecodeEnd; 
       StreamSource.Clear; 
       DestStream.Position:=0; 
       StreamSource.CopyFrom(DestStream,DestStream.Size); 
       StreamSource.Position:=0; 
       finally 
       DestStream.Free; 
       end; 
      finally 
       Decoder.Free; 
      end; 

      end; 


      repeat 
       BytesIn := StreamSource.Read(Buffer^, BufferSize); 
       Final  := (StreamSource.Position >= StreamSource.Size); 
       if Encrypt then 
       begin 
       if not CryptEncrypt(CRYPTKEY, 0, Final, 0, Buffer, BytesIn, BytesIn) then RaiseLastOSError; 
       end 
       else 
       if not CryptDecrypt(CRYPTKEY, 0, Final, 0, Buffer, BytesIn) then RaiseLastOSError; 

       StreamDest.Write(Buffer^, BytesIn); 
      until Final; 


      //encode the string using base64 
      if Encrypt then 
      begin 
      Encoder := TIdEncoderMIME.Create(nil); 
      try 
       DestStream:=TStringStream.Create; 
       try 
       StreamDest.Position:=0; 
       Encoder.Encode(StreamDest,DestStream); 
       Result := DestStream.DataString; 
       finally 
       DestStream.Free; 
       end; 
      finally 
       Encoder.Free; 
      end; 
      end 
      else 
      Result:= StreamDest.DataString; 


     finally 
     FreeMem(Buffer, BufferSize); 
     end; 

     finally 
     StreamSource.Free; 
     StreamDest.Free; 
     end; 
    finally 
    CryptReleaseContext(CRYPTPROV, 0); 
    end; 
end; 


var 
    plaintext : string; 
    Encrypted : string; 
begin 
    try 
    plaintext:='this is a plain text'; Writeln('Plain Text '+plaintext); 
    Encrypted:=CryptString(plaintext,'...ThiS Is A PaSsWord...',True); 
    Writeln('Encrypted/Encoded string '+Encrypted); 
    plaintext:=CryptString(Encrypted,'...ThiS Is A PaSsWord...',False); 
    Writeln('Original string '+plaintext); 
    except 
     on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 
    Readln; 
end. 
+0

謝謝你! 但是大家都知道Base64。它有'=' - 易於識別和易於解碼。 – maxfax

+0

這並不重要,因爲字符串是加密的。如果有人解碼的base64字符串將有一個加密的字符串。 – RRUZ

+0

如果使用base64或十六進制格式,兩者都只是加密字符串的表示形式。 – RRUZ

4

這是某種衆所周知的ROT13 crypt的:不是A到Z,a到z其他

// will crypt A..Z, a..z, 0..9 characters by rotating 
function Crypt(const s: string): string; 
var i: integer; 
begin 
    result := s; 
    for i := 1 to length(s) do 
    case ord(s[i]) of 
    ord('A')..ord('M'),ord('a')..ord('m'): result[i] := chr(ord(s[i])+13); 
    ord('N')..ord('Z'),ord('n')..ord('z'): result[i] := chr(ord(s[i])-13); 
    ord('0')..ord('4'): result[i] := chr(ord(s[i])+5); 
    ord('5')..ord('9'): result[i] := chr(ord(s[i])-5); 
    end; 
end; 

任何字符,0..9將保持不變。

+0

是不是有點太簡單? – Ampere

+0

@Allforfree這顯然是簡單的混淆,而不是加密加密。將AES用於更強大的部分。但是你需要使用一個經過驗證的庫。見例如[此方法](https://synopse.info/files/html/api-1.18/SynCrypto.html#TAESABSTRACT_SIMPLEENCRYPT)用於對稱加密,[this one](https://synopse.info/files/html/api -1.18/SynEcc.html#ECDH_SHARED_SECRET)用於密鑰的非對稱計算。 –

12

簡單的Enc /月與支持Unicode,按照電子海圖產量只有十六進制字符:

const CKEY1 = 53761; 
     CKEY2 = 32618; 

function EncryptStr(const S :WideString; Key: Word): String; 
var i   :Integer; 
     RStr  :RawByteString; 
     RStrB  :TBytes Absolute RStr; 
begin 
    Result:= ''; 
    RStr:= UTF8Encode(S); 
    for i := 0 to Length(RStr)-1 do begin 
    RStrB[i] := RStrB[i] xor (Key shr 8); 
    Key := (RStrB[i] + Key) * CKEY1 + CKEY2; 
    end; 
    for i := 0 to Length(RStr)-1 do begin 
    Result:= Result + IntToHex(RStrB[i], 2); 
    end; 
end; 

function DecryptStr(const S: String; Key: Word): String; 
var i, tmpKey :Integer; 
     RStr  :RawByteString; 
     RStrB  :TBytes Absolute RStr; 
     tmpStr  :string; 
begin 
    tmpStr:= UpperCase(S); 
    SetLength(RStr, Length(tmpStr) div 2); 
    i:= 1; 
    try 
    while (i < Length(tmpStr)) do begin 
     RStrB[i div 2]:= StrToInt('$' + tmpStr[i] + tmpStr[i+1]); 
     Inc(i, 2); 
    end; 
    except 
    Result:= ''; 
    Exit; 
    end; 
    for i := 0 to Length(RStr)-1 do begin 
    tmpKey:= RStrB[i]; 
    RStrB[i] := RStrB[i] xor (Key shr 8); 
    Key := (tmpKey + Key) * CKEY1 + CKEY2; 
    end; 
    Result:= UTF8Decode(RStr); 
end; 

例子:

procedure TForm1.btn1Click(Sender: TObject); 
begin 
    txt2.Text:= EncryptStr(txt1.Text, 223); 
    lbl1.Caption:= DecryptStr(txt2.Text, 223); 
end; 
+0

偉大的代碼。如果您更改CKEY,它仍然可以工作嗎? – drzymala

+0

@martini:是的。 – MohsenB

+0

爲什麼's'參數在一個函數中聲明爲字符串,而另一個函數中是寬字符? – Ampere