com.spring.boxes.dollar.support.cryptor.SkipJack Maven / Gradle / Ivy
package com.spring.boxes.dollar.support.cryptor;
import java.nio.ByteBuffer;
import org.apache.commons.codec.binary.Base64;
public class SkipJack {
private final static long LONG_BYTES = 8;
private final int[] secretKey;
private SkipJack(int[] secretStr) {
this.secretKey = secretStr;
}
public static SkipJack of(int[] secretStr) {
return new SkipJack(secretStr);
}
public static long encrypt(long message, int[] key) {
long state = message;
int stepcounter = 0;//k starts at 0
while (stepcounter < 8) { // 8 rounds of rule A.
state = roundA(stepcounter, key, state);
stepcounter++;
}
while (stepcounter < 16) { // 8 rounds of rule B.
state = roundB(stepcounter, key, state);
stepcounter++;
}
// do that same thing again. Thus 32 rounds.
while (stepcounter < 24) {
state = roundA(stepcounter, key, state);
stepcounter++;
}
while (stepcounter < 32) {
state = roundB(stepcounter, key, state);
stepcounter++;
}
return state;
}
public static long decrypt(long message, int[] key) {
long state = message;
int stepcounter = 31;//k starts at 31
while (stepcounter > 23) { // 8 rounds of rule B.
state = roundBPrime(stepcounter, key, state);
stepcounter--;
}
while (stepcounter > 15) { // 8 rounds of rule A.
state = roundAprime(stepcounter, key, state);
stepcounter--;
}
// do that same thing again. Thus 32 rounds.
while (stepcounter > 7) {
state = roundBPrime(stepcounter, key, state);
stepcounter--;
}
while (stepcounter > -1) {
state = roundAprime(stepcounter, key, state);
stepcounter--;
}
return state;
}
private static long roundA(int step, int[] key, long block) {
long w_1i, w_2i, w_3i, w_4i;
long w_1o, w_2o, w_3o, w_4o;
w_1i = block >>> 48;
w_2i = block >> 32 & 0xFFFFL;
w_3i = block >> 16 & 0xFFFFL;
w_4i = block & 0xFFFFL;
w_1o = G(step, key, w_1i) ^ w_4i ^ step + 1;
w_2o = G(step, key, w_1i);
w_3o = w_2i;
w_4o = w_3i;
return w_1o << 48 | w_2o << 32 | w_3o << 16 | w_4o;
}
private static long roundB(int step, int[] key, long block) {
long w_1i, w_2i, w_3i, w_4i;
long w_1o, w_2o, w_3o, w_4o;
w_1i = block >>> 48;
w_2i = block >> 32 & 0xFFFFL;
w_3i = block >> 16 & 0xFFFFL;
w_4i = block & 0xFFFFL;
w_1o = w_4i;
w_2o = G(step, key, w_1i);
w_3o = w_1i ^ w_2i ^ step + 1;
w_4o = w_3i;
return w_1o << 48 | w_2o << 32 | w_3o << 16 | w_4o;
}
private static long roundAprime(int step, int[] key, long block) {
long w_1i, w_2i, w_3i, w_4i;
long w_1o, w_2o, w_3o, w_4o;
w_1i = block >>> 48;
w_2i = block >> 32 & 0xFFFFL;
w_3i = block >> 16 & 0xFFFFL;
w_4i = block & 0xFFFFL;
w_1o = Gprime(step, key, w_2i);
w_2o = w_3i;
w_3o = w_4i;
w_4o = w_1i ^ w_2i ^ step + 1;
return w_1o << 48 | w_2o << 32 | w_3o << 16 | w_4o;
}
private static long roundBPrime(int step, int[] key, long block) {
long w_1i, w_2i, w_3i, w_4i;
long w_1o, w_2o, w_3o, w_4o;
w_1i = block >>> 48;
w_2i = block >> 32 & 0xFFFFL;
w_3i = block >> 16 & 0xFFFFL;
w_4i = block & 0xFFFFL;
w_1o = Gprime(step, key, w_2i);
w_2o = Gprime(step, key, w_2i) ^ w_3i ^ step + 1;
w_3o = w_4i;
w_4o = w_1i;
return w_1o << 48 | w_2o << 32 | w_3o << 16 | w_4o;
}
private static long G(int step, int[] key, long w) {
int g_1, g_2, g_3, g_4, g_5, g_6, cv0, cv1, cv2, cv3;
g_1 = (int) (w >>> 8);
g_2 = (int) (w & 0xFF);
cv0 = key[step * 4 % 10];
cv1 = key[(step * 4 + 1) % 10];
cv2 = key[(step * 4 + 2) % 10];
cv3 = key[(step * 4 + 3) % 10];
g_3 = SkipConstants.F[g_2 ^ cv0] ^ g_1;
g_4 = SkipConstants.F[g_3 ^ cv1] ^ g_2;
g_5 = SkipConstants.F[g_4 ^ cv2] ^ g_3;
g_6 = SkipConstants.F[g_5 ^ cv3] ^ g_4;
return (long) g_5 << 8 | g_6;
}
private static long Gprime(int step, int[] key, long w) {
int g_1, g_2, g_3, g_4, g_5, g_6, cv0, cv1, cv2, cv3;
g_1 = (int) (w & 0xFF);
g_2 = (int) (w >>> 8);
cv0 = key[(step * 4 + 3) % 10];
cv1 = key[(step * 4 + 2) % 10];
cv2 = key[(step * 4 + 1) % 10];
cv3 = key[step * 4 % 10];
g_3 = SkipConstants.F[g_2 ^ cv0] ^ g_1;
g_4 = SkipConstants.F[g_3 ^ cv1] ^ g_2;
g_5 = SkipConstants.F[g_4 ^ cv2] ^ g_3;
g_6 = SkipConstants.F[g_5 ^ cv3] ^ g_4;
return (long) g_6 << 8 | g_5;
}
public String encodeBase64URLSafeStringLong(long value) {
long encoded = encrypt(value, secretKey);
byte[] rawData = ByteBuffer.allocate(8).putLong(encoded).array();
return Base64.encodeBase64URLSafeString(rawData);
}
public long decodeBase64Long(String value) {
byte[] encrypted = Base64.decodeBase64(value);
if (encrypted == null || encrypted.length != LONG_BYTES) {
throw new RuntimeException("fail to decode: " + value);
}
long encoded = ByteBuffer.wrap(encrypted).getLong();
return decrypt(encoded, secretKey);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy