📄 safer.java
字号:
* @param ps The desired new variant identifier for this cipher. * @throw IllegalStateException If this cipher is not uninitialised. * @throw InvalidParameterException If the variant identifier is invalid. */ public void setVariant (String ps) { if (getState() != UNINITIALIZED) throw new IllegalStateException("Cipher not in UNINITIALIZED state"); if (ps.equalsIgnoreCase("SK128") || ps.equalsIgnoreCase("SK-128")) variant = SK128_VARIANT; else if (ps.equalsIgnoreCase("SK64") || ps.equalsIgnoreCase("SK-64")) variant = SK64_VARIANT; else if (ps.equalsIgnoreCase("K128") || ps.equalsIgnoreCase("K-128")) variant = K128_VARIANT; else if (ps.equalsIgnoreCase("K64") || ps.equalsIgnoreCase("K-64")) variant = K64_VARIANT; else throw new InvalidParameterException(); } /** * Gets the variant for this cipher ("SK-128", "SK-64", "K-128", or "K-64"). */ public String getVariant() { switch (variant) { case SK128_VARIANT: return "SK-128"; case SK64_VARIANT: return "SK-64"; case K128_VARIANT: return "K-128"; case K64_VARIANT: return "K-64"; default: throw new InternalError("variant = " + variant); } } /** * Encryption algorithm. * * @param in contains the plaintext block. * @param inOff start index within input where data should be considered. * @param out will contain the ciphertext block. * @param outOff index in out where ciphertext starts. */ private void blockEncrypt (byte[] in, int inOff, byte[] out, int outOff) { int k = 0, round = sKey[k++]; if (MAX_NOF_ROUNDS < round) round = MAX_NOF_ROUNDS; int t, a = in[inOff++], b = in[inOff++], c = in[inOff++], d = in[inOff++], e = in[inOff++], f = in[inOff++], g = in[inOff++], h = in[inOff++]; for (int i = 0; i < round; i++) { a ^= sKey[k++]; b += sKey[k++]; c += sKey[k++]; d ^= sKey[k++]; e ^= sKey[k++]; f += sKey[k++]; g += sKey[k++]; h ^= sKey[k++]; a = EXP[a & 0xFF] + sKey[k++]; b = LOG[b & 0xFF] ^ sKey[k++]; c = LOG[c & 0xFF] ^ sKey[k++]; d = EXP[d & 0xFF] + sKey[k++]; e = EXP[e & 0xFF] + sKey[k++]; f = LOG[f & 0xFF] ^ sKey[k++]; g = LOG[g & 0xFF] ^ sKey[k++]; h = EXP[h & 0xFF] + sKey[k++]; b += a; a += b; // PHT(a, b); d += c; c += d; // PHT(c, d); f += e; e += f; // PHT(e, f); h += g; g += h; // PHT(g, h); c += a; a += c; // PHT(a, c); g += e; e += g; // PHT(e, g); d += b; b += d; // PHT(b, d); h += f; f += h; // PHT(f, h); e += a; a += e; // PHT(a, e); f += b; b += f; // PHT(b, f); g += c; c += g; // PHT(c, g); h += d; d += h; // PHT(d, h); t = b; b = e; e = c; c = t; t = d; d = f; f = g; g = t; } out[outOff++] = (byte)(a ^ sKey[k++]); out[outOff++] = (byte)(b + sKey[k++]); out[outOff++] = (byte)(c + sKey[k++]); out[outOff++] = (byte)(d ^ sKey[k++]); out[outOff++] = (byte)(e ^ sKey[k++]); out[outOff++] = (byte)(f + sKey[k++]); out[outOff++] = (byte)(g + sKey[k++]); out[outOff++] = (byte)(h ^ sKey[k++]); } /** * Decryption algorithm. * * @param in contains the ciphertext block. * @param inOff index within input where cipher data should be considered * @param out will contain the plaintext block. * @param outOff index in out where plaintext starts. */ private void blockDecrypt (byte[] in, int inOff, byte[] out, int outOff) { int round = sKey[0]; if (MAX_NOF_ROUNDS < round) round = MAX_NOF_ROUNDS; int t, a = in[inOff++], b = in[inOff++], c = in[inOff++], d = in[inOff++], e = in[inOff++], f = in[inOff++], g = in[inOff++], h = in[inOff++]; int k = BLOCK_SIZE * (1 + 2 * round); h ^= sKey[k]; g -= sKey[--k]; f -= sKey[--k]; e ^= sKey[--k]; d ^= sKey[--k]; c -= sKey[--k]; b -= sKey[--k]; a ^= sKey[--k]; for (int i = 0; i < round; i++) { t = e; e = b; b = c; c = t; t = f; f = d; d = g; g = t; a -= e; e -= a; // IPHT(a, e); b -= f; f -= b; // IPHT(b, f); c -= g; g -= c; // IPHT(c, g); d -= h; h -= d; // IPHT(d, h); a -= c; c -= a; // IPHT(a, c); e -= g; g -= e; // IPHT(e, g); b -= d; d -= b; // IPHT(b, d); f -= h; h -= f; // IPHT(f, h); a -= b; b -= a; // IPHT(a, b); c -= d; d -= c; // IPHT(c, d); e -= f; f -= e; // IPHT(e, f); g -= h; h -= g; // IPHT(g, h); h -= sKey[--k]; g ^= sKey[--k]; f ^= sKey[--k]; e -= sKey[--k]; d -= sKey[--k]; c ^= sKey[--k]; b ^= sKey[--k]; a -= sKey[--k]; h = LOG[h & 0xFF] ^ sKey[--k]; g = EXP[g & 0xFF] - sKey[--k]; f = EXP[f & 0xFF] - sKey[--k]; e = LOG[e & 0xFF] ^ sKey[--k]; d = LOG[d & 0xFF] ^ sKey[--k]; c = EXP[c & 0xFF] - sKey[--k]; b = EXP[b & 0xFF] - sKey[--k]; a = LOG[a & 0xFF] ^ sKey[--k]; } out[outOff++] = (byte)a; out[outOff++] = (byte)b; out[outOff++] = (byte)c; out[outOff++] = (byte)d; out[outOff++] = (byte)e; out[outOff++] = (byte)f; out[outOff++] = (byte)g; out[outOff++] = (byte)h; } /** * Expands a userKey to a working SAFER key (sKey). * <p> * The key bytes are fist extracted from the user-key and formatted * into a 16-byte array (128 bits) which is then passed to the * Safer_Expand_Userkey() method. The length of the array is known * by the currently set variant of this object. If there isn't enough * bytes in the user key to make a valid SAFER user-key (64 or 128 * bits), the user-key is either trunctated or copied appropriately * to obtain enough bytes for the Safer_Expand_Userkey() method. An * exception is thrown only if the user-key is null; */ private synchronized void makeKey (Key key) throws KeyException { byte[] keyBytes = key.getEncoded(); if (keyBytes == null) throw new KeyException("Invalid SAFER key"); byte[] userKey = new byte[2 * BLOCK_SIZE]; int keyLen = keyBytes.length, len = 2 * BLOCK_SIZE, userKeyLenSoFar = 0; while (len >= keyLen) { System.arraycopy(keyBytes, 0, userKey, userKeyLenSoFar, keyLen); len -= keyLen; userKeyLenSoFar += keyLen; } System.arraycopy(keyBytes, 0, userKey, userKeyLenSoFar, len); byte[] key1 = new byte[BLOCK_SIZE], key2 = new byte[BLOCK_SIZE]; System.arraycopy(userKey, 0, key1, 0, BLOCK_SIZE); System.arraycopy(userKey, BLOCK_SIZE, key2, 0, BLOCK_SIZE); Safer_Expand_Userkey(key1, key2); } /** * Expands a user-selected key of length 64 bits or 128 bits to the * encryption / decryption sKey. * * Note: SAFER K-64 and SAFER SK-64 with a user-selected key 'z' of * length 64 bits are identical to SAFER K-128 and SAFER SK-128 with * a user-selected key 'z z' of length 128 bits, respectively. * * @param userkey_1 contains the first 64 bits of user key. * @param userkey_2 contains the second 64 bits of user key. */ private void Safer_Expand_Userkey (byte[] userkey_1, byte[] userkey_2) { // 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_1, userkey_2, rounds, isStrong())); return; } catch (Error error) { native_finalize(); native_lock = null;if (DEBUG && debuglevel > 0) debug(error + ". Will use 100% Java."); } } } byte[] ka = new byte[BLOCK_SIZE + 1], kb = new byte[BLOCK_SIZE + 1]; int k = 0; sKey[k++] = (byte)rounds; for (int j = 0; j < BLOCK_SIZE; j++) { ka[j] = (byte)(userkey_1[j] << 5 |(userkey_1[j] & 0xFF) >>> 3); ka[BLOCK_SIZE] ^= ka[j]; sKey[k++] = userkey_2[j]; kb[j] = userkey_2[j]; kb[BLOCK_SIZE] ^= kb[j]; } for (int i = 1; i <= rounds; i++) { for (int j = 0; j < BLOCK_SIZE + 1; j++) { ka[j] = (byte)(ka[j] << 6 |(ka[j] & 0xFF) >>> 2); kb[j] = (byte)(kb[j] << 6 |(kb[j] & 0xFF) >>> 2); } for (int j = 0; j < BLOCK_SIZE; j++) if (isStrong()) sKey[k++] = (ka[(j + 2 * i - 1) % (BLOCK_SIZE + 1)] + EXP[EXP[18 * i + j + 1]]) & 0xFF; else sKey[k++] = (ka[j] + EXP[EXP[18 * i + j + 1]]) & 0xFF; for (int j = 0; j < BLOCK_SIZE; j++) if (isStrong()) sKey[k++] = (kb[(j + 2 * i) % (BLOCK_SIZE + 1)] + EXP[EXP[18 * i + j + 10]]) & 0xFF; else sKey[k++] = (kb[j] + EXP[EXP[18 * i + j + 10]]) & 0xFF; } } /** Returns true if this cipher should use a strengthened key schedule. */ private boolean isStrong () { return (variant < K128_VARIANT); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -