Fondamentalement, vous pouvez diviser votre opération dans les parties:
- En quelque sorte, "crypter" votre nombre
n
, de sorte que deux numéros consécutifs de la production (très) différents résultats
- Construire votre "lisible" code à partir du résultat de l'étape 1
Pour l'étape 1 je vous suggère d'utiliser un simple algorithme de chiffrement par bloc (par exemple, un chiffrement Feistel avec une ronde en fonction de votre choix). Voir également cette question.
Algorithmes de chiffrement Feistel le travail en plusieurs tours. Au cours de chaque cycle, certaines ronde fonction est appliquée à la moitié de l'entrée, le résultat est xor
ed avec l'autre moitié et les deux moitiés sont échangées. La bonne chose à propos de Feistel algorithmes est que la fonction round n'a pas à être deux sens (de l'entrée à la fonction round est maintenue inchangée après chaque ronde, de sorte que le résultat de la fonction round peut être reconstruit au cours de déchiffrement). Par conséquent, vous pouvez choisir ce que fou opération(s) que vous aimez :). Aussi Feistel sont les algorithmes symétriques, ce qui répond à votre première exigence.
Un petit exemple en C#
const int BITCOUNT = 30;
const int BITMASK = (1 << BITCOUNT/2) - 1;
static uint roundFunction(uint number) {
return (((number ^ 47894) + 25) << 1) & BITMASK;
}
static uint crypt(uint number) {
uint left = number >> (BITCOUNT/2);
uint right = number & BITMASK;
for (int round = 0; round < 10; ++round) {
left = left ^ roundFunction(right);
uint temp = left; left = right; right = temp;
}
return left | (right << (BITCOUNT/2));
}
(À noter qu'après le dernier tour, il n'y a pas d'échange, dans le code de l'échange est tout simplement annulée dans la construction de la suite)
En dehors de l'accomplissement de vos conditions 3 et 4 (la fonction est totale, donc, pour les différentes entrées, vous obtenez différentes sorties et l'entrée est "totalement brouillés", selon votre définition informelle), il est aussi son propre inverse (donc implicitement l'accomplissement de l'exigence 1), c'est à dire crypt(crypt(x))==x
pour chaque x
dans le domaine d'entrée (0..2^30-1
dans cette mise en œuvre). Aussi il est bon marché en termes d'exigences de performance.
Pour l'étape 2 juste coder le résultat à une base de votre choix. Par exemple, pour coder un 30-nombre de bits, vous pouvez utiliser 6 "chiffres" d'un alphabet de 32 caractères (donc vous pouvez encoder 6*5=30 bits).
Un exemple pour cette étape en C#:
const string ALPHABET= "AG8FOLE2WVTCPY5ZH3NIUDBXSMQK7946";
static string couponCode(uint number) {
StringBuilder b = new StringBuilder();
for (int i=0; i<6; ++i) {
b.Append(ALPHABET[(int)number&((1 << 5)-1)]);
number = number >> 5;
}
return b.ToString();
}
static uint codeFromCoupon(string coupon) {
uint n = 0;
for (int i = 0; i < 6; ++i)
n = n | (((uint)ALPHABET.IndexOf(coupon[i])) << (5 * i));
return n;
}
Pour les entrées 0 - 9 présente les rendements suivants coupon codes
0 => 5VZNKB
1 => HL766Z
2 => TMGSEY
3 => P28L4W
4 => EM5EWD
5 => WIACCZ
6 => 8DEPDA
7 => OQE33A
8 => 4SEQ5A
9 => AVAXS5
Notez que cette approche a deux différents interne "secrets": d'Abord, la fonction round avec le nombre de tours d'occasion et de seconde, l'alphabet que vous utilisez pour l'encodage de l'encyrpted résultat. Mais aussi à noter que la mise en œuvre n'est en aucune façon sécurisée dans un cryptographiques majeures de sens!
Notez également, que la fonction est un total bijective fonction, dans le sens, que tout un code de 6 caractères (avec les caractères de l'alphabet) permet d'obtenir un numéro unique. Pour empêcher quiconque de pénétrer dans n'importe code, vous devez définir une sorte de restrictions sur le nombre d'entrée. E. g. seul problème des coupons pour la première 10.000 numéros. Ensuite, la probabilité d'un hasard de code promo valide serait 10000/2^30=0.00001 (il faudrait près de 50000 tente de trouver un bon code promo). Si vous avez besoin de plus de "sécurité", vous pouvez simplement augmenter la taille en bits/coupon code longueur (voir ci-dessous).
EDIT: Changement de code promo longueur
La modification de la longueur de la code promo nécessite quelques calculs: La première (chiffrement) étape ne fonctionne que sur une chaîne de bits avec le même nombre de bits (ce qui est nécessaire pour le chiffrement Feistel de travail).
Dans la deuxième étape, le nombre de bits qui peuvent être codées à l'aide d'un alphabet donné dépend de la "taille" de choisi de l'alphabet et de la longueur du code de coupon. Cette "entropie", donné en bits, est, en général, n'est pas un nombre entier, et encore moins un même nombre entier. Par exemple:
5-digit code à l'aide d'un de 30 caractères de l'alphabet résultats au 30^5 codes possibles qui signifie ld(30^5)=24.53 bits/code promo.
Pour un code à quatre chiffres, il y a une solution simple: étant Donné un de 32 Caractères de l'alphabet, vous pouvez encoder *ld(32^4)=5*4=20* Bits. De sorte que vous pouvez simplement mettre la BITCOUNT
- 20 et modifier l' for
boucle dans la deuxième partie du code à exécuter jusqu' 4
(au lieu de 6
)
La génération d'un code à cinq chiffres est un peu plus compliqué et somhow "affaiblit" l'algorithme: Vous pouvez définir l' BITCOUNT
à 24 et tout simplement de générer un 5 chiffres code à partir d'un alphabet de 30 caractères (enlever les deux personnages de l' ALPHABET
chaîne et de laisser l' for
boucle de courir jusqu' 5
).
Mais cela ne génère pas possible de 5 chiffres-codes: avec 24 bits, vous ne pouvez obtenir de 16777216 valeurs possibles de cryptage de la scène, les 5 chiffres de codes pourrait coder 24,300,000 possible nombres, de sorte que certains codes ne sera jamais produite. Plus précisément, la dernière position du code, ils ne contiennent certains caractères de l'alphabet. Ceci peut être vu comme un inconvénient, car il se rétrécit vers le bas l'ensemble des codes valides de façon évidente.
Lors du décodage d'un code promo, vous devez exécuter l' codeFromCoupon
de la fonction et de vérifier ensuite, si le bit 25 de la suite est définie. Ce serait la marque d'un code non valide que vous pouvez rejeter immédiatement. Notez que, dans la pratique, cela peut même être un avantage, car elle permet une vérification rapide (par exemple sur le côté client) de la validité d'un code sans donner tous les éléments internes de l'algorithme.
Si le bit 25 n'est pas ensemble vous vous appelez l' crypt
fonction et obtenir le numéro d'origine.