Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Encrypting/Decripting of Credit Card Numbers 5

Status
Not open for further replies.

StevenK

Programmer
Jan 5, 2001
1,294
0
0
GB
Obviously we should not store an individual's credit card number in a database.
We therefore need some method of encrypting (and then decrypting) the card number. The encrypted version will be stored and the decrypting version displayed.
Anyone make any suggestions as to how we can do this ?
We ideally need a simple method involoving storing a resultant string (or number) in the database field as required.
Steve
 
Ive done this a couple of times, the best way I found was to reverse the number and then increment or decrement each character in the string by a given number using the ASCII character set. I always set my systems to randomly change the number used to increment/decrement the characters every other week. For retrieving the number, store the incremented number at the end of the CC Number and you can always track it back.
 
Something like this would be ideal.
Remind me how I make use of the ASCII character set ? Converting backward and forward ?
My memory fails me ....
Steve
 
You would need a list of ASCII characters for the numbers 0 - 9 (And the space). I cant remember what they are but they are all # and a number. I think A = #65

Write some code to remove the hash symbol, increment the number and replace the hash symbol and there you have your new character.

Im sure I did something else too but my memory also fails me. Hey, its friday!
 
here are the numbers

Ascii(dec)value Hex Number
48 30 0
49 31 1
50 32 2
51 33 3
52 34 4
53 35 5
54 36 6
55 37 7
56 38 8
57 39 9
 
Ord (or ascii in MSSQL) to get Ascii value of a character
Chr (char in MSSQL) to do the inverse
 
There are also free encryption components:

Look at for "Cipher Compendium"
It's free, fast and good !!! Sting encryption, file encryption and it contains allot of ciphers and hash'es !!!
Easy to use too, and comes with a handy demo project !!!

Good luck, BobbaFet

Everyone has a right to my opinion.
E-mail me at caswegkamp@hotmail.com
 
Sorry I pointed you to the wrong site ...
This is a link to the components:


From menu choose "Compression, Encryption" and the
scroll down till you see "cipher.zip" ...

That's the one, and its good, no kidding !!!

Good luck, BobbaFet

Everyone has a right to my opinion.
E-mail me at caswegkamp@hotmail.com
 
Thanks for your help and pointers with this one folks.
I've managed to fit together an encrypt and decrypt function that now work well.
Thanks again.
Steve
 
I thought I was there with this one. However I've proved myself wrong.
I'm making use of ASCII values and as part of the function 'EncryptMyString' am returning a string (the encrypted version of the string passed). Sometimes this returned string is shorter than the original, if I feed a 20 character string I sometimes get a return string of say 1 character, i.e. '3' and when I pass this through the 'DecryptMyString' function do not get the original string as required.
In order to hopefully bypass this issue I made use of the 'DecryptMyString' function inside the scope of the 'EncryptMyString' function, such that the encrypted version of the string would only be in turn if the decrypted version (using 'DecryptMyString') matched the original string parameter passed to be encrypted.
The 'EncryptMyString' function seems to do this OK (Outputting to screen to follow work done) but the resultant 'encrypted' string as shown in the edit box on the form does not return the original string when passed through the 'DecryptMyString' function.
Anyone have any suggestions as to what might be going amiss here ?
Thanks in advance.
Would it be down to whitespace ? I've tried trimming the strings back and forth for the comparisons.
Hope someone can help me over this (hopefully) final hurdle.
Steve
 
Could be something to do with your font set. Depending on the ineteger value your adding to your original ASCII character, some characters appear in the ASCII set more than once.
 
I'm using the standard default font.
I would have thought that due to my usage of 'DecryptMyString' within the scope of 'EncryptMyString' the returned string would always give me a string that would decrypt correctly.
Any thoughts ?
Steve
 
Could you paste/explain your Encryption/Decryption routines, and give an example of a string that doesn't encrypt/decrypt correctly?
 
For the 'Encrypt' we do :

function EncryptMyString(const pStrToEncrypt : String) : String;
var
tpInStr : String;
tpOutStr : String;
tpInLen : Integer;
tpI : Integer;
tpChar : Char;
tpASCIIVal : Integer;
tpAddFactor : Integer;
tpOKToReturn : Boolean;
tpDecrypted : String;
begin
tpOKToReturn := False;
tpInStr := pStrToEncrypt;
tpInLen := Length(tpInStr);
Randomize;
// Loop the encryption process until we produce a string that we can decrypt
while (tpOKToReturn = False) do
begin
tpAddFactor := Random(200); // Pick a Random number up to 200
tpOutStr := '';
Result := ''; // Prime result as blank
// Work from end-to-beginning
for tpI := tpInLen downto 1 do
begin
tpChar := pStrToEncrypt[tpI]; // Get the character from the string
tpASCIIVal := Ord(tpChar); // Get the associated ASCII value
// Add factor and square of character position (and add to string)
tpOutStr := tpOutStr + Chr(tpASCIIVal + tpAddFactor + Sqr(tpI));
end;
// Add the associated character for generated Random number (for unlocking)
tpOutStr := tpOutStr + Chr(tpAddFactor);
tpDecrypted := DecryptMyString(Trim(tpOutStr));
if (tpdecrypted = Trim(pStrToEncrypt)) then
begin
tpOKToReturn := True;
end;
end;
Result := tpOutStr;
end;

And for the 'Decryption' we use :

