Source Code Cross Referenced for KeyProtector.java in  » 6.0-JDK-Modules » j2me » sun » security » provider » 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 » sun.security.provider 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * @(#)KeyProtector.java	1.23 06/10/10
003:         *
004:         * Copyright  1990-2006 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:
028:        package sun.security.provider;
029:
030:        import java.io.IOException;
031:        import java.io.UnsupportedEncodingException;
032:        import java.security.Key;
033:        import java.security.KeyStoreException;
034:        import java.security.MessageDigest;
035:        import java.security.NoSuchAlgorithmException;
036:        import java.security.SecureRandom;
037:        import java.security.UnrecoverableKeyException;
038:        import java.util.*;
039:
040:        import sun.security.pkcs.PKCS8Key;
041:        import sun.security.pkcs.EncryptedPrivateKeyInfo;
042:        import sun.security.x509.AlgorithmId;
043:        import sun.security.util.ObjectIdentifier;
044:        import sun.security.util.DerValue;
045:
046:        /**
047:         * This is an implementation of a Sun proprietary, exportable algorithm
048:         * intended for use when protecting (or recovering the cleartext version of)
049:         * sensitive keys.
050:         * This algorithm is not intended as a general purpose cipher.
051:         *
052:         * This is how the algorithm works for key protection:
053:         *
054:         * p - user password
055:         * s - random salt
056:         * X - xor key
057:         * P - to-be-protected key
058:         * Y - protected key
059:         * R - what gets stored in the keystore
060:         *
061:         * Step 1:
062:         * Take the user's password, append a random salt (of fixed size) to it,
063:         * and hash it: d1 = digest(p, s)
064:         * Store d1 in X.
065:         *
066:         * Step 2:
067:         * Take the user's password, append the digest result from the previous step,
068:         * and hash it: dn = digest(p, dn-1).
069:         * Store dn in X (append it to the previously stored digests).
070:         * Repeat this step until the length of X matches the length of the private key
071:         * P.
072:         *
073:         * Step 3:
074:         * XOR X and P, and store the result in Y: Y = X XOR P.
075:         *
076:         * Step 4:
077:         * Store s, Y, and digest(p, P) in the result buffer R:
078:         * R = s + Y + digest(p, P), where "+" denotes concatenation.
079:         * (NOTE: digest(p, P) is stored in the result buffer, so that when the key is
080:         * recovered, we can check if the recovered key indeed matches the original
081:         * key.) R is stored in the keystore.
082:         *
083:         * The protected key is recovered as follows:
084:         *
085:         * Step1 and Step2 are the same as above, except that the salt is not randomly
086:         * generated, but taken from the result R of step 4 (the first length(s)
087:         * bytes).
088:         *
089:         * Step 3 (XOR operation) yields the plaintext key.
090:         *
091:         * Then concatenate the password with the recovered key, and compare with the
092:         * last length(digest(p, P)) bytes of R. If they match, the recovered key is
093:         * indeed the same key as the original key.
094:         *
095:         * @author Jan Luehe
096:         *
097:         * @version 1.23, 10/10/06
098:         *
099:         * @see java.security.KeyStore
100:         * @see JavaKeyStore
101:         * @see KeyTool
102:         *
103:         * @since JDK1.2
104:         */
105:
106:        final class KeyProtector {
107:
108:            private static final int SALT_LEN = 20; // the salt length
109:            private static final String DIGEST_ALG = "SHA";
110:            private static final int DIGEST_LEN = 20;
111:
112:            // defined by JavaSoft
113:            private static final String KEY_PROTECTOR_OID = "1.3.6.1.4.1.42.2.17.1.1";
114:
115:            // The password used for protecting/recovering keys passed through this
116:            // key protector. We store it as a byte array, so that we can digest it.
117:            private byte[] passwdBytes;
118:
119:            private MessageDigest md;
120:
121:            /**
122:             * Creates an instance of this class, and initializes it with the given
123:             * password.
124:             *
125:             * <p>The password is expected to be in printable ASCII.
126:             * Normal rules for good password selection apply: at least
127:             * seven characters, mixed case, with punctuation encouraged.
128:             * Phrases or words which are easily guessed, for example by
129:             * being found in dictionaries, are bad.
130:             */
131:            public KeyProtector(char[] password)
132:                    throws NoSuchAlgorithmException {
133:                int i, j;
134:
135:                if (password == null) {
136:                    throw new IllegalArgumentException("password can't be null");
137:                }
138:                md = MessageDigest.getInstance(DIGEST_ALG);
139:                // Convert password to byte array, so that it can be digested
140:                passwdBytes = new byte[password.length * 2];
141:                for (i = 0, j = 0; i < password.length; i++) {
142:                    passwdBytes[j++] = (byte) (password[i] >> 8);
143:                    passwdBytes[j++] = (byte) password[i];
144:                }
145:            }
146:
147:            /**
148:             * Ensures that the password bytes of this key protector are
149:             * set to zero when there are no more references to it.
150:             */
151:            protected void finalize() {
152:                if (passwdBytes != null) {
153:                    Arrays.fill(passwdBytes, (byte) 0x00);
154:                    passwdBytes = null;
155:                }
156:            }
157:
158:            /*
159:             * Protects the given plaintext key, using the password provided at
160:             * construction time.
161:             */
162:            public byte[] protect(Key key) throws KeyStoreException {
163:                int i;
164:                int numRounds;
165:                byte[] digest;
166:                int xorOffset; // offset in xorKey where next digest will be stored
167:                int encrKeyOffset = 0;
168:
169:                if (key == null) {
170:                    throw new IllegalArgumentException(
171:                            "plaintext key can't be null");
172:                }
173:                byte[] plainKey = key.getEncoded();
174:
175:                // Determine the number of digest rounds
176:                numRounds = plainKey.length / DIGEST_LEN;
177:                if ((plainKey.length % DIGEST_LEN) != 0)
178:                    numRounds++;
179:
180:                // Create a random salt
181:                byte[] salt = new byte[SALT_LEN];
182:                SecureRandom random = new SecureRandom();
183:                random.nextBytes(salt);
184:
185:                // Set up the byte array which will be XORed with "plainKey"
186:                byte[] xorKey = new byte[plainKey.length];
187:
188:                // Compute the digests, and store them in "xorKey"
189:                for (i = 0, xorOffset = 0, digest = salt; i < numRounds; i++, xorOffset += DIGEST_LEN) {
190:                    md.update(passwdBytes);
191:                    md.update(digest);
192:                    digest = md.digest();
193:                    md.reset();
194:                    // Copy the digest into "xorKey"
195:                    if (i < numRounds - 1) {
196:                        System.arraycopy(digest, 0, xorKey, xorOffset,
197:                                digest.length);
198:                    } else {
199:                        System.arraycopy(digest, 0, xorKey, xorOffset,
200:                                xorKey.length - xorOffset);
201:                    }
202:                }
203:
204:                // XOR "plainKey" with "xorKey", and store the result in "tmpKey"
205:                byte[] tmpKey = new byte[plainKey.length];
206:                for (i = 0; i < tmpKey.length; i++) {
207:                    tmpKey[i] = (byte) (plainKey[i] ^ xorKey[i]);
208:                }
209:
210:                // Store salt and "tmpKey" in "encrKey"
211:                byte[] encrKey = new byte[salt.length + tmpKey.length
212:                        + DIGEST_LEN];
213:                System.arraycopy(salt, 0, encrKey, encrKeyOffset, salt.length);
214:                encrKeyOffset += salt.length;
215:                System.arraycopy(tmpKey, 0, encrKey, encrKeyOffset,
216:                        tmpKey.length);
217:                encrKeyOffset += tmpKey.length;
218:
219:                // Append digest(password, plainKey) as an integrity check to "encrKey"
220:                md.update(passwdBytes);
221:                Arrays.fill(passwdBytes, (byte) 0x00);
222:                passwdBytes = null;
223:                md.update(plainKey);
224:                digest = md.digest();
225:                md.reset();
226:                System.arraycopy(digest, 0, encrKey, encrKeyOffset,
227:                        digest.length);
228:
229:                // wrap the protected private key in a PKCS#8-style
230:                // EncryptedPrivateKeyInfo, and returns its encoding
231:                AlgorithmId encrAlg;
232:                try {
233:                    encrAlg = new AlgorithmId(new ObjectIdentifier(
234:                            KEY_PROTECTOR_OID));
235:                    return new EncryptedPrivateKeyInfo(encrAlg, encrKey)
236:                            .getEncoded();
237:                } catch (IOException ioe) {
238:                    throw new KeyStoreException(ioe.getMessage());
239:                }
240:            }
241:
242:            /*
243:             * Recovers the plaintext version of the given key (in protected format),
244:             * using the password provided at construction time.
245:             */
246:            public Key recover(EncryptedPrivateKeyInfo encrInfo)
247:                    throws UnrecoverableKeyException {
248:                int i;
249:                byte[] digest;
250:                int numRounds;
251:                int xorOffset; // offset in xorKey where next digest will be stored
252:                int encrKeyLen; // the length of the encrpyted key
253:
254:                // do we support the algorithm?
255:                AlgorithmId encrAlg = encrInfo.getAlgorithm();
256:                if (!(encrAlg.getOID().toString().equals(KEY_PROTECTOR_OID))) {
257:                    throw new UnrecoverableKeyException(
258:                            "Unsupported key protection " + "algorithm");
259:                }
260:
261:                byte[] protectedKey = encrInfo.getEncryptedData();
262:
263:                /*
264:                 * Get the salt associated with this key (the first SALT_LEN bytes of
265:                 * <code>protectedKey</code>)
266:                 */
267:                byte[] salt = new byte[SALT_LEN];
268:                System.arraycopy(protectedKey, 0, salt, 0, SALT_LEN);
269:
270:                // Determine the number of digest rounds
271:                encrKeyLen = protectedKey.length - SALT_LEN - DIGEST_LEN;
272:                numRounds = encrKeyLen / DIGEST_LEN;
273:                if ((encrKeyLen % DIGEST_LEN) != 0)
274:                    numRounds++;
275:
276:                // Get the encrypted key portion and store it in "encrKey"
277:                byte[] encrKey = new byte[encrKeyLen];
278:                System
279:                        .arraycopy(protectedKey, SALT_LEN, encrKey, 0,
280:                                encrKeyLen);
281:
282:                // Set up the byte array which will be XORed with "encrKey"
283:                byte[] xorKey = new byte[encrKey.length];
284:
285:                // Compute the digests, and store them in "xorKey"
286:                for (i = 0, xorOffset = 0, digest = salt; i < numRounds; i++, xorOffset += DIGEST_LEN) {
287:                    md.update(passwdBytes);
288:                    md.update(digest);
289:                    digest = md.digest();
290:                    md.reset();
291:                    // Copy the digest into "xorKey"
292:                    if (i < numRounds - 1) {
293:                        System.arraycopy(digest, 0, xorKey, xorOffset,
294:                                digest.length);
295:                    } else {
296:                        System.arraycopy(digest, 0, xorKey, xorOffset,
297:                                xorKey.length - xorOffset);
298:                    }
299:                }
300:
301:                // XOR "encrKey" with "xorKey", and store the result in "plainKey"
302:                byte[] plainKey = new byte[encrKey.length];
303:                for (i = 0; i < plainKey.length; i++) {
304:                    plainKey[i] = (byte) (encrKey[i] ^ xorKey[i]);
305:                }
306:
307:                /*
308:                 * Check the integrity of the recovered key by concatenating it with
309:                 * the password, digesting the concatenation, and comparing the
310:                 * result of the digest operation with the digest provided at the end
311:                 * of <code>protectedKey</code>. If the two digest values are
312:                 * different, throw an exception.
313:                 */
314:                md.update(passwdBytes);
315:                Arrays.fill(passwdBytes, (byte) 0x00);
316:                passwdBytes = null;
317:                md.update(plainKey);
318:                digest = md.digest();
319:                md.reset();
320:                for (i = 0; i < digest.length; i++) {
321:                    if (digest[i] != protectedKey[SALT_LEN + encrKeyLen + i]) {
322:                        throw new UnrecoverableKeyException(
323:                                "Cannot recover key");
324:                    }
325:                }
326:
327:                // The parseKey() method of PKCS8Key parses the key
328:                // algorithm and instantiates the appropriate key factory,
329:                // which in turn parses the key material.
330:                try {
331:                    return PKCS8Key.parseKey(new DerValue(plainKey));
332:                } catch (IOException ioe) {
333:                    throw new UnrecoverableKeyException(ioe.getMessage());
334:                }
335:            }
336:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.