2011-07-23 2 views
8

У меня есть строка - серийный номер материнской платы (только цифры и буквы). Как шифровать/расшифровать его и иметь нормальный вид: буквы только от А до Я и цифры от 0 до 9. Пользователь должен отправить мне строку, я должен ответить.Delphi: простое строковое шифрование

Я могу зашифровать, но с недопустимыми символами.

Спасибо!

+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:

// 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; 

Любые символы, кроме a..z, A..Z, 0..9 останется без изменений.

+0

не слишком сложно? – Ampere

+0

@Allforfree Это явно простая обфускация, а не криптографическое шифрование. Используйте AES для чего-то более сильного. Но вам нужно будет использовать проверенную библиотеку. См. [этот метод] (https://synopse.info/files/html/api-1.18/SynCrypto.html#TAESABSTRACT_SIMPLEENCRYPT) для симметричного шифрования и [этот] (https://synopse.info/files/html/api -1.18/SynEcc.html # ECDH_SHARED_SECRET) для асимметричного вычисления ключа. –

12

Простой Enc/декабрь с поддержкой Unicode, выход Enc является только шестнадцатеричные символы:

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' объявлен как строка в одной функции и widestring в другом? – Ampere

Смежные вопросы