Source Code Cross Referenced for RSA.java in  » 6.0-JDK-Modules » j2me » com » sun » midp » crypto » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » j2me » com.sun.midp.crypto 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *   
003:         *
004:         * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006:         * 
007:         * This program is free software; you can redistribute it and/or
008:         * modify it under the terms of the GNU General Public License version
009:         * 2 only, as published by the Free Software Foundation.
010:         * 
011:         * This program is distributed in the hope that it will be useful, but
012:         * WITHOUT ANY WARRANTY; without even the implied warranty of
013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014:         * General Public License version 2 for more details (a copy is
015:         * included at /legal/license.txt).
016:         * 
017:         * You should have received a copy of the GNU General Public License
018:         * version 2 along with this work; if not, write to the Free Software
019:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020:         * 02110-1301 USA
021:         * 
022:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023:         * Clara, CA 95054 or visit www.sun.com if you need additional
024:         * information or have any questions.
025:         */
026:
027:        package com.sun.midp.crypto;
028:
029:        /**
030:         * This class implements RSA encryption/decryption
031:         */
032:        public final class RSA extends Cipher {
033:            /** Local certificate key. */
034:            private RSAKey ckey = null;
035:            /** Current cipher mode. */
036:            private int mode;
037:            /** Local random number for seed. */
038:            private static SecureRandom rnd = null;
039:
040:            /** Signature pad offset. */
041:            private final static int PAD_OFFSET = 2;
042:
043:            /** Message to sign. */
044:            private byte[] messageToSign;
045:
046:            /** Number of bytes in the message to sign. */
047:            private int bytesInMessage;
048:
049:            /**
050:             * A native method for performing modular exponentiation.
051:             *
052:             * @param data      contains the data on which exponentiation is to
053:             *                  be performed
054:             * @param exponent  contains the exponent, e.g. 65537 (decimal) is 
055:             *                  written as a three-byte array containing 
056:             *                  0x01, 0x00, 0x01
057:             * @param modulus   contains the modulus
058:             * @param result    the result of the modular exponentiation is 
059:             *                  returned in this array
060:             * @return          length of the result in bytes
061:             * @exception IllegalArgumentException if a argument is too long for
062:             *    the native code to handle. (currently (32K - 8) bits max)
063:             */
064:            private static native int modExp(byte[] data, byte[] exponent,
065:                    byte[] modulus, byte[] result)
066:                    throws IllegalArgumentException;
067:
068:            /**
069:             * Performs an RSA operation on specified data. If the data length
070:             * is not the same as the modulus length (as may happen for an 
071:             * encryption request), PKCS#1 block type 2 padding is added.
072:             * <P />
073:             * @param data byte array to be encrypted/decrypted
074:             * @return a byte array containing the result
075:             * @exception IllegalStateException 
076:             *            if the encryption/decryption key is missing a modulus or
077:             *            exponent
078:             */
079:            private byte[] doIt(byte[] data) {
080:                int modLen = ckey.getModulusLen();
081:                byte[] buf = new byte[modLen];
082:                byte[] mod = new byte[modLen];
083:                int bufLen;
084:
085:                // Note: Both RSAPublicKey and RSAPrivateKey provide the same
086:                // interface
087:                short val = ckey.getModulus(mod, (short) 0);
088:
089:                byte[] tmp = new byte[modLen];
090:                val = ckey.getExponent(tmp, (short) 0);
091:                byte[] exp = new byte[val];
092:                System.arraycopy(tmp, 0, exp, 0, val);
093:
094:                bufLen = modExp(data, exp, mod, buf);
095:
096:                if (bufLen == modLen) {
097:                    return buf;
098:                } else if (bufLen < modLen) {
099:                    // Reuse tmp which already points to a byte array of modLen size
100:                    for (int i = 0; i < modLen; i++)
101:                        tmp[i] = 0;
102:
103:                    if (buf[0] == (byte) 0x01) {
104:                        tmp[0] = (byte) 0x00;
105:                        tmp[1] = (byte) 0x01;
106:                        for (int i = 2; i < modLen - bufLen + 1; i++) {
107:                            tmp[i] = (byte) 0xff;
108:                        }
109:                        System.arraycopy(buf, 1, tmp, modLen - bufLen + 1,
110:                                (bufLen - 1));
111:                    } else {
112:                        System
113:                                .arraycopy(buf, 0, tmp, (modLen - bufLen),
114:                                        bufLen);
115:                    }
116:
117:                    return tmp;
118:                } else { // bufLen > modLen, key may be too long
119:                    throw new IllegalArgumentException("Key too long");
120:                }
121:            }
122:
123:            /**
124:             * Constructor for RSA.
125:             *
126:             * @exception RuntimeException if the random number generator can't be
127:             *            created
128:             */
129:            public RSA() {
130:                mode = Cipher.MODE_UNINITIALIZED;
131:
132:                try {
133:                    rnd = SecureRandom
134:                            .getInstance(SecureRandom.ALG_SECURE_RANDOM);
135:                } catch (NoSuchAlgorithmException e) {
136:                    throw new RuntimeException(
137:                            "Random number generator missing");
138:                }
139:            }
140:
141:            /**
142:             * Called by the factory method to set the mode and padding parameters.
143:             * Need because Class.newInstance does not take args.
144:             *
145:             * @param mode the mode parsed from the transformation parameter of
146:             *             getInstance and upper cased
147:             * @param padding the padding parsed from the transformation parameter of
148:             *                getInstance and upper cased
149:             *
150:             * @exception NoSuchPaddingException if <code>transformation</code>
151:             * contains a padding scheme that is not available.
152:             * @exception IllegalArgumentException if mode is incorrect
153:             */
154:            protected void setChainingModeAndPadding(String mode, String padding)
155:                    throws NoSuchPaddingException {
156:
157:                if (!(mode.equals("") || mode.equals("NONE"))) {
158:                    throw new IllegalArgumentException("illegal chaining mode");
159:                }
160:
161:                // NOPADDING is not an option.
162:                if (!(padding.equals("") || padding.equals("PKCS1PADDING"))) {
163:                    throw new NoSuchPaddingException();
164:                }
165:            }
166:
167:            /**
168:             * Initializes this cipher with a key and a set of algorithm
169:             * parameters.
170:             *
171:             * @param opMode the operation mode of this cipher
172:             * @param key the encryption key
173:             * @param params the algorithm parameters
174:             *
175:             * @exception java.security.InvalidKeyException if the given key
176:             * is inappropriate for initializing this cipher
177:             * @exception java.security.InvalidAlgorithmParameterException
178:             * if the given algorithm parameters are inappropriate for this cipher
179:             * @exception IllegalArgumentException if opMode is incorrect
180:             */
181:            public void init(int opMode, Key key, CryptoParameter params)
182:                    throws InvalidKeyException,
183:                    InvalidAlgorithmParameterException {
184:
185:                if (!(key instanceof  RSAKey)) {
186:                    throw new InvalidKeyException();
187:                }
188:
189:                if (opMode != DECRYPT_MODE && opMode != ENCRYPT_MODE) {
190:                    throw new IllegalArgumentException("Wrong operation mode");
191:                }
192:
193:                mode = opMode;
194:                ckey = (RSAKey) key;
195:
196:                if (ckey.getModulusLen() == 0) {
197:                    throw new InvalidKeyException();
198:                }
199:
200:                messageToSign = new byte[ckey.getModulusLen()];
201:                bytesInMessage = 0;
202:            }
203:
204:            /**
205:             * Fills the internal buffer to be encrypted or decrypted
206:             * (depending on how this cipher was initialized).
207:             * For the RSA public key cipher there is no output until doFinal.
208:             *
209:             * @param inBuf the input buffer
210:             * @param inOff the offset in <code>input</code> where the input
211:             * starts
212:             * @param inLen the input length
213:             * @param outBuf the buffer for the result
214:             * @param outOff the offset in <code>output</code> where the result
215:             * is stored
216:             *
217:             * @return the number of bytes stored in <code>output</code>
218:             *
219:             * @exception IllegalStateException if this cipher is in a wrong state
220:             * (e.g., has not been initialized)
221:             * @exception ShortBufferException if the given output buffer is too small
222:             * to hold the result
223:             * @exception IllegalArgumentException if a length or offset is incorrect
224:             */
225:            public int update(byte inBuf[], int inOff, int inLen,
226:                    byte outBuf[], int outOff) throws IllegalStateException,
227:                    ShortBufferException {
228:
229:                addToMessage(inBuf, inOff, inLen);
230:                return 0;
231:            }
232:
233:            /**
234:             * Fills the internal message buffer to be encrypted or decrypted
235:             * (depending on how this cipher was initialized).
236:             * For the RSA public key cipher there is no output until doFinal.
237:             *
238:             * @param inBuf the input buffer
239:             * @param inOff the offset in <code>input</code> where the input
240:             * starts
241:             * @param inLen the input length
242:             *
243:             * @exception IllegalStateException if this cipher is in a wrong state
244:             * (e.g., has not been initialized)
245:             * @exception IllegalArgumentException if a length or offset is incorrect
246:             */
247:            private void addToMessage(byte inBuf[], int inOff, int inLen)
248:                    throws IllegalStateException {
249:                int bytesToCopy;
250:
251:                if (mode == Cipher.MODE_UNINITIALIZED) {
252:                    throw new IllegalStateException();
253:                }
254:
255:                if (inLen == 0) {
256:                    return;
257:                }
258:
259:                if (inBuf == null || inOff < 0 || inLen < 0
260:                        || inOff + inLen > inBuf.length) {
261:                    throw new IllegalArgumentException("input out of bounds");
262:                }
263:
264:                bytesToCopy = messageToSign.length - bytesInMessage;
265:                if (inLen < bytesToCopy) {
266:                    bytesToCopy = inLen;
267:                }
268:
269:                System.arraycopy(inBuf, inOff, messageToSign, bytesInMessage,
270:                        bytesToCopy);
271:                bytesInMessage += bytesToCopy;
272:            }
273:
274:            /**
275:             * Performs the crypto process the buffer.
276:             *
277:             * @param inBuf the input buffer
278:             * @param inOff the offset in <code>input</code> where the input
279:             * starts
280:             * @param inLen the input length
281:             * @param outBuf the buffer for the result
282:             * @param outOff the offset in <code>output</code> where the result
283:             * is stored
284:             *
285:             * @return the number of bytes stored in <code>output</code>
286:             *
287:             * @exception IllegalStateException if this cipher is in a wrong state
288:             * (e.g., has not been initialized)
289:             * @exception IllegalBlockSizeException if this cipher is a block cipher,
290:             * no padding has been requested (only in encryption mode), and the total
291:             * input length of the data processed by this cipher is not a multiple of
292:             * block size
293:             * @exception ShortBufferException if the given output buffer is too small
294:             * to hold the result
295:             * @exception BadPaddingException if this cipher is in decryption mode,
296:             * and (un)padding has been requested, but the decrypted data is not
297:             * bounded by the appropriate padding bytes
298:             * @exception IllegalArgumentException if input is greater than the
299:             *            cipher with the given key can handle
300:             */
301:            private int performRsa(byte inBuf[], int inOff, int inLen,
302:                    byte outBuf[], int outOff) throws IllegalStateException,
303:                    ShortBufferException, IllegalBlockSizeException,
304:                    BadPaddingException {
305:                int modLen;
306:                int outLen;
307:                byte[] tmp;
308:                byte[] res;
309:                int padLen;
310:                int endOfPad;
311:
312:                modLen = ckey.getModulusLen();
313:
314:                switch (mode) {
315:                case Cipher.ENCRYPT_MODE:
316:                    if (inLen > modLen - 11) {
317:                        throw new IllegalArgumentException("Too much input");
318:                    }
319:
320:                    /*
321:                     * Add PKCS#1 (ver 1.5) padding
322:                     * 0x00 | 0x02 | <random, non-zero pad bytes> | 0x00 | <data>
323:                     */
324:                    tmp = new byte[modLen];
325:                    tmp[0] = (byte) 0x00;
326:
327:                    padLen = modLen - inLen - 3;
328:                    endOfPad = padLen + PAD_OFFSET;
329:
330:                    if (ckey instanceof  RSAPublicKey) {
331:                        tmp[1] = (byte) 0x02; // for block type 02
332:
333:                        // Use random padding (replacing 0x00s)
334:                        rnd.nextBytes(tmp, PAD_OFFSET, padLen);
335:
336:                        for (int i = PAD_OFFSET; i < endOfPad; i++) {
337:                            if (tmp[i] == (byte) 0x00) {
338:                                // padding byte must be non-zero
339:                                tmp[i] = (byte) 0xff;
340:                            }
341:                        }
342:                    } else {
343:                        // NOTE: RFC2313 suggests 0x01 for private key signatures
344:                        tmp[1] = (byte) 0x01;
345:                        for (int i = PAD_OFFSET; i < endOfPad; i++) {
346:                            tmp[i] = (byte) 0xff;
347:                        }
348:                    }
349:
350:                    if (inLen > modLen) {
351:                        throw new IllegalArgumentException("inlen > modlen");
352:                    }
353:
354:                    tmp[modLen - inLen - 1] = (byte) 0x00;
355:                    System.arraycopy(inBuf, inOff, tmp, modLen - inLen, inLen);
356:
357:                    res = doIt(tmp);
358:
359:                    if (outOff + res.length > outBuf.length) {
360:                        throw new ShortBufferException();
361:                    }
362:
363:                    System.arraycopy(res, 0, outBuf, outOff, res.length);
364:                    outLen = res.length;
365:                    break;
366:
367:                case Cipher.DECRYPT_MODE:
368:                    // This is specified in RFC2313
369:                    if (inLen != modLen) {
370:                        throw new IllegalArgumentException("inlen != modlen");
371:                    }
372:
373:                    if (inOff != 0) {
374:                        tmp = new byte[modLen];
375:                        System.arraycopy(inBuf, inOff, tmp, 0, modLen);
376:                        res = doIt(tmp);
377:                    } else {
378:                        res = doIt(inBuf);
379:                    }
380:
381:                    // Count number of padding bytes (these must be non-zero)
382:                    padLen = 0;
383:                    for (int i = 2; (i < res.length) && (res[i] != (byte) 0x00); i++) {
384:                        padLen++;
385:                    }
386:
387:                    /*
388:                     * Note that whatever our decryption key type is,
389:                     * the other side used an opposite key type when encrypting
390:                     * so if our key type is TYPE_RSA_PUBLIC, the sender used
391:                     * TYPE_RSA_PRIVATE and the expected block type after 
392:                     * decryption (before encryption) is 0x00 or 0x01
393:                     */
394:                    if ((padLen < modLen - 3)
395:                            && (res.length > 1)
396:                            && (res[0] == (byte) 0x00)
397:                            && (((ckey instanceof  RSAPublicKey) && ((res[1] == (byte) 0x01) || (res[1] == (byte) 0x00))) || ((ckey instanceof  RSAPrivateKey) && (res[1] == (byte) 0x02)))) {
398:                        outLen = modLen - padLen - 3;
399:
400:                        if (outOff + outLen > outBuf.length) {
401:                            throw new ShortBufferException();
402:                        }
403:
404:                        System.arraycopy(res, padLen + 3, outBuf, outOff,
405:                                outLen);
406:                    } else {
407:                        throw new BadPaddingException();
408:                    }
409:
410:                    break;
411:
412:                default:
413:                    throw new IllegalStateException();
414:                }
415:
416:                return outLen;
417:            }
418:
419:            /**
420:             * Process the final data record.
421:             * 
422:             * @param inBuf input buffer of data 
423:             * @param inOff offset in the provided input buffer
424:             * @param inLen length of data to be processed
425:             * @param outBuf output buffer of data 
426:             * @param outOff offset in the provided output buffer
427:             * @return number of bytes copied to output buffer
428:             *
429:             * @exception IllegalStateException if this cipher is in a wrong state
430:             * (e.g., has not been initialized)
431:             * @exception IllegalBlockSizeException if this cipher is a block cipher,
432:             * no padding has been requested (only in encryption mode), and the total
433:             * input length of the data processed by this cipher is not a multiple of
434:             * block size
435:             * @exception ShortBufferException if the given output buffer is too small
436:             * to hold the result
437:             * @exception BadPaddingException if this cipher is in decryption mode,
438:             * and (un)padding has been requested, but the decrypted data is not
439:             * bounded by the appropriate padding bytes
440:             * @exception IllegalArgumentException if input is greater than the
441:             *            cipher with the given key can handle, or the output
442:             *            parameters are invalid
443:             */
444:            public int doFinal(byte[] inBuf, int inOff, int inLen,
445:                    byte[] outBuf, int outOff) throws IllegalStateException,
446:                    ShortBufferException, IllegalBlockSizeException,
447:                    BadPaddingException {
448:
449:                addToMessage(inBuf, inOff, inLen);
450:
451:                if (outBuf == null || outOff < 0) {
452:                    throw new IllegalArgumentException("output out of bounds");
453:                }
454:
455:                int val = performRsa(messageToSign, 0, bytesInMessage, outBuf,
456:                        outOff);
457:
458:                try {
459:                    init(mode, ckey);
460:                } catch (InvalidKeyException ike) {
461:                    // Ignore, nothing to do
462:                }
463:
464:                return val;
465:            }
466:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.