001: package org.bouncycastle.crypto.engines;
002:
003: import org.bouncycastle.crypto.AsymmetricBlockCipher;
004: import org.bouncycastle.crypto.CipherParameters;
005: import org.bouncycastle.crypto.DataLengthException;
006: import org.bouncycastle.crypto.params.ParametersWithRandom;
007: import org.bouncycastle.crypto.params.RSABlindingParameters;
008: import org.bouncycastle.crypto.params.RSAKeyParameters;
009:
010: import java.math.BigInteger;
011:
012: /**
013: * This does your basic RSA Chaum's blinding and unblinding as outlined in
014: * "Handbook of Applied Cryptography", page 475. You need to use this if you are
015: * trying to get another party to generate signatures without them being aware
016: * of the message they are signing.
017: */
018: public class RSABlindingEngine implements AsymmetricBlockCipher {
019: private RSACoreEngine core = new RSACoreEngine();
020:
021: private RSAKeyParameters key;
022: private BigInteger blindingFactor;
023:
024: private boolean forEncryption;
025:
026: /**
027: * Initialise the blinding engine.
028: *
029: * @param forEncryption true if we are encrypting (blinding), false otherwise.
030: * @param param the necessary RSA key parameters.
031: */
032: public void init(boolean forEncryption, CipherParameters param) {
033: RSABlindingParameters p;
034:
035: if (param instanceof ParametersWithRandom) {
036: ParametersWithRandom rParam = (ParametersWithRandom) param;
037:
038: p = (RSABlindingParameters) rParam.getParameters();
039: } else {
040: p = (RSABlindingParameters) param;
041: }
042:
043: core.init(forEncryption, p.getPublicKey());
044:
045: this .forEncryption = forEncryption;
046: this .key = p.getPublicKey();
047: this .blindingFactor = p.getBlindingFactor();
048: }
049:
050: /**
051: * Return the maximum size for an input block to this engine.
052: * For RSA this is always one byte less than the key size on
053: * encryption, and the same length as the key size on decryption.
054: *
055: * @return maximum size for an input block.
056: */
057: public int getInputBlockSize() {
058: return core.getInputBlockSize();
059: }
060:
061: /**
062: * Return the maximum size for an output block to this engine.
063: * For RSA this is always one byte less than the key size on
064: * decryption, and the same length as the key size on encryption.
065: *
066: * @return maximum size for an output block.
067: */
068: public int getOutputBlockSize() {
069: return core.getOutputBlockSize();
070: }
071:
072: /**
073: * Process a single block using the RSA blinding algorithm.
074: *
075: * @param in the input array.
076: * @param inOff the offset into the input buffer where the data starts.
077: * @param inLen the length of the data to be processed.
078: * @return the result of the RSA process.
079: * @throws DataLengthException the input block is too large.
080: */
081: public byte[] processBlock(byte[] in, int inOff, int inLen) {
082: BigInteger msg = core.convertInput(in, inOff, inLen);
083:
084: if (forEncryption) {
085: msg = blindMessage(msg);
086: } else {
087: msg = unblindMessage(msg);
088: }
089:
090: return core.convertOutput(msg);
091: }
092:
093: /*
094: * Blind message with the blind factor.
095: */
096: private BigInteger blindMessage(BigInteger msg) {
097: BigInteger blindMsg = blindingFactor;
098: blindMsg = msg.multiply(blindMsg.modPow(key.getExponent(), key
099: .getModulus()));
100: blindMsg = blindMsg.mod(key.getModulus());
101:
102: return blindMsg;
103: }
104:
105: /*
106: * Unblind the message blinded with the blind factor.
107: */
108: private BigInteger unblindMessage(BigInteger blindedMsg) {
109: BigInteger m = key.getModulus();
110: BigInteger msg = blindedMsg;
111: BigInteger blindFactorInverse = blindingFactor.modInverse(m);
112: msg = msg.multiply(blindFactorInverse);
113: msg = msg.mod(m);
114:
115: return msg;
116: }
117: }
|