[bmx] Unreversible Password Encription by Bobysait [ 1+ years ago ]

Started by BlitzBot, June 29, 2017, 00:28:39

Previous topic - Next topic

BlitzBot

Title : Unreversible Password Encription
Author : Bobysait
Posted : 1+ years ago

Description : You can use this to encrypt a single password, or mix it with username or email or both
This is a "check" algorithm : You first generate the encrypted password that you store somewhere (in a database for eg) then to login, you check if the password[+name[+mail]] combination match the registered one.
There is no way we can retrieve the password from the generated password, wether or not you own the key.
But, it won't prevent to log with a password that generates the same key.

And by the way, you won't be able to check anything without the generated key.
So, you'll have to store it somewhere too.

If you want to use it with a client-server application, you can use this algorithm to encrypt your password and send only encrypted data, so there is no visible password that is transfered anywhere.

By the way : You can also encrypt the username. (if you don't need to use it ... for eg, if you also have a pseudonym field, you can register the name as and encrypted value, that will enforce the user security, all you will have is the pseudo to display, and nothing can be hacked on the database)
For eg:
-> Run this once to generate a random Key that the client and server will use to encrypt/check password and or name
Local Sr:TPassSerializer = TPassSerializer.Create(,False)
Print Sr.GetKey()


Let's say the key is "aNPFNifz21531xoPDjoDJpxa1"
(this is just to demonstrate, the key is actually longer and chararcters are all unique)

' when you come to use the serializer, provide the key, else it will generate an other key and it will never match with the server if the key does not correspond.
Local sr:TPassSerializer = New TPassSerializer.Create("aNPFNifz21531xoPDjoDJpxa1",False)
Local pseudo:String = "My Unique Pseudo"
Local name:String = "My UserName"
Local pass:String = "My Password"
Local mail:String = "My-mail@..."
Local enc_name:String = sr.Serialize2(name, pseudo, 32)
Local enc_pass:String = sr.Serialize3(pass, enc_name, mail, 64)


This will generate an encrypted password that use an encrypted username you will send to the server.
On the server side, you just have to search the registered pseudo with its corresponding password and username and return True or False if everything match.
And remember that this will break the data you encrypt !
You can't use this to send data that need to be recovered. [/i]

Code :
Code (blitzmax) Select
SuperStrict

FrameWork BRL.Random
Import BRL.LinkedList
Import BRL.Map
Import BRL.Math

Import BRL.StandardIO


Type TPassSerializer

Field m_K:String;
Field m_K1024:String;
Field m_KL:Int;
Field m_CaseSensitive:Byte;

Function ResizeStr:String(s:String, l:Int, pCaseSensitive:Byte=True)
If (pCaseSensitive=False) Then s=s.ToLower();
local n:Int = s.Length;
If n>l Then Return s[..l];
Local nb:Int = Ceil(Float(l)/n);
Local o:String="";
Local i:Int = 0;
For i = 0 Until nb
o :+ s
Next
Return o[..l];
End Function

Method GenerateKey:String()
Local l:TList = New TList, a:Int;
Local pass:Int = 3, i:Int=0;
For i = 0 Until pass
For a = 0 To 25; l.AddLast(Chr("a"[0]+a)); l.AddLast(Chr("A"[0]+a)); Next
For a = 0 To 9; l.AddLast(Chr("0"[0]+a)); Next;
Next
Self.m_k = ""
While l.Count()>0
Local i:Int = Rand(0,l.Count()-1);
Local ar:Object[] = l.ToArray();
Self.m_k :+ String(ar[i]);
l.Remove(ar[i]);
Wend
Self.m_KL = Self.m_k.Length;
Return Self.m_k;
End Method

Method Create:TPassSerializer(k:String="", pCaseSensitive:Byte=True)
Self.m_K = k; If k=""  Then Self.GenerateKey();
Self.m_KL = Self.m_k.Length;
Self.m_K1024 = TPassSerializer.ResizeStr(Self.m_K,1024);
Self.m_CaseSensitive = pCaseSensitive;
Return Self;
End Method

Method Serialize:String(s$,ln:Int=-1)
s=s.Trim(); If s="" Then Return ""
If ln<0 Then ln=s.Length;
s = ResizeStr(s,ln, Self.m_CaseSensitive);
Local i:Int = 0, o:String = "";
For i = 0 Until ln
o :+ Chr(Self.m_K1024[ s[i] + Self.m_K1024[i] ])
Next
Return o;
End Method

Method Serialize2:String(s$,p$,ln:Int=-1)
s=s.Trim(); If s="" Then Return ""
p=p.Trim(); If p="" Then Return ""
If ln<0 Then ln=Max(s.Length,p.Length);
s = ResizeStr(s,ln, Self.m_CaseSensitive);
p = ResizeStr(p,ln, Self.m_CaseSensitive);
Local i:Int = 0, o:String = "";
For i = 0 Until ln
o :+ Chr(Self.m_K1024[ s[i] + p[i] + Self.m_K1024[i] ])
Next
Return o;
End Method

Method Serialize3:String(s$,p$,m$,ln:Int=-1)
s=s.Trim(); If s="" Then Return ""
p=p.Trim(); If p="" Then Return ""
m=m.Trim(); If m="" Then Return ""
If ln<0 Then ln=Max(Max(s.Length,p.Length),m.Length);
s = ResizeStr(s,ln, Self.m_CaseSensitive);
p = ResizeStr(p,ln, Self.m_CaseSensitive);
m = ResizeStr(m,ln, Self.m_CaseSensitive);
Local i:Int = 0, o:String = "";
For i = 0 Until ln
o :+ Chr(Self.m_K1024[ s[i] + p[i] + m[i] + Self.m_K1024[i] ])
Next
Return o;
End Method

Method GetKey:String()
Return Self.m_K;
End Method

End Type


Local sr:TPassSerializer = New TPassSerializer.Create(,False)
Print "key="+sr.GetKey()
Print "serialize : '"+sr.Serialize2("My Pass-Word", "BobySait", 64)+"'"
Print "serialize : '"+sr.Serialize3("My Pass-Word", "BobySait", "BobySait@GMAIL.COM", 64)+"'"
Print "serialize : '"+sr.Serialize3("my PASS-WORD", "bobysait", "bobysait@gmail.com", 64)+"'"


Comments :


Guy Fawkes(Posted 1+ years ago)

 It'd be nice if we could have a Blitz3D version of this as well! =)Thanks!Regards, ~GF


Bobysait(Posted 1+ years ago)

 I've not Blitz3D installed, and I won't, so, whatever I translate it, I can't ensure it will work (and will very probably contains lots of errors)And as blitz 3d has no such think as byte arrays, everything needs to be translated using Chr, Mid and Asc and offset the position by 1 ( bytes are from 0 to Len()-1, while Mid is from 1 to Len() )... boring task and slower.Here is a test (keep in mind I've not compiled it, so, no warranty...)

Function Max#(a#,b#)
If a>b Then Return a
Return b
End Function

Type TPassSerializer
Field m_K$
Field m_K1024$
Field m_CaseSensitive%
End Type

Function SerializerResizeStr$(s$, l%, pCaseSensitive%=True)
If (pCaseSensitive=False) Then s=Lower(s)
Local n% = Len(s)
If n>l Then Return Left(s,l)
Local nb% = Ceil(Float(l)/n)
Local o$=""
Local i% = 0
For i = 1 To nb
o = o + s
Next
Return Left(o,l)
End Function

Type TRandomChar
Field m_C%
End Type
Function NewRandomChar.TRandomChar(v%)
Local rc.TRandomChar = New TRandomChar
rcm_C = v
Return rc
End Function

Function GenerateKey$(sr.TPassSerializer)
Local pass% = 3, i%=0
Local nb% = 0
For i = 1 To pass
For a = 0 To 25
NewRandomChar(Asc("a")+a)
NewRandomChar(Asc("A")+a)
Next
For a = 0 To 9
NewRandomChar(Asc("0")+a)
Next
nb = nb + 62
Next

Local rc.TRandomChar
srm_K = ""
While First TRandomChar<>Null
i = Rand(0,nb-1)
For rc = Each TRandomChar
If i=0
srm_K = srm_K + Chr(rcm_C)
Delete rc
nb=nb-1
Exit
EndIf
i=i-1
Next
Wend
Return srm_K
End Function

Function CreatePassSerializer.TPassSerializer(k$="", pCaseSensitive%=True)
Local sr.TPassSerializer = New TPassSerializer
srm_K = k: If k=""  Then GenerateKey(sr)
srm_K1024 = SerializerResizeStr(srm_K,1024)
srm_CaseSensitive = pCaseSensitive
Return sr
End Function

Function Serialize$(sr.TPassSerializer, s$,ln%=-1)
s=Trim(s): If s="" Then Return ""
If ln<0 Then ln=Len(s)
s = SerializerResizeStr(s, ln, srm_CaseSensitive)
Local i% = 0, o$ = ""
For i = 1 To ln
o = o + Chr( Asc(Mid(srm_K1024, Asc(Mid(s,i,1)) + Asc(Mid(srm_K1024,i,1)), 1) ) )
Next
Return o
End Function

Function Serialize2$(sr.TPassSerializer, s$,p$,ln%=-1)
s=Trim(s): If s="" Then Return ""
p=Trim(p): If p="" Then Return ""
If ln<0 Then ln=Max(Len(s),Len(p))
s = SerializerResizeStr(s, ln, srm_CaseSensitive)
p = SerializerResizeStr(p, ln, srm_CaseSensitive)
Local i% = 0, o$ = ""
For i = 1 To ln
o = o + Chr( Asc( Mid(srm_K1024, Asc(Mid(s,i,1))+Asc(Mid(p,i,1))+Asc(Mid(srm_K1024,i,1)), 1 ) ) )
Next
Return o
End Function

Function Serialize3$(sr.TPassSerializer, s$,p$,m$,ln%=-1)
s=Trim(s): If s="" Then Return ""
p=Trim(p): If p="" Then Return ""
m=Trim(m): If p="" Then Return ""
If ln<0 Then ln=Max(Max(Len(s),Len(p)), Len(m))
s = SerializerResizeStr(s, ln, srm_CaseSensitive)
p = SerializerResizeStr(p, ln, srm_CaseSensitive)
m = SerializerResizeStr(m, ln, srm_CaseSensitive)
Local i% = 0, o$ = ""
For i = 1 To ln
o = o + Chr( Asc( Mid(srm_K1024, Asc(Mid(s,i,1)) + Asc(Mid(p,i,1)) + Asc(Mid(m,i,1)) + Asc(Mid(srm_K1024,i,1)), 1 ) ) )
Next
Return o
End Function

Function SerializerKey$(sr.TPassSerializer)
Return srm_K
End Function

Local sr.TPassSerializer = CreatePassSerializer("",False)
Print "key="+SerializerKey(sr)
Print "serialize : '"+Serialize2(sr, "My Pass-Word", "BobySait", 64)+"'"
Print "serialize : '"+Serialize3(sr, "My Pass-Word", "BobySait", "BobySait@...", 64)+"'"
Print "serialize : '"+Serialize3(sr, "my PASS-WORD", "bobysait", "bobysait@...", 64)+"'"

WaitKey()
End




Derron(Posted 1+ years ago)

 So to say: your code creates a hash?Similar to MD5, Sha and so on?byeRon


Bobysait(Posted 1+ years ago)

 Yep, it's a similar algorithm


Bobysait(Posted 1+ years ago)

 By the way, this is the module versionIt also provides encription for Byte ptr (reversible, and obviousy less secure)SuperStrict

Module MDT.Serializer

Import BRL.Random
Import BRL.LinkedList
Import BRL.Map
Import BRL.Math

' -> sample use Print and TBank
'Import BRL.StandardIO
'Import BRL.Bank

Type TPassSerializer

Field m_K:String;
Field m_K1024:String;
Field m_KL:Int;
Field m_CaseSensitive:Byte;

Function ResizeStr:String(s:String, l:Int, pCaseSensitive:Byte=True)
If (pCaseSensitive=False) Then s=s.ToLower();
local n:Int = s.Length;
If n>l Then Return s[..l];
Local nb:Int = Ceil(Float(l)/n);
Local o:String="";
Local i:Int = 0;
For i = 0 Until nb
o :+ s
Next
Return o[..l];
End Function

Method GenerateKey:String()
Local l:TList = New TList, a:Int;
Local pass:Int = 3, i:Int=0;
For i = 0 Until pass
For a = 0 To 25; l.AddLast(Chr("a"[0]+a)); l.AddLast(Chr("A"[0]+a)); Next
For a = 0 To 9; l.AddLast(Chr("0"[0]+a)); Next;
Next
Self.m_k = ""
While l.Count()>0
Local i:Int = Rand(0,l.Count()-1);
Local ar:Object[] = l.ToArray();
Self.m_k :+ String(ar[i]);
l.Remove(ar[i]);
Wend
Self.m_KL = Self.m_k.Length;
Return Self.m_k;
End Method

Method Create:TPassSerializer(k:String="", pCaseSensitive:Byte=True)
Self.m_K = k; If k=""  Then Self.GenerateKey();
Self.m_KL = Self.m_k.Length;
Self.m_K1024 = TPassSerializer.ResizeStr(Self.m_K,1024);
Self.m_CaseSensitive = pCaseSensitive;
Return Self;
End Method

Method Serialize:String(s$,ln:Int=-1)
s=s.Trim(); If s="" Then Return ""
If ln<0 Then ln=s.Length;
s = ResizeStr(s,ln, Self.m_CaseSensitive);
Local i:Int = 0, o:String = "";
For i = 0 Until ln
o :+ Chr(Self.m_K1024[ s[i] + Self.m_K1024[i] ])
Next
Return o;
End Method

Method Serialize2:String(s$,p$,ln:Int=-1)
s=s.Trim(); If s="" Then Return ""
p=p.Trim(); If p="" Then Return ""
If ln<0 Then ln=Max(s.Length,p.Length);
s = ResizeStr(s,ln, Self.m_CaseSensitive);
p = ResizeStr(p,ln, Self.m_CaseSensitive);
Local i:Int = 0, o:String = "";
For i = 0 Until ln
o :+ Chr(Self.m_K1024[ s[i] + p[i] + Self.m_K1024[i] ])
Next
Return o;
End Method

Method Serialize3:String(s$,p$,m$,ln:Int=-1)
s=s.Trim(); If s="" Then Return ""
p=p.Trim(); If p="" Then Return ""
m=m.Trim(); If m="" Then Return ""
If ln<0 Then ln=Max(Max(s.Length,p.Length),m.Length);
s = ResizeStr(s,ln, Self.m_CaseSensitive);
p = ResizeStr(p,ln, Self.m_CaseSensitive);
m = ResizeStr(m,ln, Self.m_CaseSensitive);
Local i:Int = 0, o:String = "";
For i = 0 Until ln
o :+ Chr(Self.m_K1024[ s[i] + p[i] + m[i] + Self.m_K1024[i] ])
Next
Return o;
End Method

Method GetKey:String()
Return Self.m_K;
End Method

End Type

Type TDataSerializer

Field m_K:Byte[];
Field m_K2:Byte[];
Field m_RK:Byte[]; ' reverse key

Function ResizeStr:String(s:String, l:Int)
local n:Int = s.Length;
If n>l Then Return s[..l];
Local nb:Int = Ceil(Float(l)/n);
Local o:String="";
Local i:Int = 0;
For i = 0 Until nb
o :+ s
Next
Return o[..l];
End Function

Method GenerateKey:Byte[]()
Local l:TList = New TList, a:Int;
For a = 0 To 255;
l.AddLast(String.FromInt(a));
Next

Self.m_K = New Byte[256];
Self.m_K2 = New Byte[512];
Self.m_RK = New Byte[256];
Local i:Int
For i = 0 Until 256
Local j:Int = Rand(0,l.Count()-1);
Local o:Object = l.ToArray()[j];
Self.m_K[i] = String(o).ToInt();
Self.m_K2[i] = Self.m_K[i];
Self.m_K2[i+256] = Self.m_K[i];
l.Remove(o);
Next
Return Self.m_k;
End Method

Method Create:TDataSerializer(k:String="")
Self.GenerateKey();
Self.m_RK = New Byte[256];
For Local i:Int = 0 Until 256
Self.m_RK[Self.m_K[i]] = i;
Next
Return Self;
End Method

Method Serialize:Byte Ptr(s:Byte Ptr, ln:Int, out:Byte Ptr=Null)
if out=Null Then out = New Byte[ln];
If ln=0 Then Return out;
Local i:Int = 0;
For i = 0 Until ln
out[i] = Self.m_K2[ s[i] + Self.m_K[i] ];
Next
Return out;
End Method

Method DeSerialize:Byte Ptr(v:Byte Ptr, ln:Int, out:Byte Ptr=Null)
if out=Null Then out = New Byte[ln];
If ln=0 Then Return out;
Local i:Int = 0;
For i = 0 Until ln
out[i] = (256 + ( Self.m_RK[v[i]] - Self.m_K[i])) mod(256);
Next
Return out;
End Method

Method GetKey:String()
Local a:Int=0, s:String=""
For a = 0 Until 256; s :+ Self.m_K[a]+" "; Next
Return s;
End Method

Method GetReverseKey:String()
Return String.FromBytes(Self.m_RK, 256);
End Method

End Type

Rem
' Sample
' create the serializer (False-> not case-sensitive)
Local sr:TPassSerializer = New TPassSerializer.Create(,False)
' the generated key -> The first time, you generate the key, the next time, you use this key when creating the serializer
' -> Local sr:TPassSerializer = New TPassSerializer.Create(COPY_THE_STRING_KEY_HERE,False)
Print "key="+sr.GetKey()
Print "serialize : '"+sr.Serialize2("My Pass-Word", "MyName", 64)+"'"
Print "serialize : '"+sr.Serialize3("My Pass-Word", "MyName", "MY-eMail@...", 64)+"'"
' As it's not case-sensitive, so it should print the same result here !
Print "serialize : '"+sr.Serialize3("my PASS-WORD", "mynAMe", "my-Email@...", 64)+"'"

Local dr:TDataSerializer = New TDataSerializer.Create()
Local bankI:TBank = CreateBank(16);
Local bankS:TBank = Createbank(16);
Local bankO:TBank = Createbank(16);
bankI.PokeInt(0,12345678);
bankI.PokeShort(4,65000);
bankI.PokeFloat(6,1.234);
bankI.PokeByte(10,100);
bankI.PokeByte(11,20);
bankI.PokeShort(12,1);
bankI.PokeShort(14,32000);

' input bank to serialized bank
dr.Serialize(bankI.Buf(), bankI.Size(), bankS.Buf())

' serialized bank to ouput bank
dr.Deserialize(bankS.Buf(), bankS.Size(), bankO.Buf())

' draw results
Print "Input > Serialized > Ouput [=Deserialized] (Output should give the same result as Input)
Print bankI.PeekInt(0)   +" > "+bankS.PeekInt(0)   +" > "+bankO.PeekInt(0)
Print bankI.PeekShort(4) +" > "+bankS.PeekShort(4) +" > "+bankO.PeekShort(4)
Print bankI.PeekFloat(6) +" > "+bankS.PeekFloat(6) +" > "+bankO.PeekFloat(6)
Print bankI.PeekByte(10) +" > "+bankS.PeekByte(10) +" > "+bankO.PeekByte(10)
Print bankI.PeekByte(11) +" > "+bankS.PeekByte(11) +" > "+bankO.PeekByte(11)
Print bankI.PeekShort(12)+" > "+bankS.PeekShort(12)+" > "+bankO.PeekShort(12)
Print bankI.PeekShort(14)+" > "+bankS.PeekShort(14)+" > "+bankO.PeekShort(14)

EndRem



Brucey(Posted 1+ years ago)

 I doubt anyone would want to use it for anything like password hashing, as it's not very strong.Toy hashes like this are interesting, but for serious stuff you really should be using globally recommended algorithms such as bcrpyt. <a href="https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet" target="_blank">OWASP</a> is a good place to look when considering which algorithms to use for such things...


Bobysait(Posted 1+ years ago)

 Sure, but here, it's opened to modification. You can add false characters on top and and/or on end without problems, the structur is ready for this. It's up to the user to use its own method to make it safe.I obviously forgot to mention : I won't post a "robust" method, but only a structur, because as it's open sourced, if you use this exactly as it is, a hacker just need to know the source of the algorithm to just do some reverse-engeneering on the algorithm.The most robust hash method is the one that noone knows about : a unique algorithm made for the purpose.It surely can't be provided as an open-sourced on a programmer forum, or it will be de-facto unsecure.Don't know if I'm very clear, but Yes, as it is, it's far from the most robust algorithm.So, I give the chips, it's up to the user to add the "salt" ^_^


Brucey(Posted 1+ years ago)

 So you are saying that algorithms (like bcrypt) used by the majority of companies on the internet for password hashing are insecure because they are open-source?ok :-)


Bobysait(Posted 1+ years ago)

 I don't think those algorithms are insecure, I just think they can and will be hacked over time.But, whatever, that's absolutely not my point here.-> We are on the blitz website, and it's the code archive. I don't think someone will need to protect such important data with a big lack of knowledge on encryption.The one who is in need for robust stuff is supposed to be capable to do it by himself.This section, for what I think it is made for (I might be wrong, but it's how I see it) is essentially for people who don't know how to do thingsNot really for experimented guys.And for thoose "noob" guys, it's better to use an unreversible easy to break algorithm that at least ensure the integrity of the userSo that, whatever an account is hacked, all the hacker will be able to do is play with another user account. At least, he won't use its pseudo/password combination to test on some commercial website. (because, whatever we prevent users to use unique password, they still use the same pseudo-pass on each website and game account regardless of the risks)So, I totally agree with you, but I think it's not relevant here, that's all :)ps :- And regarding of what you say, sha1 was supposed to be a robust one until it was broken. (same as md5)Robust algorithm or not, there always comes a time where a "smart" guy break it. And, I don't think exposing the algorithm helps to make it safe whatever bcript is a good one-> it's robust essentially because it's low as hell to hack, but with massive trojaned computers, there should be a possible way to use a brute force by sending requests from lots  of computers at the same time. Of course, it's hard and requires lots of knowledges and materials, but it's not unbreakble.Most of the general algorithms are safe because the data protected are less valuable than the time required to hack them. It's relevant enough to secure anything from anyone (except from stupid hackers that just take thoose algorithms as challenge regardless of the cost ...)


