Ciao
Le classi del namespace System.Security.Cryptography forniscono degli algoritmi di crittografia piuttosto avanzati, ma non ce n'è nessuno che produca in output un numero di byte uguale a quelli in input. Ora, poichè per codificare un decimal sono necessari 16 byte, e una funzione di crittografia te ne produce in eccesso, quando devi andare a decodificare avrai bisogno anche dei byte in più che però sono andati persi.
L'unica soluzione è quindi quella di implementare a mano un altro algoritmo che sia reversibile, ad esempio usando l'xor e la rotazione dei bit; ti scrivo qui sotto le funzioni che ho provato a scrivere per l'occasione:
//La funzione ottiene i due long che identificano
//gli 8 byte superiori e gli 8 byte inferiori del decimal
static void GetLongs(decimal value, out ulong high, out ulong low)
{
unsafe
{
//Ottiene un puntatore a value
decimal* val = &value;
//Converte il puntatore a decimal in un puntatore a long
//il cui primo elemento è il long superiore e il secondo
//è il long inferiore
ulong* lVal = (ulong*)val;
//Imposta high e low
high = lVal[0];
low = lVal[1];
}
}
//La funzione ottiene un valore decimal a partire
//da due long, costituenti gli 8 byte superiori e inferiori
static decimal GetDecimal(ulong high, ulong low)
{
unsafe
{
//Crea la variabile decimal del risultato
decimal result = 0;
//Ottiene un puntatore al risultato
decimal* resPtr = &result;
//converte il puntatore in un puntatore a long
ulong* lPtr = (ulong*)resPtr;
//Imposta low e high
lPtr[0] = high;
lPtr[1] = low;
//Ottiene il risultato
return result;
}
}
//Criptazione con password e uso di xor e rotazione bit
static decimal Encrypt(decimal input, decimal password)
{
//Ottiene i due long dal decimal dell'input
ulong low, high;
GetLongs(input, out high, out low);
//Ottiene i due long dal decimal della password
ulong pLow, pHigh;
GetLongs(password, out pHigh, out pLow);
//Esegue una xOr fra i bit
ulong crLow, crHigh;
crLow = low ^ pLow;
crHigh = high ^ pHigh;
//Dalla password ottiene il numero di bit di rotazione
int shiftCount = (int)(pLow >> 7) & 0x1F;
//Esegue una rotazione ciclica verso destra per la parte inferiore
//verso sinistra per quella superiore
crLow = (crLow >> shiftCount) | (crLow << (sizeof(ulong) * 8 - shiftCount));
crHigh = (crHigh << shiftCount) | (crHigh >> (sizeof(ulong) * 8 - shiftCount));
//Ritorna il decimal ottenuto dai due long
return GetDecimal(crHigh, crLow);
}
//Decriptazione con password e uso di xor e rotazione bit
decimal Decrypt(decimal input, decimal password)
{
//Ottiene i due long dal decimal dell'input
ulong low, high;
GetLongs(input, out high, out low);
//Ottiene i due long dal decimal della password
ulong pLow, pHigh;
GetLongs(password, out pHigh, out pLow);
//Dalla password ottiene il numero di bit di rotazione
int shiftCount = (int)(pLow >> 7) & 0x1F;
ulong crLow, crHigh;
//Esegue la rotazione ciclica inversa: verso sinistra per
//la parte inferiore e verso destra per la parte superiore
crLow = (low << shiftCount) | (low >> (sizeof(ulong) * 8 - shiftCount));
crHigh = (high >> shiftCount) | (high << (sizeof(ulong) * 8 - shiftCount));
//Esegue l'xOr fra i bit
crLow = crLow ^ pLow;
crHigh = crHigh ^ pHigh;
//Ritorna il decimal ottenuto dai due long
return GetDecimal(crHigh, crLow);
}
Le funzioni necessitano di una password che devi fornire come valore decimal. Ti sconsiglio password non significative, come 0, perchè sminuiscono la (già poca) sicurezza dell'algoritmo.
Luca