function DecryptMyString(const pStrToDecrypt : String) : String;
var
tpInStr : String;
tpOutStr : String;
tpI : Integer;
tpASCIIToDecode : integer;
tpAddFactor : Integer;
begin
// Determine the (Random) number that was used for the encryption
tpAddFactor := Ord(pStrToDecrypt[Length(pStrToDecrypt)]);
// Get the string that needs to be decrypted (less last character for key number)
tpInStr := Copy(pStrToDecrypt, 0, Length(pStrToDecrypt) - 1);
tpOutStr := '';
Result := ''; // Prime the Result as blank
// Work backwards down the string decrypting character by character
tpI := Length(tpInStr);
while tpI > 0 do
begin
tpASCIIToDecode := Ord(tpInStr[tpI]) - tpAddFactor - (Sqr(Length(tpInStr) - tpI + 1));
tpOutStr := tpOutStr + Chr(tpASCIItoDecode);
tpI := tpI - 1;
end;
Result := tpOutStr;
end;

The functions operate without a hitch if I omit the use of the 'Sqr' (making use of the value of tpI rather than its square) - but when using the 'Sqr' I get occasions when the returned string from 'EncryptMyString' does not decrypt correctly.

The value I'm using for testing is '9218 2367 8127 3267 1659'.
Any thoughts/help would be appreciated.
Thanks
Steve
 
More importantly, and something I had lost sight of :
Someone suggested that I should be following some set of rules when encrypting credit card details.
Where can I find this set of standards ?
Is there one ?
Thanks again
Steve
 
It's because sometimes when you encrypt the string, you end up with characters with the Ascii value 0; the string terminator. When you attempt to display these strings in an edit box they're truncated at the first 0.
 
That then begs the question as to how I might work around this ?
Any ideas anyone ?
Steve
 
Well you don't actually need to display the encrypted string so it shouldn't be a problem. As far as I know you can insert strings with #0 characters into a SQL Server database, but if you really don't want them you can just check your encrypted string each time to ensure it has no #0s in it.
 
Thanks again MikeEd.
I'm now performing a check as part of the 'EncryptMyString' function and ensuring that the ASCII value to be converted is not 0 (using mod 256). If it is then I perform the function again til I get to a point when none of the values to obtain the keys for is 0.
This seems to elimate the problems I've been seeing.
Thanks again.
Steve
 
Here is a simple funcitions that can solve your problem...



procedure TMain.Button1Click(Sender: TObject);
var i : integer;
sRet : String;
sPom : String;
sPassWord : String;

begin
sPassWord:=ParamStr(4);
sRet :='';
sPom :='';
For i:=1 to (Length(sPassWord) div 2) do
begin
sPom := Chr(StrToInt('$' + MidStr(sPassWord,2 * i - 1, 2)));
sRet:= sRet + sPom;
end;

Edit1.text := DecryptStr(sRet, 'asdfghjkl')
end;

Function TMain.Add128(strul : String) : String;
var
strIz :String;
i : Integer;
sPom : String;
sPomi : Integer;
begin
strIz :='';
For i:=1 to Length(strul) do
begin
sPom := MidStr(strul,i,1);
sPomi := Ord(sPom[1]);
strIz := strIz + Chr((sPomi + 128) mod 256);
end;
Add128 := strIz
end;

Function TMain.CreateEncryptCode(Key : String) : Integer;
var
Total1,Total2 : Integer;
NbChars1, NbChars2 : Integer;
Counter : Integer;
sPom : String;
sPomR : Real;
begin
Total1 := 0;
Total2 := 0;
NbChars1 := 0;
NbChars2 := 0;

For Counter := 1 to Length (Key) do
case (Counter mod 2) of
0 : begin
sPom := MidStr(Key, Counter, 1);
Total1 := Total1 + Ord(sPom[1]);
NbChars1 := NbChars1 + 1
end
else
begin
sPom := MidStr(Key, Counter, 1);
Total2 := Total2 + Ord(sPom[1]);
NbChars2 := NbChars2 + 1
end
end;

If (NbChars1>0) AND (NbChars2>0) Then
begin
sPomR := Abs((Total1 / NbChars1)-(Total2 / NbChars2));
CreateEncryptCode := Round(sPomR);
end
else
CreateEncryptCode := 1
end;

Function TMain.DecryptStr(EncStr : String; Key : String) : String;
var
Counter : Integer;
EncCode : Integer;
sPom : String;
Result1 : string;
begin
EncCode := CreateEncryptCode(Key);
DecryptStr := '';
Result :='';
EncStr := Add128(EncStr);
For Counter := 1 To Length (EncStr) do
case (Counter mod 2) of
0 : begin
sPom := MidStr(EncStr, Counter, 1);
Result1 := Result1 + Chr(Ord(sPom[1]) - EncCode);
end
else
begin
sPom := MidStr(EncStr, Counter, 1);
Result1 := Result1 + Chr(Ord(sPom[1]) + EncCode);
end

end;
DecryptStr := Result1
end;
Function TMain.EncryptStr(OrigStr : String; Key : String) : String;
var
Counter : Integer;
EncCode : Integer;
sPom : String;
Result1 : string;
begin
EncCode := CreateEncryptCode(Key);
EncryptStr := '';
Result :='';
For Counter := 1 To Length (OrigStr) do
case (Counter mod 2) of
0 : begin
sPom := MidStr(OrigStr, Counter, 1);
Result1 := Result1 + Chr(Ord(sPom[1]) + EncCode);
end
else
begin
sPom := MidStr(OrigStr, Counter, 1);
Result1 := Result1 + Chr(Ord(sPom[1]) - EncCode);
end

end;
EncryptStr := Add128(Result1);
end;
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top