2362N/A * Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved. 0N/A * Copyright (C) 1998 by the FundsXpress, INC. 0N/A * All rights reserved. 0N/A * Export of this software from the United States of America may require 0N/A * a specific license from the United States Government. It is the 0N/A * responsibility of any person or organization contemplating export to 0N/A * obtain such a license before exporting. 0N/A * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 0N/A * distribute this software and its documentation for any purpose and 0N/A * without fee is hereby granted, provided that the above copyright 0N/A * notice appear in all copies and that both that copyright notice and 0N/A * this permission notice appear in supporting documentation, and that 0N/A * the name of FundsXpress. not be used in advertising or publicity pertaining 0N/A * to distribution of the software without specific, written prior 0N/A * permission. FundsXpress makes no representations about the suitability of 0N/A * this software for any purpose. It is provided "as is" without express 0N/A * or implied warranty. 0N/A * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 0N/A * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 0N/A * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 0N/A * Implements Derive Key cryptography functionality as defined in RFC 3961. 0N/A * This is an abstract class. Concrete subclasses need to implement 0N/A * the abstract methods. 0N/A protected static final boolean debug =
false;
0N/A // These values correspond to the ASCII encoding for the string "kerberos" 0N/A {
0x6b,
0x65,
0x72,
0x62,
0x65,
0x72,
0x6f,
0x73};
0N/A * encryption function conf = random string of length c 0N/A * pad = shortest string to bring confounder 0N/A * and plaintext to a length that's a 0N/A * (C1, newIV) = E(Ke, conf | plaintext | pad, 0N/A * H1 = HMAC(Ki, conf | plaintext | pad) 0N/A * ciphertext = C1 | H1[1..h] 0N/A * newstate.ivec = newIV 0N/A * @param ivec initial vector to use when initializing the cipher; if null, 0N/A * then blocksize number of zeros are used, 0N/A * @param new_ivec if non-null, it is updated upon return to be the 0N/A * new ivec to use when calling encrypt next time 0N/A // Derive encryption key 0N/A // C1 = E(Ke, conf | plaintext | pad, oldivec) 0N/A "; plaintext = " +
len +
"; padding = " +
0N/A // Set padding bytes to zero 0N/A // Update ivec for next operation 0N/A // (last blockSize bytes of ciphertext) 0N/A // newstate.ivec = newIV 0N/A // Derive integrity key 0N/A // Generate checksum 0N/A // H1 = HMAC(Ki, conf | plaintext | pad) 0N/A * Performs encryption using given key only; does not add 0N/A * confounder, padding, or checksum. Incoming data to be encrypted 0N/A * assumed to have the correct blocksize. 0N/A "length of data to be encrypted (" +
len +
0N/A ") is not a multiple of the blocksize (" +
blockSize +
")");
0N/A * Decrypts data using specified key and initial vector. 0N/A * @param baseKey encryption key to use 0N/A * @param ciphertext encrypted data to be decrypted 0N/A * @param usage ignored 0N/A "length of data to be decrypted (" +
len +
0N/A ") is not a multiple of the blocksize (" +
blockSize +
")");
0N/A * @param baseKey key from which keys are to be derived using usage 0N/A * @param ciphertext E(Ke, conf | plaintext | padding, ivec) | H1[1..h] 0N/A // Derive encryption key 0N/A // Decrypt [confounder | plaintext | padding] (without checksum) 0N/A // decrypted = [confounder | plaintext | padding] 0N/A // Derive integrity key 0N/A // H1 = HMAC(Ki, conf | plaintext | pad) 0N/A // Prepare decrypted msg and ivec to be returned 0N/A // Last blockSize bytes of ciphertext without checksum 0N/A // Get rid of confounder 0N/A // [plaintext | padding] 0N/A // Round up to the next blocksize 0N/A // Generate checksum 0N/A // H1 = HMAC(Kc, input) 0N/A // DK(Key, Constant) = random-to-key(DR(Key, Constant)) 0N/A * DR(Key, Constant) = k-truncate(E(Key, Constant, 0N/A * initial-cipher-state)) 0N/A * Here DR is the random-octet generation function described below, and 0N/A * DK is the key-derivation function produced from it. In this 0N/A * construction, E(Key, Plaintext, CipherState) is a cipher, Constant is 0N/A * a well-known constant determined by the specific usage of this 0N/A * function, and k-truncate truncates its argument by taking the first k 0N/A * bits. Here, k is the key generation seed length needed for the 0N/A * encryption system. 0N/A * The output of the DR function is a string of bits; the actual key is 0N/A * produced by applying the cryptosystem's random-to-key operation on 0N/A * If the Constant is smaller than the cipher block size of E, then it 0N/A * must be expanded with n-fold() so it can be encrypted. If the output 0N/A * of E is shorter than k bits it is fed back into the encryption as 0N/A * many times as necessary. The construct is as follows (where | 0N/A * indicates concatentation): 0N/A * K1 = E(Key, n-fold(Constant), initial-cipher-state) 0N/A * K2 = E(Key, K1, initial-cipher-state) 0N/A * K3 = E(Key, K2, initial-cipher-state) 0N/A * DR(Key, Constant) = k-truncate(K1 | K2 | K3 | K4 ...) 0N/A /* loop encrypting the blocks until enough key bytes are generated */ 0N/A// --------------------------------- 0N/A // From MIT-1.3.1 distribution 0N/A * s = k-bits | k-bits rot 13 | k-bits rot 13*2 | ... | k-bits rot 13*(r-1) 0N/A * compute the 1's complement sum: 0N/A * n-fold = s[0..n-1]+s[n..2n-1]+s[2n..3n-1]+..+s[(k-1)*n..k*n-1] 0N/A * representation: msb first, assume n and k are multiples of 8, and 0N/A * that k>=16. this is the case of all the cryptosystems which are 0N/A * likely to be used. this function can be replaced if that 0N/A * assumption ever fails. 0N/A /* input length is in bits */ 0N/A /* first compute lcm(n,k) */ 0N/A /* now do the real work */ 0N/A // this will end up cycling through k lcm(k,n)/k times, which 0N/A for (i =
lcm-
1; i >=
0; i--) {
0N/A /* compute the msbit in k which gets added into this byte */ 0N/A msbit = (
/* first, start with msbit in the first, unrotated byte */ 0N/A /* then, for each byte, shift to right for each repetition */ 0N/A /* last, pick out correct byte within that shifted repetition */ 0N/A /* pull out the byte value itself */ 0N/A // Mask off values using &0xff to get only the lower byte 0N/A // Use >>> to avoid sign extension 0N/A System.err.println("((" + 0N/A ((in[((inbits-1)-(msbit>>>3))%inbits]&0xff)<<8) 0N/A + "|" + (in[((inbits)-(msbit>>>3))%inbits]&0xff) + ")" 0N/A + ">>>" + ((msbit&7)+1) + ")&0xff = " + bval); 0N/A /* do the addition */ 0N/A // Mask off values using &0xff to get only the lower byte 0N/A /* keep around the carry bit, if any */ 0N/A /* if there's a carry bit left over, add it back in */ 0N/A /* do the addition */ 0N/A /* keep around the carry bit, if any */ 0N/A // Routines used for debugging 0N/A // Get character representation of digest 0N/A// String.getBytes("UTF-8"); 0N/A// Do this instead of using String to avoid making password immutable