Source Code Cross Referenced for DkCrypto.java in  » 6.0-JDK-Modules-sun » security » sun » security » krb5 » internal » crypto » dk » 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 sun » security » sun.security.krb5.internal.crypto.dk 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Portions Copyright 2004-2007 Sun Microsystems, Inc.  All Rights Reserved.
003:         */
004:
005:        /*
006:         * Copyright (C) 1998 by the FundsXpress, INC.
007:         *
008:         * All rights reserved.
009:         *
010:         * Export of this software from the United States of America may require
011:         * a specific license from the United States Government.  It is the
012:         * responsibility of any person or organization contemplating export to
013:         * obtain such a license before exporting.
014:         *
015:         * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
016:         * distribute this software and its documentation for any purpose and
017:         * without fee is hereby granted, provided that the above copyright
018:         * notice appear in all copies and that both that copyright notice and
019:         * this permission notice appear in supporting documentation, and that
020:         * the name of FundsXpress. not be used in advertising or publicity pertaining
021:         * to distribution of the software without specific, written prior
022:         * permission.  FundsXpress makes no representations about the suitability of
023:         * this software for any purpose.  It is provided "as is" without express
024:         * or implied warranty.
025:         *
026:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
027:         * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
028:         * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
029:         */
030:
031:        package sun.security.krb5.internal.crypto.dk;
032:
033:        import javax.crypto.Cipher;
034:        import javax.crypto.Mac;
035:        import java.security.GeneralSecurityException;
036:        import java.io.UnsupportedEncodingException;
037:        import java.util.Arrays;
038:        import java.io.ByteArrayInputStream;
039:        import java.io.ByteArrayOutputStream;
040:        import java.nio.charset.Charset;
041:        import java.nio.CharBuffer;
042:        import java.nio.ByteBuffer;
043:        import sun.misc.HexDumpEncoder;
044:        import sun.security.krb5.Confounder;
045:        import sun.security.krb5.internal.crypto.KeyUsage;
046:        import sun.security.krb5.KrbCryptoException;
047:
048:        /**
049:         * Implements Derive Key cryptography functionality as defined in RFC 3961.
050:         * http://www.ietf.org/rfc/rfc3961.txt
051:         *
052:         * This is an abstract class. Concrete subclasses need to implement
053:         * the abstract methods.
054:         */
055:
056:        public abstract class DkCrypto {
057:
058:            protected static final boolean debug = false;
059:
060:            // These values correspond to the ASCII encoding for the string "kerberos"
061:            static final byte[] KERBEROS_CONSTANT = { 0x6b, 0x65, 0x72, 0x62,
062:                    0x65, 0x72, 0x6f, 0x73 };
063:
064:            protected abstract int getKeySeedLength(); // in bits
065:
066:            protected abstract byte[] randomToKey(byte[] in);
067:
068:            protected abstract Cipher getCipher(byte[] key, byte[] ivec,
069:                    int mode) throws GeneralSecurityException;
070:
071:            public abstract int getChecksumLength(); // in bytes
072:
073:            protected abstract byte[] getHmac(byte[] key, byte[] plaintext)
074:                    throws GeneralSecurityException;
075:
076:            /**
077:             * From RFC 3961.
078:             *
079:             * encryption function       conf = random string of length c
080:             *                     pad = shortest string to bring confounder
081:             *                           and plaintext to a length that's a
082:             *                           multiple of m
083:             *                     (C1, newIV) = E(Ke, conf | plaintext | pad,
084:             *                                     oldstate.ivec)
085:             *                    H1 = HMAC(Ki, conf | plaintext | pad)
086:             *                     ciphertext =  C1 | H1[1..h]
087:             *                     newstate.ivec = newIV
088:             *
089:             * @param ivec initial vector to use when initializing the cipher; if null,
090:             *     then blocksize number of zeros are used, 
091:             * @param new_ivec if non-null, it is updated upon return to be the 
092:             *       new ivec to use when calling encrypt next time
093:             */
094:            public byte[] encrypt(byte[] baseKey, int usage, byte[] ivec,
095:                    byte[] new_ivec, byte[] plaintext, int start, int len)
096:                    throws GeneralSecurityException, KrbCryptoException {
097:
098:                if (!KeyUsage.isValid(usage)) {
099:                    throw new GeneralSecurityException(
100:                            "Invalid key usage number: " + usage);
101:                }
102:
103:                byte[] Ke = null;
104:                byte[] Ki = null;
105:
106:                try {
107:                    // Derive encryption key
108:
109:                    byte[] constant = new byte[5];
110:                    constant[0] = (byte) ((usage >> 24) & 0xff);
111:                    constant[1] = (byte) ((usage >> 16) & 0xff);
112:                    constant[2] = (byte) ((usage >> 8) & 0xff);
113:                    constant[3] = (byte) (usage & 0xff);
114:
115:                    constant[4] = (byte) 0xaa;
116:
117:                    Ke = dk(baseKey, constant);
118:                    if (debug) {
119:                        System.err.println("usage: " + usage);
120:                        if (ivec != null) {
121:                            traceOutput("old_state.ivec", ivec, 0, ivec.length);
122:                        }
123:                        traceOutput("plaintext", plaintext, start, Math.min(
124:                                len, 32));
125:                        traceOutput("constant", constant, 0, constant.length);
126:                        traceOutput("baseKey", baseKey, 0, baseKey.length);
127:                        traceOutput("Ke", Ke, 0, Ke.length);
128:                    }
129:
130:                    // Encrypt
131:                    // C1 = E(Ke, conf | plaintext | pad, oldivec)
132:                    Cipher encCipher = getCipher(Ke, ivec, Cipher.ENCRYPT_MODE);
133:                    int blockSize = encCipher.getBlockSize();
134:                    byte[] confounder = Confounder.bytes(blockSize);
135:
136:                    int plainSize = roundup(confounder.length + len, blockSize);
137:                    if (debug) {
138:                        System.err.println("confounder = " + confounder.length
139:                                + "; plaintext = " + len + "; padding = "
140:                                + (plainSize - confounder.length - len)
141:                                + "; total = " + plainSize);
142:                        traceOutput("confounder", confounder, 0,
143:                                confounder.length);
144:                    }
145:
146:                    byte[] toBeEncrypted = new byte[plainSize];
147:                    System.arraycopy(confounder, 0, toBeEncrypted, 0,
148:                            confounder.length);
149:                    System.arraycopy(plaintext, start, toBeEncrypted,
150:                            confounder.length, len);
151:
152:                    // Set padding bytes to zero
153:                    Arrays.fill(toBeEncrypted, confounder.length + len,
154:                            plainSize, (byte) 0);
155:
156:                    int cipherSize = encCipher.getOutputSize(plainSize);
157:                    int ccSize = cipherSize + getChecksumLength(); // cipher | hmac
158:
159:                    byte[] ciphertext = new byte[ccSize];
160:
161:                    encCipher.doFinal(toBeEncrypted, 0, plainSize, ciphertext,
162:                            0);
163:
164:                    // Update ivec for next operation 
165:                    // (last blockSize bytes of ciphertext)
166:                    // newstate.ivec = newIV
167:                    if (new_ivec != null && new_ivec.length == blockSize) {
168:                        System.arraycopy(ciphertext, cipherSize - blockSize,
169:                                new_ivec, 0, blockSize);
170:                        if (debug) {
171:                            traceOutput("new_ivec", new_ivec, 0,
172:                                    new_ivec.length);
173:                        }
174:                    }
175:
176:                    // Derive integrity key
177:                    constant[4] = (byte) 0x55;
178:                    Ki = dk(baseKey, constant);
179:                    if (debug) {
180:                        traceOutput("constant", constant, 0, constant.length);
181:                        traceOutput("Ki", Ki, 0, Ke.length);
182:                    }
183:
184:                    // Generate checksum
185:                    // H1 = HMAC(Ki, conf | plaintext | pad)
186:                    byte[] hmac = getHmac(Ki, toBeEncrypted);
187:
188:                    if (debug) {
189:                        traceOutput("hmac", hmac, 0, hmac.length);
190:                        traceOutput("ciphertext", ciphertext, 0, Math.min(
191:                                ciphertext.length, 32));
192:                    }
193:
194:                    // C1 | H1[1..h]
195:                    System.arraycopy(hmac, 0, ciphertext, cipherSize,
196:                            getChecksumLength());
197:                    return ciphertext;
198:                } finally {
199:                    if (Ke != null) {
200:                        Arrays.fill(Ke, 0, Ke.length, (byte) 0);
201:                    }
202:                    if (Ki != null) {
203:                        Arrays.fill(Ki, 0, Ki.length, (byte) 0);
204:                    }
205:                }
206:            }
207:
208:            /**
209:             * Performs encryption using given key only; does not add
210:             * confounder, padding, or checksum. Incoming data to be encrypted
211:             * assumed to have the correct blocksize.
212:             * Ignore key usage.
213:             */
214:            public byte[] encryptRaw(byte[] baseKey, int usage, byte[] ivec,
215:                    byte[] plaintext, int start, int len)
216:                    throws GeneralSecurityException, KrbCryptoException {
217:
218:                if (debug) {
219:                    System.err.println("usage: " + usage);
220:                    if (ivec != null) {
221:                        traceOutput("old_state.ivec", ivec, 0, ivec.length);
222:                    }
223:                    traceOutput("plaintext", plaintext, start, Math
224:                            .min(len, 32));
225:                    traceOutput("baseKey", baseKey, 0, baseKey.length);
226:                }
227:
228:                // Encrypt
229:                Cipher encCipher = getCipher(baseKey, ivec, Cipher.ENCRYPT_MODE);
230:                int blockSize = encCipher.getBlockSize();
231:
232:                if ((len % blockSize) != 0) {
233:                    throw new GeneralSecurityException(
234:                            "length of data to be encrypted (" + len
235:                                    + ") is not a multiple of the blocksize ("
236:                                    + blockSize + ")");
237:                }
238:
239:                int cipherSize = encCipher.getOutputSize(len);
240:                byte[] ciphertext = new byte[cipherSize];
241:
242:                encCipher.doFinal(plaintext, 0, len, ciphertext, 0);
243:                return ciphertext;
244:            }
245:
246:            /**
247:             * Decrypts data using specified key and initial vector. 
248:             * @param baseKey encryption key to use
249:             * @param ciphertext  encrypted data to be decrypted
250:             * @param usage ignored
251:             */
252:            public byte[] decryptRaw(byte[] baseKey, int usage, byte[] ivec,
253:                    byte[] ciphertext, int start, int len)
254:                    throws GeneralSecurityException {
255:
256:                if (debug) {
257:                    System.err.println("usage: " + usage);
258:                    if (ivec != null) {
259:                        traceOutput("old_state.ivec", ivec, 0, ivec.length);
260:                    }
261:                    traceOutput("ciphertext", ciphertext, start, Math.min(len,
262:                            32));
263:                    traceOutput("baseKey", baseKey, 0, baseKey.length);
264:                }
265:
266:                Cipher decCipher = getCipher(baseKey, ivec, Cipher.DECRYPT_MODE);
267:
268:                int blockSize = decCipher.getBlockSize();
269:
270:                if ((len % blockSize) != 0) {
271:                    throw new GeneralSecurityException(
272:                            "length of data to be decrypted (" + len
273:                                    + ") is not a multiple of the blocksize ("
274:                                    + blockSize + ")");
275:                }
276:
277:                byte[] decrypted = decCipher.doFinal(ciphertext, start, len);
278:
279:                if (debug) {
280:                    traceOutput("decrypted", decrypted, 0, Math.min(
281:                            decrypted.length, 32));
282:                }
283:
284:                return decrypted;
285:            }
286:
287:            /**
288:             * @param baseKey key from which keys are to be derived using usage
289:             * @param ciphertext  E(Ke, conf | plaintext | padding, ivec) | H1[1..h]
290:             */
291:            public byte[] decrypt(byte[] baseKey, int usage, byte[] ivec,
292:                    byte[] ciphertext, int start, int len)
293:                    throws GeneralSecurityException {
294:
295:                if (!KeyUsage.isValid(usage)) {
296:                    throw new GeneralSecurityException(
297:                            "Invalid key usage number: " + usage);
298:                }
299:
300:                byte[] Ke = null;
301:                byte[] Ki = null;
302:
303:                try {
304:                    // Derive encryption key
305:                    byte[] constant = new byte[5];
306:                    constant[0] = (byte) ((usage >> 24) & 0xff);
307:                    constant[1] = (byte) ((usage >> 16) & 0xff);
308:                    constant[2] = (byte) ((usage >> 8) & 0xff);
309:                    constant[3] = (byte) (usage & 0xff);
310:
311:                    constant[4] = (byte) 0xaa;
312:
313:                    Ke = dk(baseKey, constant); // Encryption key
314:
315:                    if (debug) {
316:                        System.err.println("usage: " + usage);
317:                        if (ivec != null) {
318:                            traceOutput("old_state.ivec", ivec, 0, ivec.length);
319:                        }
320:                        traceOutput("ciphertext", ciphertext, start, Math.min(
321:                                len, 32));
322:                        traceOutput("constant", constant, 0, constant.length);
323:                        traceOutput("baseKey", baseKey, 0, baseKey.length);
324:                        traceOutput("Ke", Ke, 0, Ke.length);
325:                    }
326:
327:                    Cipher decCipher = getCipher(Ke, ivec, Cipher.DECRYPT_MODE);
328:                    int blockSize = decCipher.getBlockSize();
329:
330:                    // Decrypt [confounder | plaintext | padding] (without checksum)
331:                    int cksumSize = getChecksumLength();
332:                    int cipherSize = len - cksumSize;
333:                    byte[] decrypted = decCipher.doFinal(ciphertext, start,
334:                            cipherSize);
335:
336:                    if (debug) {
337:                        traceOutput("decrypted", decrypted, 0, Math.min(
338:                                decrypted.length, 32));
339:                    }
340:
341:                    // decrypted = [confounder | plaintext | padding]
342:
343:                    // Derive integrity key
344:                    constant[4] = (byte) 0x55;
345:                    Ki = dk(baseKey, constant); // Integrity key
346:                    if (debug) {
347:                        traceOutput("constant", constant, 0, constant.length);
348:                        traceOutput("Ki", Ki, 0, Ke.length);
349:                    }
350:
351:                    // Verify checksum
352:                    // H1 = HMAC(Ki, conf | plaintext | pad)
353:                    byte[] calculatedHmac = getHmac(Ki, decrypted);
354:
355:                    if (debug) {
356:                        traceOutput("calculated Hmac", calculatedHmac, 0,
357:                                calculatedHmac.length);
358:                        traceOutput("message Hmac", ciphertext, cipherSize,
359:                                cksumSize);
360:                    }
361:
362:                    boolean cksumFailed = false;
363:                    if (calculatedHmac.length >= cksumSize) {
364:                        for (int i = 0; i < cksumSize; i++) {
365:                            if (calculatedHmac[i] != ciphertext[cipherSize + i]) {
366:                                cksumFailed = true;
367:                                break;
368:                            }
369:                        }
370:                    }
371:
372:                    if (cksumFailed) {
373:                        throw new GeneralSecurityException("Checksum failed");
374:                    }
375:
376:                    // Prepare decrypted msg and ivec to be returned
377:                    // Last blockSize bytes of ciphertext without checksum
378:                    if (ivec != null && ivec.length == blockSize) {
379:                        System.arraycopy(ciphertext, start + cipherSize
380:                                - blockSize, ivec, 0, blockSize);
381:                        if (debug) {
382:                            traceOutput("new_state.ivec", ivec, 0, ivec.length);
383:                        }
384:                    }
385:
386:                    // Get rid of confounder
387:                    // [plaintext | padding] 
388:                    byte[] plaintext = new byte[decrypted.length - blockSize];
389:                    System.arraycopy(decrypted, blockSize, plaintext, 0,
390:                            plaintext.length);
391:                    return plaintext; // padding still there
392:                } finally {
393:                    if (Ke != null) {
394:                        Arrays.fill(Ke, 0, Ke.length, (byte) 0);
395:                    }
396:                    if (Ki != null) {
397:                        Arrays.fill(Ki, 0, Ki.length, (byte) 0);
398:                    }
399:                }
400:            }
401:
402:            // Round up to the next blocksize
403:            int roundup(int n, int blocksize) {
404:                return (((n + blocksize - 1) / blocksize) * blocksize);
405:            }
406:
407:            public byte[] calculateChecksum(byte[] baseKey, int usage,
408:                    byte[] input, int start, int len)
409:                    throws GeneralSecurityException {
410:
411:                if (!KeyUsage.isValid(usage)) {
412:                    throw new GeneralSecurityException(
413:                            "Invalid key usage number: " + usage);
414:                }
415:
416:                // Derive keys
417:                byte[] constant = new byte[5];
418:                constant[0] = (byte) ((usage >> 24) & 0xff);
419:                constant[1] = (byte) ((usage >> 16) & 0xff);
420:                constant[2] = (byte) ((usage >> 8) & 0xff);
421:                constant[3] = (byte) (usage & 0xff);
422:
423:                constant[4] = (byte) 0x99;
424:
425:                byte[] Kc = dk(baseKey, constant); // Checksum key
426:                if (debug) {
427:                    System.err.println("usage: " + usage);
428:                    traceOutput("input", input, start, Math.min(len, 32));
429:                    traceOutput("constant", constant, 0, constant.length);
430:                    traceOutput("baseKey", baseKey, 0, baseKey.length);
431:                    traceOutput("Kc", Kc, 0, Kc.length);
432:                }
433:
434:                try {
435:                    // Generate checksum
436:                    // H1 = HMAC(Kc, input)
437:                    byte[] hmac = getHmac(Kc, input);
438:                    if (debug) {
439:                        traceOutput("hmac", hmac, 0, hmac.length);
440:                    }
441:                    if (hmac.length == getChecksumLength()) {
442:                        return hmac;
443:                    } else if (hmac.length > getChecksumLength()) {
444:                        byte[] buf = new byte[getChecksumLength()];
445:                        System.arraycopy(hmac, 0, buf, 0, buf.length);
446:                        return buf;
447:                    } else {
448:                        throw new GeneralSecurityException(
449:                                "checksum size too short: " + hmac.length
450:                                        + "; expecting : "
451:                                        + getChecksumLength());
452:                    }
453:                } finally {
454:                    Arrays.fill(Kc, 0, Kc.length, (byte) 0);
455:                }
456:            }
457:
458:            // DK(Key, Constant) = random-to-key(DR(Key, Constant))
459:            byte[] dk(byte[] key, byte[] constant)
460:                    throws GeneralSecurityException {
461:                return randomToKey(dr(key, constant));
462:            }
463:
464:            /*
465:             * From RFC 3961.
466:             *
467:             * DR(Key, Constant) = k-truncate(E(Key, Constant,
468:             *                                  initial-cipher-state))
469:             *
470:             * Here DR is the random-octet generation function described below, and
471:             * DK is the key-derivation function produced from it.  In this
472:             * construction, E(Key, Plaintext, CipherState) is a cipher, Constant is
473:             * a well-known constant determined by the specific usage of this
474:             * function, and k-truncate truncates its argument by taking the first k
475:             * bits.  Here, k is the key generation seed length needed for the
476:             * encryption system.
477:             *
478:             * The output of the DR function is a string of bits; the actual key is
479:             * produced by applying the cryptosystem's random-to-key operation on
480:             * this bitstring.
481:             *
482:             * If the Constant is smaller than the cipher block size of E, then it
483:             * must be expanded with n-fold() so it can be encrypted.  If the output
484:             * of E is shorter than k bits it is fed back into the encryption as
485:             * many times as necessary.  The construct is as follows (where |
486:             * indicates concatentation):
487:             *
488:             * K1 = E(Key, n-fold(Constant), initial-cipher-state)
489:             * K2 = E(Key, K1, initial-cipher-state)
490:             * K3 = E(Key, K2, initial-cipher-state)
491:             * K4 = ...
492:             *
493:             * DR(Key, Constant) = k-truncate(K1 | K2 | K3 | K4 ...)
494:             */
495:            private byte[] dr(byte[] key, byte[] constant)
496:                    throws GeneralSecurityException {
497:
498:                Cipher encCipher = getCipher(key, null, Cipher.ENCRYPT_MODE);
499:                int blocksize = encCipher.getBlockSize();
500:
501:                if (constant.length != blocksize) {
502:                    constant = nfold(constant, blocksize * 8);
503:                }
504:                byte[] toBeEncrypted = constant;
505:
506:                int keybytes = (getKeySeedLength() >> 3); // from bits to bytes
507:                byte[] rawkey = new byte[keybytes];
508:                int posn = 0;
509:
510:                /* loop encrypting the blocks until enough key bytes are generated */
511:                int n = 0, len;
512:                while (n < keybytes) {
513:                    if (debug) {
514:                        System.err.println("Encrypting: "
515:                                + bytesToString(toBeEncrypted));
516:                    }
517:
518:                    byte[] cipherBlock = encCipher.doFinal(toBeEncrypted);
519:                    if (debug) {
520:                        System.err.println("K: " + ++posn + " = "
521:                                + bytesToString(cipherBlock));
522:                    }
523:
524:                    len = (keybytes - n <= cipherBlock.length ? (keybytes - n)
525:                            : cipherBlock.length);
526:                    if (debug) {
527:                        System.err.println("copying " + len + " key bytes");
528:                    }
529:                    System.arraycopy(cipherBlock, 0, rawkey, n, len);
530:                    n += len;
531:                    toBeEncrypted = cipherBlock;
532:                }
533:                return rawkey;
534:            }
535:
536:            // ---------------------------------
537:
538:            // From MIT-1.3.1 distribution
539:            /*
540:             * n-fold(k-bits):
541:             *	 l = lcm(n,k)
542:             *	 r = l/k
543:             * s = k-bits | k-bits rot 13 | k-bits rot 13*2 | ... | k-bits rot 13*(r-1)
544:             * compute the 1's complement sum:
545:             * n-fold = s[0..n-1]+s[n..2n-1]+s[2n..3n-1]+..+s[(k-1)*n..k*n-1]
546:             */
547:
548:            /* 
549:             * representation: msb first, assume n and k are multiples of 8, and
550:             *  that k>=16.  this is the case of all the cryptosystems which are
551:             *  likely to be used.  this function can be replaced if that
552:             *  assumption ever fails.  
553:             */
554:
555:            /* input length is in bits */
556:            static byte[] nfold(byte[] in, int outbits) {
557:
558:                int inbits = in.length;
559:                outbits >>= 3; // count in bytes
560:
561:                /* first compute lcm(n,k) */
562:                int a, b, c, lcm;
563:                a = outbits; // n
564:                b = inbits; // k
565:
566:                while (b != 0) {
567:                    c = b;
568:                    b = a % b;
569:                    a = c;
570:                }
571:                lcm = outbits * inbits / a;
572:
573:                if (debug) {
574:                    System.err.println("k: " + inbits);
575:                    System.err.println("n: " + outbits);
576:                    System.err.println("lcm: " + lcm);
577:                }
578:
579:                /* now do the real work */
580:                byte[] out = new byte[outbits];
581:                Arrays.fill(out, (byte) 0);
582:
583:                int this byte = 0;
584:                int msbit, i, bval, oval;
585:
586:                // this will end up cycling through k lcm(k,n)/k times, which
587:                // is correct
588:                for (i = lcm - 1; i >= 0; i--) {
589:                    /* compute the msbit in k which gets added into this byte */
590:                    msbit = (/* first, start with msbit in the first, unrotated byte */
591:                    ((inbits << 3) - 1)
592:                    /* then, for each byte, shift to right for each repetition */
593:                    + (((inbits << 3) + 13) * (i / inbits))
594:                    /* last, pick out correct byte within that shifted repetition */
595:                    + ((inbits - (i % inbits)) << 3)) % (inbits << 3);
596:
597:                    /* pull out the byte value itself */
598:                    // Mask off values using &0xff to get only the lower byte
599:                    // Use >>> to avoid sign extension
600:                    bval = ((((in[((inbits - 1) - (msbit >>> 3)) % inbits] & 0xff) << 8) | (in[((inbits) - (msbit >>> 3))
601:                            % inbits] & 0xff)) >>> ((msbit & 7) + 1)) & 0xff;
602:
603:                    /*
604:                    System.err.println("((" +
605:                    ((in[((inbits-1)-(msbit>>>3))%inbits]&0xff)<<8)
606:                    + "|" + (in[((inbits)-(msbit>>>3))%inbits]&0xff) + ")"
607:                    + ">>>" + ((msbit&7)+1) + ")&0xff = " + bval);
608:                     */
609:
610:                    this byte += bval;
611:
612:                    /* do the addition */
613:                    // Mask off values using &0xff to get only the lower byte
614:                    oval = (out[i % outbits] & 0xff);
615:                    this byte += oval;
616:                    out[i % outbits] = (byte) (this byte & 0xff);
617:
618:                    if (debug) {
619:                        System.err.println("msbit[" + i + "] = " + msbit
620:                                + "\tbval=" + Integer.toHexString(bval)
621:                                + "\toval=" + Integer.toHexString(oval)
622:                                + "\tsum = " + Integer.toHexString(this byte));
623:                    }
624:
625:                    /* keep around the carry bit, if any */
626:                    this byte >>>= 8;
627:
628:                    if (debug) {
629:                        System.err.println("carry=" + this byte);
630:                    }
631:                }
632:
633:                /* if there's a carry bit left over, add it back in */
634:                if (this byte != 0) {
635:                    for (i = outbits - 1; i >= 0; i--) {
636:                        /* do the addition */
637:                        this byte += (out[i] & 0xff);
638:                        out[i] = (byte) (this byte & 0xff);
639:
640:                        /* keep around the carry bit, if any */
641:                        this byte >>>= 8;
642:                    }
643:                }
644:
645:                return out;
646:            }
647:
648:            // Routines used for debugging
649:            static String bytesToString(byte[] digest) {
650:                // Get character representation of digest
651:                StringBuffer digestString = new StringBuffer();
652:
653:                for (int i = 0; i < digest.length; i++) {
654:                    if ((digest[i] & 0x000000ff) < 0x10) {
655:                        digestString.append("0"
656:                                + Integer.toHexString(digest[i] & 0x000000ff));
657:                    } else {
658:                        digestString.append(Integer
659:                                .toHexString(digest[i] & 0x000000ff));
660:                    }
661:                }
662:                return digestString.toString();
663:            }
664:
665:            private static byte[] binaryStringToBytes(String str) {
666:                char[] usageStr = str.toCharArray();
667:                byte[] usage = new byte[usageStr.length / 2];
668:                for (int i = 0; i < usage.length; i++) {
669:                    byte a = Byte.parseByte(new String(usageStr, i * 2, 1), 16);
670:                    byte b = Byte.parseByte(new String(usageStr, i * 2 + 1, 1),
671:                            16);
672:                    usage[i] = (byte) ((a << 4) | b);
673:                }
674:                return usage;
675:            }
676:
677:            static void traceOutput(String traceTag, byte[] output, int offset,
678:                    int len) {
679:                try {
680:                    ByteArrayOutputStream out = new ByteArrayOutputStream(len);
681:                    new HexDumpEncoder().encodeBuffer(new ByteArrayInputStream(
682:                            output, offset, len), out);
683:
684:                    System.err.println(traceTag + ":" + out.toString());
685:                } catch (Exception e) {
686:                }
687:            }
688:
689:            // String.getBytes("UTF-8");
690:            // Do this instead of using String to avoid making password immutable
691:            static byte[] charToUtf8(char[] chars) {
692:                Charset utf8 = Charset.forName("UTF-8");
693:
694:                CharBuffer cb = CharBuffer.wrap(chars);
695:                ByteBuffer bb = utf8.encode(cb);
696:                int len = bb.limit();
697:                byte[] answer = new byte[len];
698:                bb.get(answer, 0, len);
699:                return answer;
700:            }
701:
702:            static byte[] charToUtf16(char[] chars) {
703:                Charset utf8 = Charset.forName("UTF-16LE");
704:
705:                CharBuffer cb = CharBuffer.wrap(chars);
706:                ByteBuffer bb = utf8.encode(cb);
707:                int len = bb.limit();
708:                byte[] answer = new byte[len];
709:                bb.get(answer, 0, len);
710:                return answer;
711:            }
712:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.