1 files changed, 139 insertions, 0 deletions
diff --git a/Crypto/src/crypto/engines/RSABlindingEngine.cs b/Crypto/src/crypto/engines/RSABlindingEngine.cs
new file mode 100644
index 000000000..76b57a3f7
--- /dev/null
+++ b/Crypto/src/crypto/engines/RSABlindingEngine.cs
@@ -0,0 +1,139 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+ /**
+ * This does your basic RSA Chaum's blinding and unblinding as outlined in
+ * "Handbook of Applied Cryptography", page 475. You need to use this if you are
+ * trying to get another party to generate signatures without them being aware
+ * of the message they are signing.
+ */
+ public class RsaBlindingEngine
+ : IAsymmetricBlockCipher
+ {
+ private readonly RsaCoreEngine core = new RsaCoreEngine();
+
+ private RsaKeyParameters key;
+ private BigInteger blindingFactor;
+
+ private bool forEncryption;
+
+ public string AlgorithmName
+ {
+ get { return "RSA"; }
+ }
+
+ /**
+ * Initialise the blinding engine.
+ *
+ * @param forEncryption true if we are encrypting (blinding), false otherwise.
+ * @param param the necessary RSA key parameters.
+ */
+ public void Init(
+ bool forEncryption,
+ ICipherParameters param)
+ {
+ RsaBlindingParameters p;
+
+ if (param is ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ p = (RsaBlindingParameters)rParam.Parameters;
+ }
+ else
+ {
+ p = (RsaBlindingParameters)param;
+ }
+
+ core.Init(forEncryption, p.PublicKey);
+
+ this.forEncryption = forEncryption;
+ this.key = p.PublicKey;
+ this.blindingFactor = p.BlindingFactor;
+ }
+
+ /**
+ * Return the maximum size for an input block to this engine.
+ * For RSA this is always one byte less than the key size on
+ * encryption, and the same length as the key size on decryption.
+ *
+ * @return maximum size for an input block.
+ */
+ public int GetInputBlockSize()
+ {
+ return core.GetInputBlockSize();
+ }
+
+ /**
+ * Return the maximum size for an output block to this engine.
+ * For RSA this is always one byte less than the key size on
+ * decryption, and the same length as the key size on encryption.
+ *
+ * @return maximum size for an output block.
+ */
+ public int GetOutputBlockSize()
+ {
+ return core.GetOutputBlockSize();
+ }
+
+ /**
+ * Process a single block using the RSA blinding algorithm.
+ *
+ * @param in the input array.
+ * @param inOff the offset into the input buffer where the data starts.
+ * @param inLen the length of the data to be processed.
+ * @return the result of the RSA process.
+ * @throws DataLengthException the input block is too large.
+ */
+ public byte[] ProcessBlock(
+ byte[] inBuf,
+ int inOff,
+ int inLen)
+ {
+ BigInteger msg = core.ConvertInput(inBuf, inOff, inLen);
+
+ if (forEncryption)
+ {
+ msg = BlindMessage(msg);
+ }
+ else
+ {
+ msg = UnblindMessage(msg);
+ }
+
+ return core.ConvertOutput(msg);
+ }
+
+ /*
+ * Blind message with the blind factor.
+ */
+ private BigInteger BlindMessage(
+ BigInteger msg)
+ {
+ BigInteger blindMsg = blindingFactor;
+ blindMsg = msg.Multiply(blindMsg.ModPow(key.Exponent, key.Modulus));
+ blindMsg = blindMsg.Mod(key.Modulus);
+
+ return blindMsg;
+ }
+
+ /*
+ * Unblind the message blinded with the blind factor.
+ */
+ private BigInteger UnblindMessage(
+ BigInteger blindedMsg)
+ {
+ BigInteger m = key.Modulus;
+ BigInteger msg = blindedMsg;
+ BigInteger blindFactorInverse = blindingFactor.ModInverse(m);
+ msg = msg.Multiply(blindFactorInverse);
+ msg = msg.Mod(m);
+
+ return msg;
+ }
+ }
+}
|