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