📄 des.java
字号:
/** * Table for PC2 permutations in key schedule computation. */ private static final int[] SKB = new int[8 * 64]; // blank final /** * The internal key schedule. */ private int[] sKey = new int[INTERNAL_KEY_LENGTH]; /** * Table for S-boxes and permutations, used in encrypt_base. */ private static final int SP_TRANS[] = new int[8 * 64]; // blank final// Static code//........................................................................... static { // // build the SKB table // // represent the bit number that each permutated bit is derived from // according to FIPS-46 String cd = "D]PKESYM`UBJ\\@RXA`I[T`HC`LZQ"+"\\PB]TL`[C`JQ@Y`HSXDUIZRAM`EK"; int j, s, bit; int count = 0; int offset = 0; for (int i = 0; i < cd.length(); i++) { s = cd.charAt(i) - '@'; if (s != 32) { bit = 1 << count++; for (j = 0; j < 64; j++) if ((bit & j) != 0) SKB[offset + j] |= 1 << s; if (count == 6) { offset += 64; count = 0; } } } // // build the SP_TRANS table // // I'd _really_ like to just say 'SP_TRANS = { ... }', but // that would be terribly inefficient (code size + time). // Instead we use a compressed representation --GK String spt = "g3H821:80:H03BA0@N1290BAA88::3112aIH8:8282@0@AH0:1W3A8P810@22;22"+ "A18^@9H9@129:<8@822`?:@0@8PH2H81A19:G1@03403A0B1;:0@1g192:@919AA"+ "0A109:W21492H@0051919811:215011139883942N8::3112A2:31981jM118::A"+ "101@I88:1aN0<@030128:X;811`920:;H0310D1033@W980:8A4@804A3803o1A2"+ "021B2:@1AH023GA:8:@81@@12092B:098042P@:0:A0HA9>1;289:@1804:40Ph="+ "1:H0I0HP0408024bC9P8@I808A;@0@0PnH0::8:19J@818:@iF0398:8A9H0<13@"+ "001@11<8;@82B01P0a2989B:0AY0912889bD0A1@B1A0A0AB033O91182440A9P8"+ "@I80n@1I03@1J828212A`A8:12B1@19A9@9@8^B:0@H00<82AB030bB840821Q:8"+ "310A302102::A1::20A1;8"; // OK, try to type _that_! // [526 chars, 3156 bits] // The theory is that each bit position in each int of SP_TRANS is // set in exactly 32 entries. We keep track of set bits. offset = 0; int k, c, param; for (int i = 0; i < 32; i++) { // each bit position k = -1; // pretend the -1th bit was set bit = 1 << i; for (j = 0; j < 32; j++) { // each set bit // Each character consists of two three-bit values: c = spt.charAt(offset >> 1) - '0' >> (offset & 1) * 3 & 7; offset++; if (c < 5) { // values 0...4 indicate a set bit 1...5 positions // from the previous set bit k += c + 1; SP_TRANS[k] |= bit; continue; } // other values take at least an additional parameter: // the next value in the sequence. param = spt.charAt(offset >> 1) - '0' >> (offset & 1) * 3 & 7; offset++; if (c == 5) { // indicates a bit set param+6 positions from // the previous set bit k += param + 6; SP_TRANS[k] |= bit; } else if (c == 6) { // indicates a bit set (param * 64) + 1 positions // from the previous set bit k += (param << 6) + 1; SP_TRANS[k] |= bit; } else { // indicates that we should skip (param * 64) positions, // then process the next value which will be in the range // 0...4. k += param << 6; j--; } } } }// Constructor, finalizer, and clone()//........................................................................... /** * Constructs a DES cipher object, in the UNINITIALIZED state. * This calls the Cipher constructor with <i>implBuffering</i> false, * <i>implPadding</i> false and the provider set to "Cryptix". */ public DES() { super(false, false, "Cryptix"); link(); } /** Cleans up resources used by this instance, if necessary. */ protected final void finalize() { if (native_lock != null) { synchronized(native_lock) { String error = native_finalize(); // may be called more than once if (error != null) debug(error + " in native_finalize"); } } } /** * Always throws a CloneNotSupportedException (cloning of ciphers is not * supported for security reasons). */ public final Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); }// Implementation of JCE methods//........................................................................... /** * <b>SPI</b>: Returns the length of an input block, in bytes. * * @return the length in bytes of an input block for this cipher. */ public int engineBlockSize() { return BLOCK_SIZE; } /** * <b>SPI</b>: Initializes this cipher for encryption, using the * specified key. * * @param key the key to use for encryption. * @exception InvalidKeyException if one of the following occurs: <ul> * <li> key.getEncoded() == null; * <li> The length of the user key array is not KEY_LENGTH. * </ul> */ public void engineInitEncrypt (Key key) throws InvalidKeyException { makeKey(key); } /** * <b>SPI</b>: Initializes this cipher for decryption, using the * specified key. * * @param key the key to use for decryption. * @exception InvalidKeyException if one of the following occurs: <ul> * <li> key.getEncoded() == null; * <li> The length of the user key array is not KEY_LENGTH. * </ul> */ public void engineInitDecrypt (Key key) throws InvalidKeyException, CryptixException { makeKey(key); } /** * <b>SPI</b>: This is the main engine method for updating data. * <p> * <i>in</i> and <i>out</i> may be the same array, and the input and output * regions may overlap. * * @param in the input data. * @param inOffset the offset into in specifying where the data starts. * @param inLen the length of the subarray. * @param out the output array. * @param outOffset the offset indicating where to start writing into * the out array. * @return the number of bytes written. * @exception CryptixException if the native library is being used, and it * reports an error. */ protected int engineUpdate(byte[] in, int inOffset, int inLen, byte[] out, int outOffset) { if (inLen < 0) throw new IllegalArgumentException("inLen < 0"); int blockCount = inLen / BLOCK_SIZE; inLen = blockCount * BLOCK_SIZE; boolean doEncrypt = (getState() == ENCRYPT); // Avoid overlapping input and output regions. if (in == out && (outOffset >= inOffset && outOffset < (long)inOffset+inLen || inOffset >= outOffset && inOffset < (long)outOffset+inLen)) { byte[] newin = new byte[inLen]; System.arraycopy(in, inOffset, newin, 0, inLen); in = newin; inOffset = 0; } if (native_lock != null) { synchronized(native_lock) { // If in == null || out == 0, evaluating their lengths will throw a // NullPointerException. if (inOffset < 0 || (long)inOffset + inLen > in.length || outOffset < 0 || (long)outOffset + inLen > out.length) throw new ArrayIndexOutOfBoundsException(getAlgorithm() + ": Arguments to native_crypt would cause a buffer overflow"); // In future, we may pass more than one block to native_crypt to reduce // native method overhead. for (int i = 0; i < blockCount; i++) { if (0 == native_crypt(native_cookie, in, inOffset, out, outOffset, doEncrypt)) throw new CryptixException(getAlgorithm() + ": Error in native code"); inOffset += BLOCK_SIZE; outOffset += BLOCK_SIZE; } } } else { for (int i = 0; i < blockCount; i++) { des(in, inOffset, out, outOffset, doEncrypt); inOffset += BLOCK_SIZE; outOffset += BLOCK_SIZE; } } return inLen; }// Own methods//........................................................................... /** * Expands a user-key to a working key schedule. * * @param key the user-key object to use. * @exception InvalidKeyException if one of the following occurs: <ul> * <li> key.getEncoded() == null; * <li> The length of the user key array is not KEY_LENGTH. * </ul> */ private void makeKey (Key key) throws InvalidKeyException { byte[] userkey = key.getEncoded(); if (userkey == null) throw new InvalidKeyException(getAlgorithm() + ": Null user key"); if (userkey.length != KEY_LENGTH) throw new InvalidKeyException(getAlgorithm() + ": Invalid user key length"); // If native library available then use it. If not or if // native method returned error then revert to 100% Java. if (native_lock != null) { synchronized(native_lock) { try { linkStatus.check(native_ks(native_cookie, userkey)); return; } catch (Error error) { native_finalize(); native_lock = null;if (DEBUG && debuglevel > 0) debug(error + ". Will use 100% Java."); } } } int i = 0; int c = (userkey[i++] & 0xFF) | (userkey[i++] & 0xFF) << 8 | (userkey[i++] & 0xFF) << 16 | (userkey[i++] & 0xFF) << 24; int d = (userkey[i++] & 0xFF) | (userkey[i++] & 0xFF) << 8 | (userkey[i++] & 0xFF) << 16 | (userkey[i++] & 0xFF) << 24; int t = ((d >>> 4) ^ c) & 0x0F0F0F0F; c ^= t; d ^= t << 4; t = ((c << 18) ^ c) & 0xCCCC0000; c ^= t ^ t >>> 18; t = ((d << 18) ^ d) & 0xCCCC0000; d ^= t ^ t >>> 18; t = ((d >>> 1) ^ c) & 0x55555555; c ^= t; d ^= t << 1; t = ((c >>> 8) ^ d) & 0x00FF00FF; d ^= t; c ^= t << 8; t = ((d >>> 1) ^ c) & 0x55555555; c ^= t; d ^= t << 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -