Link to home
Start Free TrialLog in
Avatar of Marco Gasi
Marco GasiFlag for Spain

asked on

dynamic array and variant record

Hi all. I'll try to explain my problem. In order to hide some sensitive string
in a my program, I use a tecnique I don't know hot to call it, so I describe it.

I declare a record this way:
Rec = record
      case Boolean of
        False: (s: array[0..51] of AnsiChar);
        True: (i: array[0..12] of Integer);
    end;

Open in new window


Obviously the arry's length depends on the string length. Then, supposing the
string is s:
 
procedure TForm2.btnCreateStringClick(Sender: TObject);
var
  r: Rec;
  s: AnsiString;
  I: Integer;
  code, value: string;
begin
  //da stringa a Cardinal
  FillChar(r.s, SizeOf(r.s), 0);
  s := 'IDontKnowHowToDoItButIHopeYouCanHelpMeEasilyAndSoon';
  Move(PAnsiChar(s)^, r.s, Length(s));
  for I := Low(r.i) to High(r.i) do
  begin
    value := IntToStr(not(r.i[I] shl 1));
    mmoString.Lines.Add('r.i['+ IntToStr(I) +'] := Cardinal(not ' + value + ') shr 1;');
  end;
end;

Open in new window


This way I can refer to the string using r.s and the cracker has to work a lot more
to break my code.

Since I have yet changed several times the string to mask this way (it is the
url for convalidation the software license), I thought to make a little utility
to allow me to simply tyoe the string and output the record values to use in my code.
For the above example this code is:

 
r.i[0] := Cardinal(not 521606959) shr 1;
r.i[1] := Cardinal(not 933339531) shr 1;
r.i[2] := Cardinal(not 790570805) shr 1;
r.i[3] := Cardinal(not 924924205) shr 1;
r.i[4] := Cardinal(not -1557060819) shr 1;
r.i[5] := Cardinal(not 296035637) shr 1;
r.i[6] := Cardinal(not 765672245) shr 1;
r.i[7] := Cardinal(not 758358295) shr 1;
r.i[8] := Cardinal(not -1592183513) shr 1;
r.i[9] := Cardinal(not 1027022613) shr 1;
r.i[10] := Cardinal(not -1592183529) shr 1;
r.i[11] := Cardinal(not 252786489) shr 1;
r.i[12] := Cardinal(not 924784035) shr 1;

Open in new window


The r.s is 'IDontKnowHowToDoItButIHopeYouCanHelpMeEasilyAndSoon'.

Only problem is that I wish only type a string, and click a button without the
need to change the record declaration every time.

I tried to make the two arrays dynamic but I received this error:

"Type 'dynamic array' needs finalization - not alloweed in variant record".

How can I solve this' Have you a workaround?

Thanks in advance for any try to help me
ASKER CERTIFIED SOLUTION
Avatar of Emmanuel PASQUIER
Emmanuel PASQUIER
Flag of France image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
so, in your encoding tool application :

Var
 Enc:EncodedString;
begin
 EncodeString(edtStringToEncode.Text, Enc );
 WriteDecodingCode( edtStringVarName.Text, Enc );
end;

and include DecodeString in your target application
Avatar of Marco Gasi

ASKER

Thanks for your answer, epasquier. I'll try it as soon as possible  - now I have to prepare my wedding anniversary and I can stay no more at the beloved computer ;-)

Only a thing. You simplified the Move statement but you didn't use it in your code: your code doesn't need it? Or I have to merge my code with yours?

'See' you later...
no need to merge anything, take just my code

I only started with a comment on Move because obviously you didn't knew how to perform it that way.

Good Wedding Anniversary !

A night of love one never forgets...
Thanks a lot for your help, epasquier. It works very fine :-)
Hi, epasquier. Are you still monitoring this question? I have a little problem: I can't copy and past the output of your code because Delphi7 doesn't compile it. Suppose string is 'Pippo'; The output is

DecodeString(Pippo,[
4294967135,4294967085,4294967071,4294967071,4294967073]);

Thisis wrong, because DecodeString procedure requires the first parameter be and EncodedString and the second one an AnsiString. I tried to change this way

DecodeString([
4294967135,4294967085,4294967071,4294967071,4294967073], s);

But with this code I receive this error: 'Constants expression violates subrange bounds'

I tried several ways, with quotes, without brackets and so on  but I didn't succeed. Can youhelp me?
ok, my bad you cannot pass array of Cardinal like that. Only  'array of const' can be but it's more complex. Let's build a var EncConst of type EncodedString instead and pass it (first parameter, I made also an error here)

procedure WriteDecodingCode(const StrVarName:String;const Enc:EncodedString);
Var
 i:integer;
begin
 if Length(Enc)=0 Then Exit; // prevent errors
 mmoString.Lines.Add('SetLength(EncConst,'+IntToStr(Length(Enc))+');');
 for i:=0 to Length(Enc)-1 do 
  mmoString.Lines.Add(Format('EncConst[%d]=%d',[i,Enc[i]]));
 mmoString.Lines.Add('DecodeString(EncConst,'+StrVarName+');');
end;

Open in new window

Hi, epasquier. Thank you for trying to help me and I'm sorry to waste your time, but that doesn't work.

The result is

SetLength(EncConst,5);
EncConst[0]=-161
EncConst[1]=-211
EncConst[2]=-225
EncConst[3]=-225
EncConst[4]=-223
DecodeString(EncConst,pippo);

The problem is syntactical and I fixed that making this

SetLength(EncConst,5);
EncConst[0]:=-161;
EncConst[1]:=-211;
EncConst[2]:=-225;
EncConst[3]:=-225;
EncConst[4]:=-223;
DecodeString(EncConst,s);

where s is an empty string which will holds the decoded value (It's right this?). Unfortunately I still receive the same error message: 'Constants expression violates subrange bounds'

Thanks a lot.
Cardinal is unsigned int, so I guess the format function treats it as Integer. Just declare
Type
 EncodedString=Array of Integer;

Open in new window

Yeah, now it works fine! Thank you very mutch for your help. On to the next. :-)