📄 loki91.java
字号:
for (int j = 0; j < 32; j++) s |= ((i >>> Po[j]) & 0x1) << (31 - j); P[i] = s; } } /** * Returns the result of exponentiation given the base and generator * of GF. * * @param b base of exponentiation, the exponent being always 31. * @param g irreducible polynomial generating Galois Field (GF). * @return the result of (b ** 31) mod g. */ private static final byte exp31 (int b, int g) { if (b == 0) return 0; int r = b; // r = b ** 1 b = mult(b, b, g); // b = b ** 2 r = mult(r, b, g); // r = b ** 3 b = mult(b, b, g); // b = b ** 4 r = mult(r, b, g); // r = b ** 7 b = mult(b, b, g); // b = b ** 8 r = mult(r, b, g); // r = b ** 15 b = mult(b, b, g); // b = b ** 16 return (byte)mult(r, b, g); // r = b ** 31 } /** * Returns the product of two binary numbers a and b, using the generator * g as the modulus: p = (a * b) mod g. g Generates a suitable Galois * Field in GF(2 ** 8). * * @param a operand for multiply. * @param b operand for multiply. * @param g irreducible polynomial generating Galois Field. * @return the result of (a * b) % g. */ private static final int mult (int a, int b, int g) { int p = 0; while (b != 0) { if ((b & 0x01) != 0) p ^= a; a <<= 1; if (a > 0xFF) a ^= g; b >>>= 1; } return p; }// Constructor, finalizer, and clone()//............................................................................ /** * Constructs a LOKI91 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 LOKI91 () { 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. */ protected 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. */ protected 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. */ protected 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 userKey to a working Loki key (sKey). * * @param key expected 64-bit user-key from which we'll * build a session key. */ private synchronized void makeKey (Key key) throws KeyException { byte[] userkey = key.getEncoded(); if (userkey == null) throw new KeyException("Null LOKI91 key"); // consider only 8 bytes if user data is longer than that if (userkey.length < 8) throw new KeyException("Invalid LOKI91 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."); } } } sKey[0] = (userkey[0] & 0xFF) << 24 | (userkey[1] & 0xFF) << 16 | (userkey[2] & 0xFF) << 8 | (userkey[3] & 0xFF); sKey[1] = sKey[0] << 12 | sKey[0] >>> 20; sKey[2] = (userkey[4] & 0xFF) << 24 | (userkey[5] & 0xFF) << 16 | (userkey[6] & 0xFF) << 8 | (userkey[7] & 0xFF); sKey[3] = sKey[2] << 12 | sKey[2] >>> 20; for (int i = 4; i < ROUNDS; i += 4) { sKey[i ] = sKey[i - 3] << 13 | sKey[i - 3] >>> 19; sKey[i + 1] = sKey[i ] << 12 | sKey[i ] >>> 20; sKey[i + 2] = sKey[i - 1] << 13 | sKey[i - 1] >>> 19; sKey[i + 3] = sKey[i + 2] << 12 | sKey[i + 2] >>> 20; } } /** * Main LOKI91 encryption routine. * * @param in the input plain text 64-bit vlock. * @param off the offset into <i>in</i> specifying where * data starts. * @param out will contain the cipher-text block. * @param outOff index in out where cipher-text starts. */ private void blockEncrypt (byte[] in, int off, byte[] out, int outOff) { int L = (in[off++] & 0xFF) << 24 | (in[off++] & 0xFF) << 16 | (in[off++] & 0xFF) << 8 | in[off++] & 0xFF; int R = (in[off++] & 0xFF) << 24 | (in[off++] & 0xFF) << 16 | (in[off++] & 0xFF) << 8 | in[off ] & 0xFF; int a; for (int i = 0; i < ROUNDS;) { // encrypt with the 16 subkeys a = R ^ sKey[i++]; L ^= P[S[ a & 0xFFF] & 0xFF] | P[S[(a >>> 8) & 0xFFF] & 0xFF] << 1 | P[S[(a >>> 16) & 0xFFF] & 0xFF] << 2 | P[S[(a >>> 24 | a << 8) & 0xFFF] & 0xFF] << 3; a = L ^ sKey[i++]; R ^= P[S[ a & 0xFFF] & 0xFF] | P[S[(a >>> 8) & 0xFFF] & 0xFF] << 1 | P[S[(a >>> 16) & 0xFFF] & 0xFF] << 2 | P[S[(a >>> 24 | a << 8) & 0xFFF] & 0xFF] << 3; } out[outOff++] = (byte)(R >>> 24); out[outOff++] = (byte)(R >>> 16); out[outOff++] = (byte)(R >>> 8); out[outOff++] = (byte) R; out[outOff++] = (byte)(L >>> 24); out[outOff++] = (byte)(L >>> 16); out[outOff++] = (byte)(L >>> 8); out[outOff ] = (byte) L; } /** * Main LOKI91 decryption routine. * * @param in the 64-bit cipher text buffer. * @param off the offset into <i>in</i> specifying where * data starts. * @param out will contain the plain-text block. * @param outOff index in out where plain-text starts. */ private void blockDecrypt (byte[] in, int off, byte[] out, int outOff) { int L = (in[off++] & 0xFF) << 24 | (in[off++] & 0xFF) << 16 | (in[off++] & 0xFF) << 8 | in[off++] & 0xFF; int R = (in[off++] & 0xFF) << 24 | (in[off++] & 0xFF) << 16 | (in[off++] & 0xFF) << 8 | in[off ] & 0xFF; int a; for (int i = ROUNDS; i > 0;) { // subkeys in reverse order a = R ^ sKey[--i]; L ^= P[S[ a & 0xFFF] & 0xFF] | P[S[(a >>> 8) & 0xFFF] & 0xFF] << 1 | P[S[(a >>> 16) & 0xFFF] & 0xFF] << 2 | P[S[(a >>> 24 | a << 8) & 0xFFF] & 0xFF] << 3; a = L ^ sKey[--i]; R ^= P[S[ a & 0xFFF] & 0xFF] | P[S[(a >>> 8) & 0xFFF] & 0xFF] << 1 | P[S[(a >>> 16) & 0xFFF] & 0xFF] << 2 | P[S[(a >>> 24 | a << 8) & 0xFFF] & 0xFF] << 3; } out[outOff++] = (byte)(R >>> 24); out[outOff++] = (byte)(R >>> 16); out[outOff++] = (byte)(R >>> 8); out[outOff++] = (byte) R; out[outOff++] = (byte)(L >>> 24); out[outOff++] = (byte)(L >>> 16); out[outOff++] = (byte)(L >>> 8); out[outOff ] = (byte) L; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -