History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/com/sun/crypto/provider/RSACipher.java (1 of 18352 files). Show all

Unified · Split

java/pkg/com/sun/crypto/provider/RSACipher.java+444−0
@@ -0,0 +1,444 @@
1+/*
2+ * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package com.sun.crypto.provider;
27+
28+import java.util.Locale;
29+
30+import java.security.*;
31+import java.security.interfaces.*;
32+import java.security.spec.AlgorithmParameterSpec;
33+import java.security.spec.InvalidParameterSpecException;
34+import java.security.spec.MGF1ParameterSpec;
35+
36+import javax.crypto.*;
37+import javax.crypto.spec.PSource;
38+import javax.crypto.spec.OAEPParameterSpec;
39+
40+import sun.security.rsa.*;
41+import sun.security.jca.Providers;
42+
43+/**
44+ * RSA cipher implementation. Supports RSA en/decryption and signing/verifying
45+ * using PKCS#1 v1.5 padding and without padding (raw RSA). Note that raw RSA
46+ * is supported mostly for completeness and should only be used in rare cases.
47+ *
48+ * Objects should be instantiated by calling Cipher.getInstance() using the
49+ * following algorithm names:
50+ * . "RSA/ECB/PKCS1Padding" (or "RSA") for PKCS#1 padding. The mode (blocktype)
51+ * is selected based on the en/decryption mode and public/private key used
52+ * . "RSA/ECB/NoPadding" for rsa RSA.
53+ *
54+ * We only do one RSA operation per doFinal() call. If the application passes
55+ * more data via calls to update() or doFinal(), we throw an
56+ * IllegalBlockSizeException when doFinal() is called (see JCE API spec).
57+ * Bulk encryption using RSA does not make sense and is not standardized.
58+ *
59+ * Note: RSA keys should be at least 512 bits long
60+ *
61+ * @since 1.5
62+ * @author Andreas Sterbenz
63+ */
64+public final class RSACipher extends CipherSpi {
65+
66+ // constant for an empty byte array
67+ private final static byte[] B0 = new byte[0];
68+
69+ // mode constant for public key encryption
70+ private final static int MODE_ENCRYPT = 1;
71+ // mode constant for private key decryption
72+ private final static int MODE_DECRYPT = 2;
73+ // mode constant for private key encryption (signing)
74+ private final static int MODE_SIGN = 3;
75+ // mode constant for public key decryption (verifying)
76+ private final static int MODE_VERIFY = 4;
77+
78+ // constant for raw RSA
79+ private final static String PAD_NONE = "NoPadding";
80+ // constant for PKCS#1 v1.5 RSA
81+ private final static String PAD_PKCS1 = "PKCS1Padding";
82+ // constant for PKCS#2 v2.0 OAEP with MGF1
83+ private final static String PAD_OAEP_MGF1 = "OAEP";
84+
85+ // current mode, one of MODE_* above. Set when init() is called
86+ private int mode;
87+
88+ // active padding type, one of PAD_* above. Set by setPadding()
89+ private String paddingType;
90+
91+ // padding object
92+ private RSAPadding padding;
93+
94+ // cipher parameter for OAEP padding
95+ private OAEPParameterSpec spec = null;
96+
97+ // buffer for the data
98+ private byte[] buffer;
99+ // offset into the buffer (number of bytes buffered)
100+ private int bufOfs;
101+
102+ // size of the output
103+ private int outputSize;
104+
105+ // the public key, if we were initialized using a public key
106+ private RSAPublicKey publicKey;
107+ // the private key, if we were initialized using a private key
108+ private RSAPrivateKey privateKey;
109+
110+ // hash algorithm for OAEP
111+ private String oaepHashAlgorithm = "SHA-1";
112+
113+ public RSACipher() {
114+ paddingType = PAD_PKCS1;
115+ }
116+
117+ // modes do not make sense for RSA, but allow ECB
118+ // see JCE spec
119+ protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
120+ if (mode.equalsIgnoreCase("ECB") == false) {
121+ throw new NoSuchAlgorithmException("Unsupported mode " + mode);
122+ }
123+ }
124+
125+ // set the padding type
126+ // see JCE spec
127+ protected void engineSetPadding(String paddingName)
128+ throws NoSuchPaddingException {
129+ if (paddingName.equalsIgnoreCase(PAD_NONE)) {
130+ paddingType = PAD_NONE;
131+ } else if (paddingName.equalsIgnoreCase(PAD_PKCS1)) {
132+ paddingType = PAD_PKCS1;
133+ } else {
134+ String lowerPadding = paddingName.toLowerCase(Locale.ENGLISH);
135+ if (lowerPadding.equals("oaeppadding")) {
136+ paddingType = PAD_OAEP_MGF1;
137+ } else if (lowerPadding.startsWith("oaepwith") &&
138+ lowerPadding.endsWith("andmgf1padding")) {
139+ paddingType = PAD_OAEP_MGF1;
140+ // "oaepwith".length() == 8
141+ // "andmgf1padding".length() == 14
142+ oaepHashAlgorithm =
143+ paddingName.substring(8, paddingName.length() - 14);
144+ // check if MessageDigest appears to be available
145+ // avoid getInstance() call here
146+ if (Providers.getProviderList().getService
147+ ("MessageDigest", oaepHashAlgorithm) == null) {
148+ throw new NoSuchPaddingException
149+ ("MessageDigest not available for " + paddingName);
150+ }
151+ } else {
152+ throw new NoSuchPaddingException
153+ ("Padding " + paddingName + " not supported");
154+ }
155+ }
156+ }
157+
158+ // return 0 as block size, we are not a block cipher
159+ // see JCE spec
160+ protected int engineGetBlockSize() {
161+ return 0;
162+ }
163+
164+ // return the output size
165+ // see JCE spec
166+ protected int engineGetOutputSize(int inputLen) {
167+ return outputSize;
168+ }
169+
170+ // no iv, return null
171+ // see JCE spec
172+ protected byte[] engineGetIV() {
173+ return null;
174+ }
175+
176+ // see JCE spec
177+ protected AlgorithmParameters engineGetParameters() {
178+ if (spec != null) {
179+ try {
180+ AlgorithmParameters params =
181+ AlgorithmParameters.getInstance("OAEP", "SunJCE");
182+ params.init(spec);
183+ return params;
184+ } catch (NoSuchAlgorithmException nsae) {
185+ // should never happen
186+ throw new RuntimeException("Cannot find OAEP " +
187+ " AlgorithmParameters implementation in SunJCE provider");
188+ } catch (NoSuchProviderException nspe) {
189+ // should never happen
190+ throw new RuntimeException("Cannot find SunJCE provider");
191+ } catch (InvalidParameterSpecException ipse) {
192+ // should never happen
193+ throw new RuntimeException("OAEPParameterSpec not supported");
194+ }
195+ } else {
196+ return null;
197+ }
198+ }
199+
200+ // see JCE spec
201+ protected void engineInit(int opmode, Key key, SecureRandom random)
202+ throws InvalidKeyException {
203+ try {
204+ init(opmode, key, random, null);
205+ } catch (InvalidAlgorithmParameterException iape) {
206+ // never thrown when null parameters are used;
207+ // but re-throw it just in case
208+ InvalidKeyException ike =
209+ new InvalidKeyException("Wrong parameters");
210+ ike.initCause(iape);
211+ throw ike;
212+ }
213+ }
214+
215+ // see JCE spec
216+ protected void engineInit(int opmode, Key key,
217+ AlgorithmParameterSpec params, SecureRandom random)
218+ throws InvalidKeyException, InvalidAlgorithmParameterException {
219+ init(opmode, key, random, params);
220+ }
221+
222+ // see JCE spec
223+ protected void engineInit(int opmode, Key key,
224+ AlgorithmParameters params, SecureRandom random)
225+ throws InvalidKeyException, InvalidAlgorithmParameterException {
226+ if (params == null) {
227+ init(opmode, key, random, null);
228+ } else {
229+ try {
230+ OAEPParameterSpec spec = (OAEPParameterSpec)
231+ params.getParameterSpec(OAEPParameterSpec.class);
232+ init(opmode, key, random, spec);
233+ } catch (InvalidParameterSpecException ipse) {
234+ InvalidAlgorithmParameterException iape =
235+ new InvalidAlgorithmParameterException("Wrong parameter");
236+ iape.initCause(ipse);
237+ throw iape;
238+ }
239+ }
240+ }
241+
242+ // initialize this cipher
243+ private void init(int opmode, Key key, SecureRandom random,
244+ AlgorithmParameterSpec params)
245+ throws InvalidKeyException, InvalidAlgorithmParameterException {
246+ boolean encrypt;
247+ switch (opmode) {
248+ case Cipher.ENCRYPT_MODE:
249+ case Cipher.WRAP_MODE:
250+ encrypt = true;
251+ break;
252+ case Cipher.DECRYPT_MODE:
253+ case Cipher.UNWRAP_MODE:
254+ encrypt = false;
255+ break;
256+ default:
257+ throw new InvalidKeyException("Unknown mode: " + opmode);
258+ }
259+ RSAKey rsaKey = RSAKeyFactory.toRSAKey(key);
260+ if (key instanceof RSAPublicKey) {
261+ mode = encrypt ? MODE_ENCRYPT : MODE_VERIFY;
262+ publicKey = (RSAPublicKey)key;
263+ privateKey = null;
264+ } else { // must be RSAPrivateKey per check in toRSAKey
265+ mode = encrypt ? MODE_SIGN : MODE_DECRYPT;
266+ privateKey = (RSAPrivateKey)key;
267+ publicKey = null;
268+ }
269+ int n = RSACore.getByteLength(rsaKey.getModulus());
270+ outputSize = n;
271+ bufOfs = 0;
272+ if (paddingType == PAD_NONE) {
273+ if (params != null) {
274+ throw new InvalidAlgorithmParameterException
275+ ("Parameters not supported");
276+ }
277+ padding = RSAPadding.getInstance(RSAPadding.PAD_NONE, n, random);
278+ buffer = new byte[n];
279+ } else if (paddingType == PAD_PKCS1) {
280+ if (params != null) {
281+ throw new InvalidAlgorithmParameterException
282+ ("Parameters not supported");
283+ }
284+ int blockType = (mode <= MODE_DECRYPT) ? RSAPadding.PAD_BLOCKTYPE_2
285+ : RSAPadding.PAD_BLOCKTYPE_1;
286+ padding = RSAPadding.getInstance(blockType, n, random);
287+ if (encrypt) {
288+ int k = padding.getMaxDataSize();
289+ buffer = new byte[k];
290+ } else {
291+ buffer = new byte[n];
292+ }
293+ } else { // PAD_OAEP_MGF1
294+ if ((mode == MODE_SIGN) || (mode == MODE_VERIFY)) {
295+ throw new InvalidKeyException
296+ ("OAEP cannot be used to sign or verify signatures");
297+ }
298+ OAEPParameterSpec myParams;
299+ if (params != null) {
300+ if (!(params instanceof OAEPParameterSpec)) {
301+ throw new InvalidAlgorithmParameterException
302+ ("Wrong Parameters for OAEP Padding");
303+ }
304+ myParams = (OAEPParameterSpec) params;
305+ } else {
306+ myParams = new OAEPParameterSpec(oaepHashAlgorithm, "MGF1",
307+ MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT);
308+ }
309+ padding = RSAPadding.getInstance(RSAPadding.PAD_OAEP_MGF1, n,
310+ random, myParams);
311+ if (encrypt) {
312+ int k = padding.getMaxDataSize();
313+ buffer = new byte[k];
314+ } else {
315+ buffer = new byte[n];
316+ }
317+ }
318+ }
319+
320+ // internal update method
321+ private void update(byte[] in, int inOfs, int inLen) {
322+ if ((inLen == 0) || (in == null)) {
323+ return;
324+ }
325+ if (bufOfs + inLen > buffer.length) {
326+ bufOfs = buffer.length + 1;
327+ return;
328+ }
329+ System.arraycopy(in, inOfs, buffer, bufOfs, inLen);
330+ bufOfs += inLen;
331+ }
332+
333+ // internal doFinal() method. Here we perform the actual RSA operation
334+ private byte[] doFinal() throws BadPaddingException,
335+ IllegalBlockSizeException {
336+ if (bufOfs > buffer.length) {
337+ throw new IllegalBlockSizeException("Data must not be longer "
338+ + "than " + buffer.length + " bytes");
339+ }
340+ try {
341+ byte[] data;
342+ switch (mode) {
343+ case MODE_SIGN:
344+ data = padding.pad(buffer, 0, bufOfs);
345+ return RSACore.rsa(data, privateKey);
346+ case MODE_VERIFY:
347+ byte[] verifyBuffer = RSACore.convert(buffer, 0, bufOfs);
348+ data = RSACore.rsa(verifyBuffer, publicKey);
349+ return padding.unpad(data);
350+ case MODE_ENCRYPT:
351+ data = padding.pad(buffer, 0, bufOfs);
352+ return RSACore.rsa(data, publicKey);
353+ case MODE_DECRYPT:
354+ byte[] decryptBuffer = RSACore.convert(buffer, 0, bufOfs);
355+ data = RSACore.rsa(decryptBuffer, privateKey);
356+ return padding.unpad(data);
357+ default:
358+ throw new AssertionError("Internal error");
359+ }
360+ } finally {
361+ bufOfs = 0;
362+ }
363+ }
364+
365+ // see JCE spec
366+ protected byte[] engineUpdate(byte[] in, int inOfs, int inLen) {
367+ update(in, inOfs, inLen);
368+ return B0;
369+ }
370+
371+ // see JCE spec
372+ protected int engineUpdate(byte[] in, int inOfs, int inLen, byte[] out,
373+ int outOfs) {
374+ update(in, inOfs, inLen);
375+ return 0;
376+ }
377+
378+ // see JCE spec
379+ protected byte[] engineDoFinal(byte[] in, int inOfs, int inLen)
380+ throws BadPaddingException, IllegalBlockSizeException {
381+ update(in, inOfs, inLen);
382+ return doFinal();
383+ }
384+
385+ // see JCE spec
386+ protected int engineDoFinal(byte[] in, int inOfs, int inLen, byte[] out,
387+ int outOfs) throws ShortBufferException, BadPaddingException,
388+ IllegalBlockSizeException {
389+ if (outputSize > out.length - outOfs) {
390+ throw new ShortBufferException
391+ ("Need " + outputSize + " bytes for output");
392+ }
393+ update(in, inOfs, inLen);
394+ byte[] result = doFinal();
395+ int n = result.length;
396+ System.arraycopy(result, 0, out, outOfs, n);
397+ return n;
398+ }
399+
400+ // see JCE spec
401+ protected byte[] engineWrap(Key key) throws InvalidKeyException,
402+ IllegalBlockSizeException {
403+ byte[] encoded = key.getEncoded();
404+ if ((encoded == null) || (encoded.length == 0)) {
405+ throw new InvalidKeyException("Could not obtain encoded key");
406+ }
407+ if (encoded.length > buffer.length) {
408+ throw new InvalidKeyException("Key is too long for wrapping");
409+ }
410+ update(encoded, 0, encoded.length);
411+ try {
412+ return doFinal();
413+ } catch (BadPaddingException e) {
414+ // should not occur
415+ throw new InvalidKeyException("Wrapping failed", e);
416+ }
417+ }
418+
419+ // see JCE spec
420+ protected Key engineUnwrap(byte[] wrappedKey, String algorithm,
421+ int type) throws InvalidKeyException, NoSuchAlgorithmException {
422+ if (wrappedKey.length > buffer.length) {
423+ throw new InvalidKeyException("Key is too long for unwrapping");
424+ }
425+ update(wrappedKey, 0, wrappedKey.length);
426+ try {
427+ byte[] encoded = doFinal();
428+ return ConstructKeys.constructKey(encoded, algorithm, type);
429+ } catch (BadPaddingException e) {
430+ // should not occur
431+ throw new InvalidKeyException("Unwrapping failed", e);
432+ } catch (IllegalBlockSizeException e) {
433+ // should not occur, handled with length check above
434+ throw new InvalidKeyException("Unwrapping failed", e);
435+ }
436+ }
437+
438+ // see JCE spec
439+ protected int engineGetKeySize(Key key) throws InvalidKeyException {
440+ RSAKey rsaKey = RSAKeyFactory.toRSAKey(key);
441+ return rsaKey.getModulus().bitLength();
442+ }
443+
444+}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t