📄 rc2.java
字号:
* @see java.security.Cipher#UNINITIALIZED */ public RC2 () { 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 KeyException if the key is invalid. */ public void engineInitEncrypt (Key key) throws KeyException { makeKey(key); } /** * <b>SPI</b>: Initializes this cipher for decryption, using the * specified key. * * @param key the key to use for decryption. * @exception KeyException if the key is invalid. */ public void engineInitDecrypt (Key key) throws KeyException { 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 if (doEncrypt) { // state == ENCRYPT for (int i = 0; i < blockCount; i++) { blockEncrypt(in, inOffset, out, outOffset); inOffset += BLOCK_SIZE; outOffset += BLOCK_SIZE; } } else { // state == DECRYPT for (int i = 0; i < blockCount; i++) { blockDecrypt(in, inOffset, out, outOffset); inOffset += BLOCK_SIZE; outOffset += BLOCK_SIZE; } } return inLen; }// Own methods//............................................................................ /** * Expands a user key to a working RC2 key. * <p> * The secret key is first expanded to fill 128 bytes (64 words). * The expansion consists of taking the sum of the first and last * bytes in the user key, looking up the sum (modulo 256) in the S-box, * and appending the result to the key. The operation is repeated with * the second byte and new last byte of the key until all 128 bytes * have been generated. Note that the following pseudocode treats the S * array (the session key) as an array of 128 bytes rather than 64 words: * <pre> * for j = 0 to length-1 do * S[ j ] = K[ j ]; * for j = length to 127 do * S[ j ] = sBox[ ( S[ j-length ] + S[ j-1 ] ) mod 256 ]; * </pre> */ private void makeKey (Key key) throws KeyException { byte[] userkey = key.getEncoded(); if (userkey == null) throw new KeyException("Null RC2 user key"); int len = userkey.length; if (len > 128) throw new KeyException("Invalid RC2 user key size"); // 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."); } } } // first work with a 128 byte array int[] sk = new int[128]; for (int i = 0; i < len; i++) sk[i] = userkey[i] & 0xFF; for (int i = len; i < 128; i++) sk[i] = S_BOX[(sk[i - len] + sk[i - 1]) & 0xFF]; // The final phase of the key expansion involves replacing the // first byte of S with the entry selected from the S-box. In fact // this is a special case for tailoring the key to a given length. // sk[0] = S_BOX[sk[0]]; // hmm.... key reduction to 'bits' bits sk[128 - len] = S_BOX[sk[128 - len] & 0xFF]; for (int i = 127 - len; i >= 0; i--) sk[i] = S_BOX[sk[i + len] ^ sk[i + 1]]; // now convert this byte array to the short array session key schedule for (int i = 63; i >= 0; i--) sKey[i] = (sk[i * 2 + 1] << 8 | sk[i * 2]) & 0xFFFF; } /** * The cipher has 16 full rounds, each divided into 4 subrounds. * In addition the fifth and eleventh rounds add the contents of * the S-box indexed by one of the data words to another of the * data words following the four subrounds. */ private void blockEncrypt (byte[] in, int inOff, byte[] out, int outOff) { int w0 = (in[inOff++] & 0xFF) | (in[inOff++] & 0xFF) << 8; int w1 = (in[inOff++] & 0xFF) | (in[inOff++] & 0xFF) << 8; int w2 = (in[inOff++] & 0xFF) | (in[inOff++] & 0xFF) << 8; int w3 = (in[inOff++] & 0xFF) | (in[inOff ] & 0xFF) << 8; int j = 0; for (int i = 0; i < 16; i++) { w0 = (w0 + (w1 & ~w3) + (w2 & w3) + sKey[j++]) & 0xFFFF; w0 = w0 << 1 | w0 >>> 15; w1 = (w1 + (w2 & ~w0) + (w3 & w0) + sKey[j++]) & 0xFFFF; w1 = w1 << 2 | w1 >>> 14; w2 = (w2 + (w3 & ~w1) + (w0 & w1) + sKey[j++]) & 0xFFFF; w2 = w2 << 3 | w2 >>> 13; w3 = (w3 + (w0 & ~w2) + (w1 & w2) + sKey[j++]) & 0xFFFF; w3 = w3 << 5 | w3 >>> 11; if ((i == 4) || (i == 10)) { w0 += sKey[w3 & 0x3F]; w1 += sKey[w0 & 0x3F]; w2 += sKey[w1 & 0x3F]; w3 += sKey[w2 & 0x3F]; } } out[outOff++] = (byte) w0; out[outOff++] = (byte)(w0 >>> 8); out[outOff++] = (byte) w1; out[outOff++] = (byte)(w1 >>> 8); out[outOff++] = (byte) w2; out[outOff++] = (byte)(w2 >>> 8); out[outOff++] = (byte) w3; out[outOff ] = (byte)(w3 >>> 8); } /** * The decryption operation is simply the inverse of the * encryption operation. */ private void blockDecrypt (byte[] in, int inOff, byte[] out, int outOff) { int w0 = (in[inOff + 0] & 0xFF) | (in[inOff + 1] & 0xFF) << 8; int w1 = (in[inOff + 2] & 0xFF) | (in[inOff + 3] & 0xFF) << 8; int w2 = (in[inOff + 4] & 0xFF) | (in[inOff + 5] & 0xFF) << 8; int w3 = (in[inOff + 6] & 0xFF) | (in[inOff + 7] & 0xFF) << 8; int j = 63; for (int i = 15; i >= 0; i--) { w3 = (w3 >>> 5 | w3 << 11) & 0xFFFF; w3 = (w3 - (w0 & ~w2) - (w1 & w2) - sKey[j--]) & 0xFFFF; w2 = (w2 >>> 3 | w2 << 13) & 0xFFFF; w2 = (w2 - (w3 & ~w1) - (w0 & w1) - sKey[j--]) & 0xFFFF; w1 = (w1 >>> 2 | w1 << 14) & 0xFFFF; w1 = (w1 - (w2 & ~w0) - (w3 & w0) - sKey[j--]) & 0xFFFF; w0 = (w0 >>> 1 | w0 << 15) & 0xFFFF; w0 = (w0 - (w1 & ~w3) - (w2 & w3) - sKey[j--]) & 0xFFFF; if ((i == 11) || (i == 5)) { w3 = (w3 - sKey[w2 & 0x3F]) & 0xFFFF; w2 = (w2 - sKey[w1 & 0x3F]) & 0xFFFF; w1 = (w1 - sKey[w0 & 0x3F]) & 0xFFFF; w0 = (w0 - sKey[w3 & 0x3F]) & 0xFFFF; } } out[outOff++] = (byte) w0; out[outOff++] = (byte)(w0 >>> 8); out[outOff++] = (byte) w1; out[outOff++] = (byte)(w1 >>> 8); out[outOff++] = (byte) w2; out[outOff++] = (byte)(w2 >>> 8); out[outOff++] = (byte) w3; out[outOff ] = (byte)(w3 >>> 8); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -