XOR?


using System;
using System.Text;

// Am vazut un mod criptare a parolelor intr-o baza de date bazat pe operatia XOR
//
// Ideea e urmatoarea:
// La inregistrare parola userului este codificata printr-o operatie XOR
// intre parola si o cheie, iar codificarea este pastrata in baza de date.
//
// Cand utilizatorul se autentifica, trimite parola, se face codificarea si apoi
// se compara cu cea de la inregistrare. Daca e ok inseamna ca e logat.. logic.
//
// Astfel se vrea ca absolut nimeni sa nu stie parolele (nu conteaza ca e dezvoltator SQL..)
//
// Un exemplu:
// parola : *********
// cheia publica : sharedkeys
// se face XOR caracter cu caracter intre parola si cheia publica
// ********* ^ sharedkeys = codificarea (o secventa de carcatere ASCII)
//
// Daca se stiu cheia publica si codificarea se poate afla parola pentru ca
// la XOR e ceva de genul 1 ^ x = 1 sau 0 ^ x = 0 => x = 0
// 1 ^ y = 0 sau 0 ^ y = 1 => y = 1
// Mai pe romaneste cand, bit cu bit, pe aceeasi pozitie din cheia publica si codificare,
// valorile difera atunci in parola avem bitul 1, iar cand valorile sunt egale, avem in parola 0
// Astfel se poate reconstrui parola.
//
public class PasswordKey
{
public const string SHAREDKEY = "sharedkeys";
private readonly string hashPassword;
private readonly string sharedKeyFull;
private PasswordKey(){}

public PasswordKey(string hashPassword)
{
this.hashPassword = hashPassword;
this.sharedKeyFull = SharedKeyFull();
}
public PasswordKey(byte[] password)
{
this.hashPassword = ASCIIEncoding.ASCII.GetString (password);
this.sharedKeyFull = SharedKeyFull ( );
}
// Pentru ca se face XOR caracter cu caracter (codul ascii mai bine zis),
// cheia publica trebuie sa aiba acceasi lungime cu parola, iar codificarea
// rezultata va avea implicit aceeasi lungime L.
// Pentru asta ori se iau primele L caractere din cheia publica, ori se concateneaza
// cheia publica de atatea ori cat este nevoie ca din rezultat sa se poate lua primele L caractere
// si sa se formeze cheia publica pentru respectiva parola
private string SharedKeyFull()
{
int count = hashPassword.Length/SHAREDKEY.Length + 1;
if (count == 1)
return SHAREDKEY.Substring ( 0, hashPassword.Length );

StringBuilder sb = new StringBuilder();
for ( int i = 0 ; i < count ; i++ )
sb.Append(SHAREDKEY);
return sb.Remove(hashPassword.Length, sb.Length - hashPassword.Length).ToString();
}

public string GetPassword()
{
if ( String.IsNullOrEmpty ( hashPassword ) )
throw new Exception("hashPassword is not provided");
if ( String.IsNullOrEmpty ( sharedKeyFull ) )
throw new Exception ( "sharedKeyFull is not provided" );


string[] hashb2 = CConvert.StringToBase2( this.hashPassword );
string[] shareb2 = CConvert.StringToBase2 ( sharedKeyFull );


StringBuilder sb = new StringBuilder();
for ( int i = 0 ; i < shareb2.Length ; i++ )
sb.Append ( CConvert.Base2ToString ( Decrypt.Execute ( shareb2[i], hashb2[i] ) ) );
return sb.ToString();
}
}

public static class CConvert
{
public static string[] StringToBase2(string source)
{
string[] nums = new string[source.Length];
for ( int i = 0 ; i < source.Length ; i++ )
nums[i] = Convert.ToString ( source[i], 2 );
return nums;
}
public static string Base2ToString(string part)
{
int val = 0;
for ( int i = 0 ; i < part.Length ; i++ )
{
val += Int32.Parse ( part[i].ToString ( ) ) * ( int ) Math.Pow ( 2, part.Length - i - 1 );
}
return ( ( char ) val ).ToString ( );
}
}

public static class Decrypt
{
// se obtine parola pe baza proprietatilor care le-am scris mai sus ale operatiei XOR
public static string Execute ( string shareB2Part, string hashB2Part )
{
if (String.IsNullOrEmpty(shareB2Part)) throw new ArgumentNullException("shareB2Part");
if ( String.IsNullOrEmpty ( hashB2Part ) )throw new ArgumentNullException ( "hashB2Part" );

int length = shareB2Part.Length > hashB2Part.Length ? shareB2Part.Length : hashB2Part.Length;
if ( length > shareB2Part.Length )
shareB2Part = new string ( '0', length - shareB2Part.Length ) + shareB2Part;
else
if ( length > hashB2Part.Length )
hashB2Part = new string ( '0', length - hashB2Part.Length ) + hashB2Part;

StringBuilder sb = new StringBuilder();
for ( int i = 0 ; i < length ; i++ )
if ( shareB2Part[i] == hashB2Part[i] )
sb.Append('0');
else
sb.Append('1');
return sb.ToString();
}
}

// Ca sa se testeze asta e nevoie de coduri criptate ca mai sus si cel mai important sa se stie
// cheia publica. Daca nu se stie cheia publica.. sa se ia un dictionar la rasfoit :)


Comments

  1. Buna idee, imi place :)
    Am sa fac la fel cu JS intr-o buna zi...

    ReplyDelete

Post a Comment

Popular posts from this blog

IIS 7.5, HTTPS Bindings and ERR_CONNECTION_RESET

Table Per Hierarchy Inheritance with Column Discriminator and Associations used in Derived Entity Types

Verify ILogger calls with Moq.ILogger