public byte[] Decrypt(byte[] message, PrivateKey privateKey, PublicKey publicKey) { var keySize = publicKey.n.ToByteArray().Length; var encryptedBlockSize = keySize; var sourceBlockSize = keySize - preffix.Length - 2; var numberBlocks = message.Length / encryptedBlockSize; if (message.Length % encryptedBlockSize != 0) throw new ArgumentException("Wrong size of encrypted message"); var decryptedMessage = new byte[numberBlocks * sourceBlockSize]; Parallel.For(0, numberBlocks, (i) => //for (var i = 0; i < numberBlocks; i++) { var part = new byte[encryptedBlockSize]; Array.Copy(message, i * encryptedBlockSize, part, 0, encryptedBlockSize); var Mi = new BigInteger(part); var D = (publicKey.b * publicKey.b + 4 * Mi) % publicKey.n; //var s = BigInteger.ModPow(D, (privateKey.p + 1) / 4, privateKey.p); //var r = BigInteger.ModPow(D, (privateKey.q + 1) / 4, privateKey.q); var s = BigIntegerHelper.fast_exp(D, (privateKey.p + 1) / 4, privateKey.p); var r = BigIntegerHelper.fast_exp(D, (privateKey.q + 1) / 4, privateKey.q); BigInteger yp, yq; BigInteger d = 1; ExtendedEuclid(privateKey.p, privateKey.q, out yp, out yq, out d); var roots = new BigInteger[4]; roots[0] = BigInteger.Abs(yp * privateKey.p * r + yq * privateKey.q * s); roots[1] = (-roots[0]) % publicKey.n + publicKey.n; roots[0] = roots[0] % publicKey.n; roots[2] = BigInteger.Abs(yp * privateKey.p * r - yq * privateKey.q * s); roots[3] = (-roots[2]) % publicKey.n + publicKey.n; roots[2] = roots[2] % publicKey.n; for (var j = 0; j < 4; j++) { roots[j] = ((-publicKey.b + roots[j]) / 2) % publicKey.n; roots[j] = roots[j] < 0 ? roots[j] + publicKey.n : roots[j]; } var rightRoot = roots.First(num => num.ToByteArray().Skip(sourceBlockSize).Take(preffix.Length).SequenceEqual(preffix)); Array.Copy(rightRoot.ToByteArray(), 0, decryptedMessage, i * sourceBlockSize, sourceBlockSize); }); return decryptedMessage; }
public PublicKey GeneratePublicKey(PrivateKey key) { var n = key.p * key.q; var b = BigIntegerHelper.PositiveOddRandom(n / 1000000, n); return new PublicKey { n = n, b = b }; }
private static void TestOneByte() { RabinCryptosystem rabin = new RabinCryptosystem(new PrimeNumberGenerator(new MillerRabinTest())); //36157 var privateKey = new PrivateKey { p = 3163, q = 3167 }; var publicKey = new PublicKey { n = 10017221, b = 4562931 }; var message = new byte[] { 61 }; var encrypted = rabin.Encrypt(message, publicKey); var decrypted = rabin.Decrypt(encrypted, privateKey, publicKey); Console.Write("encrypted = "); for (var i = 0; i < encrypted.Length; i++) Console.Write("{0} ", encrypted[i]); Console.WriteLine(); Console.Write("decrypted = "); for (var i = 0; i < decrypted.Length; i++) Console.Write("{0} ", decrypted[i]); Console.WriteLine(); }