/// <summary> /// Generic Z_n FPE encryption, FE1 scheme /// </summary> /// <param name="modulus">Use to determine the range of the numbers. Example, if the /// numbers range from 0 to 999, use "1000" here.</param> /// <param name="plaintext">The number to encrypt.</param> /// <param name="key">Secret key</param> /// <param name="tweak">Non-secret parameter, think of it as an IV</param> /// <returns>The encrypted number.</returns> public static BigInteger Encrypt(BigInteger modulus, BigInteger plaintext, byte[] key, byte[] tweak) { FPE_Encryptor F = new FPE_Encryptor(key, modulus, tweak); BigInteger a, b; NumberTheory.factor(modulus, out a, out b); int r = rounds(a, b); BigInteger X = plaintext; for (int i = 0; i != r; ++i) { BigInteger L = X / b; BigInteger R = X.mod(b); BigInteger W = (L + F.F(i, R)).mod(a); X = a * R + W; } return(X); }
/// <summary> /// Generic Z_n FPE decryption, FD1 scheme /// </summary> /// <param name="modulus">Use to determine the range of the numbers. Example, if the /// numbers range from 0 to 999, use "1000" here.</param> /// <param name="ciphertext">The number to decrypt.</param> /// <param name="key">Secret key</param> /// <param name="tweak">Non-secret parameter, think of it as an IV - use the same one used to encrypt</param> /// <returns>The decrypted number</returns> public static BigInteger Decrypt(BigInteger modulus, BigInteger ciphertext, byte[] key, byte[] tweak) { FPE_Encryptor F = new FPE_Encryptor(key, modulus, tweak); BigInteger a, b; NumberTheory.factor(modulus, out a, out b); int r = rounds(a, b); BigInteger X = ciphertext; for (int i = 0; i != r; ++i) { BigInteger W = X.mod(a); BigInteger R = X / a; BigInteger bigInteger = (W - F.F(r - i - 1, R)); BigInteger L = bigInteger.mod(a); X = b * L + R; } return(X); }