-2

Can someone give me the code to encrypt and decrypt a Unicode strings in delphi firemonkey Mobile? I've tried everything with xor with other libraries , and nothing. There are always characters that are not recognized as the euro symbol € . If someone could help me , would be appreciated.

Edit: Thank you Hans, but always I have the same problem with stringstream . This code works perfectly in windows , but ios gives me this error : "No mapping for the Unicode character exists in the target multibyte code page"

unit UMain;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, ElAES,
  FMX.StdCtrls, FMX.Layouts, FMX.Memo, Math;

type
  TForm2 = class(TForm)
    ToolBar1: TToolBar;
    Label1: TLabel;
    Label2: TLabel;
    Memo1: TMemo;
    Layout1: TLayout;
    Button1: TButton;
    Button3: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
const
  PASSWORD = '1234';
var
  Form2: TForm2;

implementation

{$R *.fmx}
{$R *.iPhone.fmx IOS}
function StringToHex(S: string): string;
var
    i: integer;

begin
  Result := '';

  // Go throught every single characters, and convert them
  // to hexadecimal...
    for i := 1 to Length( S ) do
    Result := Result + IntToHex( Ord( S[i] ), 2 );
end;

function HexToString(S: string): string;
var
    i: integer;

begin
  Result := '';

  // Go throught every single hexadecimal characters, and convert
  // them to ASCII characters...
  for i := 1 to Length( S ) do
  begin
    // Only process chunk of 2 digit Hexadecimal...
    if ((i mod 2) = 1) then
        Result := Result + Chr( StrToInt( '0x' + Copy( S, i, 2 )));
  end;
end;


procedure TForm2.Button1Click(Sender: TObject);
var
  Source: TStringStream;
  Dest: TStringStream;
  Key: TAESKey128;
begin
try

  Source := TStringStream.Create( Memo1.Text );
  Dest   := TStringStream.Create('');
  FillChar( Key, SizeOf(Key), 0 );
  Move( PChar(PASSWORD)^, Key, Min( SizeOf( Key ), Length( PASSWORD )));
  EncryptAESStreamECB( Source, 0, Key, Dest );
  //Memo1.Lines.BeginUpdate;
  Memo1.Text := Dest.DataString;
  //Memo1.Lines.EndUpdate;
  Label2.Text := 'Texto Encriptado';
  Source.Free;
  Dest.Free;
except on E: Exception do
  begin
    ShowMessage(e.ToString);
    Source.Free;
    Dest.Free;
    Memo1.Text :='';
  end;
end;

end;


procedure TForm2.Button3Click(Sender: TObject);
var
  Source: TStringStream;
  Dest: TStringStream;
  Key: TAESKey128;
  Size: integer;
begin
try
  Source := TStringStream.Create(Trim(Memo1.Text) );
  Dest   := TStringStream.Create('');
  Size := Source.Size;
  Source.ReadBuffer(Size, SizeOf(Size));
  FillChar(Key, SizeOf(Key), 0);
  Move(PChar(PASSWORD)^, Key, Min(SizeOf(Key), Length(PASSWORD)));
  Source.Position := 0;
  DecryptAESStreamECB(Source, Source.Size - Source.Position, Key, Dest);
  Memo1.Text := Trim(Dest.DataString);
  Label2.Text := 'Texto Original';
  Source.Free;
  Dest.Free;
except on E: Exception do
  begin
    ShowMessage(e.ToString);
    Source.Free;
    Dest.Free;
    Memo1.Text :='';
  end;
end;

end;

end.

I've also tried to create stringstream with this:

Source := TStringStream.Create(Trim(Memo1.Text) , TEncoding.Unicode) ;

and sometimes works well and sometimes gives me the following error:"Los surrogate char without a preceding high surrogate char at index: 8. chaeck that the string is encoded properly. Any ideas?

elcharlie
  • 511
  • 8
  • 25
  • 5
    You don't encrypt/decrypt strings. Encryption operates on binary data. You need to decide how to encode the text, and then what encryption algo to use. Only you can decide. – David Heffernan Oct 13 '14 at 08:25
  • 1
    It is very important for the after decrypt part to **know** what kind of data has been encrypted. A string has also the encoding (ANSI, UTF8, UTF16, ...) you need to know to get the expected information out of the byte soup. It is the same with an image. You need to know it is an image an the image type (BMP, JPG, TIFF, ...) – Sir Rufo Oct 13 '14 at 09:24
  • 2
    This question appears to be off-topic because stackoverflow is not a "give me teh codez" site. – President James K. Polk Oct 13 '14 at 11:39
  • As pointed above, you are messing encoding and encrypting. It seems that you are unaware of the encoding used in your system. FWIW the error you get about surrogates is because your system expects UTF-16 (mainly used on windows). – n0p Oct 13 '14 at 14:29
  • Your edit suggests that you don't really understand the basic concepts here. I suggest that you need to do some background study to gain a sure understanding of how Unicode is handled in Delphi. – David Heffernan Oct 14 '14 at 17:01

1 Answers1

4

Use standardized libraries instead of trying to make your own encryption solution. There are for example several implementation of AES encryption available for Delphi (e.g. Eldos which is included in the NativeXML library). Write your string (MyString) to a stream and encrypt it:

var
  lSourceStream: TStringStream;
  lDestinationStream: TMemoryStream;
begin
  lSourceStream := TStringStream.Create(MyString);
  lDestinationStream := TMemoryStream.Create;
  AESencrypt(lSourceStream,lDestinationStream);
  lDestinationStream.SaveToFile(<filename>);
end;
Hans
  • 2,220
  • 13
  • 33
  • 1
    Another interesting question what encryption key and mode of operation are used here? – kludg Oct 13 '14 at 11:09
  • @DavidHeffernan: It uses the default encoding, but to be sure that Unicode is used, add an argument: TStringStream.Create(MyString, TEncoding.UniCode). – Hans Oct 13 '14 at 13:16
  • @user246408: I did not go into the AES routines, as they are implemented differently, but you of course have to set an encryption key (e.g. 128 bit), which might be a parameter or a property in the AES class. – Hans Oct 13 '14 at 13:21
  • Wouldn't it be better to specify UTF-8. Using ANSI as you propose is a poor idea. – David Heffernan Oct 13 '14 at 13:52
  • @DavidHeffernan Where do you see ANSI? – Hans Oct 14 '14 at 08:13
  • Right there where you call `TStringStream.Create`, at least on Windows. I know the question is mobile though. Which makes `TEncoding.Default` be UTF-8. The asker clearly has no comprehension of the issues of encoding and you don't help here by completely ignoring them. The asker needs help in understanding what's going on. Pass `TEncoding.UTF8` to `TStringStream.Create`. – David Heffernan Oct 14 '14 at 08:19
  • I suggested adding the extra encoding argument. I agree that if it comes to saving on disk or in any way interacting with other systems, then UTF8 is a better choice, but the question specifically stated "Unicode strings". However, after having seen the source code being added it is clear that the problem is more about the understanding of the concepts. – Hans Oct 14 '14 at 08:23
  • @Hans UTF-8 is a complete Unicode encoding. But yes, it is clear that the asker is out of their depth. – David Heffernan Oct 14 '14 at 17:00
  • @DavidHeffernan Yes you are right. However, in the Windows world (where longterm Delphi users, like my self, come from), the term Unicode was always understood as UTF16. – Hans Oct 14 '14 at 22:31
  • Not yet since TEncoding.Unicode is still used to specify UTF16 by the latest Delphi editions. – Hans Oct 19 '14 at 12:59