1 package org.bouncycastle.crypto.engines; 2 3 import java.math.BigInteger; 4 import java.security.SecureRandom; 5 6 import org.bouncycastle.crypto.AsymmetricBlockCipher; 7 import org.bouncycastle.crypto.CipherParameters; 8 import org.bouncycastle.crypto.DataLengthException; 9 import org.bouncycastle.crypto.params.ParametersWithRandom; 10 import org.bouncycastle.crypto.params.RSAKeyParameters; 11 import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters; 12 import org.bouncycastle.util.BigIntegers; 13 14 /** 15 * this does your basic RSA algorithm with blinding 16 */ 17 public class RSABlindedEngine 18 implements AsymmetricBlockCipher 19 { 20 private static final BigInteger ONE = BigInteger.valueOf(1); 21 22 private RSACoreEngine core = new RSACoreEngine(); 23 private RSAKeyParameters key; 24 private SecureRandom random; 25 26 /** 27 * initialise the RSA engine. 28 * 29 * @param forEncryption true if we are encrypting, false otherwise. 30 * @param param the necessary RSA key parameters. 31 */ init( boolean forEncryption, CipherParameters param)32 public void init( 33 boolean forEncryption, 34 CipherParameters param) 35 { 36 core.init(forEncryption, param); 37 38 if (param instanceof ParametersWithRandom) 39 { 40 ParametersWithRandom rParam = (ParametersWithRandom)param; 41 42 key = (RSAKeyParameters)rParam.getParameters(); 43 random = rParam.getRandom(); 44 } 45 else 46 { 47 key = (RSAKeyParameters)param; 48 random = new SecureRandom(); 49 } 50 } 51 52 /** 53 * Return the maximum size for an input block to this engine. 54 * For RSA this is always one byte less than the key size on 55 * encryption, and the same length as the key size on decryption. 56 * 57 * @return maximum size for an input block. 58 */ getInputBlockSize()59 public int getInputBlockSize() 60 { 61 return core.getInputBlockSize(); 62 } 63 64 /** 65 * Return the maximum size for an output block to this engine. 66 * For RSA this is always one byte less than the key size on 67 * decryption, and the same length as the key size on encryption. 68 * 69 * @return maximum size for an output block. 70 */ getOutputBlockSize()71 public int getOutputBlockSize() 72 { 73 return core.getOutputBlockSize(); 74 } 75 76 /** 77 * Process a single block using the basic RSA algorithm. 78 * 79 * @param in the input array. 80 * @param inOff the offset into the input buffer where the data starts. 81 * @param inLen the length of the data to be processed. 82 * @return the result of the RSA process. 83 * @exception DataLengthException the input block is too large. 84 */ processBlock( byte[] in, int inOff, int inLen)85 public byte[] processBlock( 86 byte[] in, 87 int inOff, 88 int inLen) 89 { 90 if (key == null) 91 { 92 throw new IllegalStateException("RSA engine not initialised"); 93 } 94 95 BigInteger input = core.convertInput(in, inOff, inLen); 96 97 BigInteger result; 98 if (key instanceof RSAPrivateCrtKeyParameters) 99 { 100 RSAPrivateCrtKeyParameters k = (RSAPrivateCrtKeyParameters)key; 101 102 BigInteger e = k.getPublicExponent(); 103 if (e != null) // can't do blinding without a public exponent 104 { 105 BigInteger m = k.getModulus(); 106 BigInteger r = BigIntegers.createRandomInRange(ONE, m.subtract(ONE), random); 107 108 BigInteger blindedInput = r.modPow(e, m).multiply(input).mod(m); 109 BigInteger blindedResult = core.processBlock(blindedInput); 110 111 BigInteger rInv = r.modInverse(m); 112 result = blindedResult.multiply(rInv).mod(m); 113 } 114 else 115 { 116 result = core.processBlock(input); 117 } 118 } 119 else 120 { 121 result = core.processBlock(input); 122 } 123 124 return core.convertOutput(result); 125 } 126 } 127