Derron(Posted 1+ years ago)

 sha1 and md5 are not "broken" - they are kind of "short circuited".The problems with Hashes is: as you cannot "reverse" them, you need to brute force.Years ago md5 was "secure" because you needed way too long to check all potential keys (md5("a"), md5("b"), ...).If the algorithm had flaws (eg. with md5 you could have multiple source keys generating the same hash) things can get done faster.Hiding an algorithm isn't possible with a locally available app (as the ASM-code is always there).Instead of using your code the "just want to secure something" user should think of using the md5-code flying around here in the forums (and then use some fine grained salt to do avoid rainbow-tables). Nonetheless: you are right that the archives are there to put your code on the net for others to benefit from it.We just wanted to make the users aware of the risk connected to custom hashing algorithms.byeRon


SomeRandomGuy(Posted 6 months ago)

 1. "I obviously forgot to mention : I won't post a "robust" method, but only a structur, because as it's open sourced, if you use this exactly as it is, a hacker just need to know the source of the algorithm to just do some reverse-engeneering on the algorithm." -> That's not how any of this works actually. Cryptographic hash functions are one-way-functions, so you're not supposed to be able to revert it, even if you know exactly how the hash is computed (if it's well designed obviously).2. "The most robust hash method is the one that noone knows about : a unique algorithm made for the purpose. It surely can't be provided as an open-sourced on a programmer forum, or it will be de-facto unsecure." -> You just described one of the most INsecure methods to work with, never hide the algorithm. Read up on Kerckhoffs's principle.


xlsior(Posted 6 months ago)

 <div class="quote"> The most robust hash method is the one that noone knows about : a unique algorithm made for the purpose.It surely can't be provided as an open-sourced on a programmer forum, or it will be de-facto unsecure. </div>That's just "security through obscurity" -- with a proper encryption method it doesn't matter if an attacker has the algorithm, it is still unbreakable over human timeframes unless they have the necessary key.If your solution depends on keeping it out of view of a determined hacker then you've already lost since the algorithm can be recovered by de-compiling your executable program anyway.


Bobysait(Posted 6 months ago)

 Kerckhoffs's principle is only that an algorithms can't be secured "only" because of the algorithm being "secret"He never told we can't hide it, he only said we can't rely on the fact it's hidden to say it's safe.But if it's hidden, it's "safer" even if it's not "safe" because it's hiddenSame thing : if it's not hidden, it's less safe, it doesn't mean it's not safe, but it's at least less safe.It's actually like javascript obfuscatorIt's clearly not strong enough to prevent from hacking attempt ... but it prevents from unexperimented people to hack it.<div class="quote">  If your solution depends on keeping it out of view of a determined hacker then you've already lost since the algorithm can be recovered by de-compiling your executable program anyway. </div>That's exactly what I didn't say, and that's also the only thing you keep on telling for no reason.So, time for a metaphor :I've got a secret map for a secret chest containing a known treasure that is not really a "big fantastic treasure" ... it's just a comic collection of not rare at all editions. ( hey ! don't judge ! :p )The chest has its own securityThe map is encripted and full of mysteries, puzzles and else.So ... the map can be on my desktop because I know nobody will find my chest... and anyway if someone did, he could not open it.But ... i don't know what the future will be, maybe the security of today will be obsolete tomorrow so ...What if I also hide the map ?The people who will find the map will also have to decript it, understand and resolve the puzzles, find the chest and finally find a way to open it...There is much to think that the same guy will not be able to do all the steps and there is much to think my fantastic treasure will not be valuable enough that he contact some professionals to get my comic books.So, the only fact the map is hidden already makes it safer just because it removes lots of people from the equation, and the remaining ones would have to be very experimented to unlock the other securities. [/i]