1 package org.bouncycastle.crypto.engines;
2
3 import java.math.BigInteger;
4
5 import org.bouncycastle.crypto.CipherParameters;
6 import org.bouncycastle.crypto.DataLengthException;
7 import org.bouncycastle.crypto.AsymmetricBlockCipher;
8 import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
9 import org.bouncycastle.crypto.params.RSAKeyParameters;
10 import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
11
12
15 public class RSAEngine
16 implements AsymmetricBlockCipher
17 {
18 private RSAKeyParameters key;
19 private boolean forEncryption;
20
21
27 public void init(
28 boolean forEncryption,
29 CipherParameters param)
30 {
31 this.key = (RSAKeyParameters)param;
32 this.forEncryption = forEncryption;
33 }
34
35
42 public int getInputBlockSize()
43 {
44 int bitSize = key.getModulus().bitLength();
45
46 if (forEncryption)
47 {
48 return (bitSize + 7) / 8 - 1;
49 }
50 else
51 {
52 return (bitSize + 7) / 8;
53 }
54 }
55
56
63 public int getOutputBlockSize()
64 {
65 int bitSize = key.getModulus().bitLength();
66
67 if (forEncryption)
68 {
69 return (bitSize + 7) / 8;
70 }
71 else
72 {
73 return (bitSize + 7) / 8 - 1;
74 }
75 }
76
77
86 public byte[] processBlock(
87 byte[] in,
88 int inOff,
89 int inLen)
90 {
91 if (inLen > (getInputBlockSize() + 1))
92 {
93 throw new DataLengthException("input too large for RSA cipher.\n");
94 }
95 else if (inLen == (getInputBlockSize() + 1) && (in[inOff] & 0x80) != 0)
96 {
97 throw new DataLengthException("input too large for RSA cipher.\n");
98 }
99
100 byte[] block;
101
102 if (inOff != 0 || inLen != in.length)
103 {
104 block = new byte[inLen];
105
106 System.arraycopy(in, inOff, block, 0, inLen);
107 }
108 else
109 {
110 block = in;
111 }
112
113 BigInteger input = new BigInteger(1, block);
114 byte[] output;
115
116 if (key instanceof RSAPrivateCrtKeyParameters)
117 {
118
119
120
121
122
123 RSAPrivateCrtKeyParameters crtKey = (RSAPrivateCrtKeyParameters)key;
124
125 BigInteger d = crtKey.getExponent();
126 BigInteger p = crtKey.getP();
127 BigInteger q = crtKey.getQ();
128 BigInteger dP = crtKey.getDP();
129 BigInteger dQ = crtKey.getDQ();
130 BigInteger qInv = crtKey.getQInv();
131
132 BigIntegerBigIntegerBigInteger // mP = ((input mod p) ^ dP)) mod p
133 mP = (input.remainder(p)).modPow(dP, p);
134
135 // mQ = ((input mod q) ^ dQ)) mod q
136 mQ = (input.remainder(q)).modPow(dQ, q);
137
138 // h = qInv * (mP - mQ) mod p
139 h = mP.subtract(mQ);
140 h = h.multiply(qInv);
141 h = h.mod(p); // mod (in Java) returns the positive residual
142
143 // m = h * q + mQ
144 m = h.multiply(q);
145 m = m.add(mQ);
146
147 output = m.toByteArray();
148 }
149 else
150 {
151 output = input.modPow(
152 key.getExponent(), key.getModulus()).toByteArray();
153 }
154
155 if (forEncryption)
156 {
157 if (output[0] == 0 && output.length > getOutputBlockSize()) // have ended up with an extra zero byte, copy down.
158 {
159 byte[] tmp = new byte[output.length - 1];
160
161 System.arraycopy(output, 1, tmp, 0, tmp.length);
162
163 return tmp;
164 }
165
166 if (output.length < getOutputBlockSize()) // have ended up with less bytes than normal, lengthen
167 {
168 byte[] tmp = new byte[getOutputBlockSize()];
169
170 System.arraycopy(output, 0, tmp, tmp.length - output.length, output.length);
171
172 return tmp;
173 }
174 }
175 else
176 {
177 if (output[0] == 0) // have ended up with an extra zero byte, copy down.
178 {
179 byte[] tmp = new byte[output.length - 1];
180
181 System.arraycopy(output, 1, tmp, 0, tmp.length);
182
183 return tmp;
184 }
185 }
186 return output;
187 }
188 }
189 ?????????????BigInteger??????????????????????????mP???????????????????input???????????????????????????????????p??????????????????????????????????????????????dP??????????????????????????????????????????????????p??????????????????????????mQ???????????????????input???????????????????????????????????q??????????????????????????????????????????????dQ??????????????????????????????????????????????????q??????????????????????????h?????????????????mP?????????????????????????????mQ?????????????h?????????????????h????????????????????????????qInv?????????????h?????????????????h???????????????????????p???????????????????????????????????????????????????????????????????m?????????????????h????????????????????????????q?????????????m?????????????????m???????????????????????mQ?????????????output??????????????????????m?????????????output??????????????????????input?????????????????????????key?????????????????????????????getExponent????????????????????????????????????????????key????????????????????????????????????????????????getModulus?????????????forEncryption?????????????????output???????????????????????????????????output???????????????????????????????????????????????????getOutputBlockSize?????????????????????????????????????????????????????????????????????????????????????????????????byte???????????????????????????????????byte????????????????????????????????????????output??????????????????????????????????output?????????????????????????????????????????????tmp?????????????????????????????????????????????????????tmp????????????????????????tmp?????????????????output?????????????????????????????????getOutputBlockSize????????????????????????????????????????????????????????????????????????????byte???????????????????????????????????byte????????????????????????????????????????getOutputBlockSize??????????????????????????????????output?????????????????????????????????????????????tmp??????????????????????????????????????????????????tmp???????????????????????????????????????????????????????????????output??????????????????????????????????????????????????????????????????????????????output????????????????????????tmp?????????????????output?????????????????????????????????????????????????????????byte???????????????????????????????????byte????????????????????????????????????????output??????????????????????????????????output?????????????????????????????????????????????tmp?????????????????????????????????????????????????????tmp????????????????????????tmp????????????????output