Delphi: простое шифрование строк - PullRequest
8 голосов
/ 23 июля 2011

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

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

Спасибо!

Ответы [ 4 ]

14 голосов
/ 23 июля 2011

Наилучшим способом является шифрование и последующее кодирование строки.

Проверьте этот пример, который использует библиотеку 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.
14 голосов
/ 21 февраля 2013

Simple Enc / Dec с поддержкой 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;
7 голосов
/ 23 июля 2011

Это какой-то известный ROT13 склеп :

// 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 голосов
/ 17 апреля 2018

Я использую этот очень простой трюк из https://edn.embarcadero.com/article/28325, который хорош своей простотой:

Я использую его для хранения некритических зашифрованных паролей в базе данных. Моя цель - положить слой запутывания (и минимизировать вычисления, необходимые для расшифровки), а не делать серьезное шифрование, для пароля администратора, например, я использую AES:

// this function both  encryptes and decryptes
// EnDecrypt(EnDeCrypt(astring)) = astring
function EnDeCrypt(const Value : String) : String;
var
  CharIndex : integer;
begin
  Result := Value;
  for CharIndex := 1 to Length(Value) do
    Result[CharIndex] := chr(not(ord(Value[CharIndex])));
end;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...