
com.scudata.common.DES Maven / Gradle / Ivy
package com.scudata.common;
/* This class implements the DES arithmetic.
* Notice: the shift operation to a byte value is hard to control, because Java
* treat the byte type as a signed integer. In order to avoid the problem, the
* process in the program is based on character type.
*/
public class DES {
private static final int DIR_ENCRYPT = 1;
private static final int DIR_DECRYPT = 2;
// S-function table
private static final char sFunctionTable[][] = {
// S-1
{
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
},
// S-2
{
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
},
// S-3
{
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
},
// S-4
{
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
},
// S-5
{
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
},
// S-6
{
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
},
// S-7
{
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
},
// S-8
{
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
}
};
private char[] codedKey = new char[8];
//Creates a DES object whose key is supplied by a string.
public byte[] pKey(byte[] key) {
int len = key.length;
if( len == 8 ) return key;
byte[] bb = new byte[8];
if( len<8 ) {
System.arraycopy(key, 0, bb, 0, len);
return bb;
} else {
for(int i=0; i>24);
buf[1] = (byte)(len>>16);
buf[2] = (byte)(len>>8);
buf[3] = (byte)len;
//System.out.println( (int)buf[0] + "," + (int)buf[1] + "," + (int)buf[2] + "," + (int)buf[3] );
System.arraycopy(s, 0, buf, 4, len);
return desProcess1(dir, buf, 4+l);
} else {
byte[] buf1 = desProcess1(dir, s, l);
//System.out.println( (int)buf1[0] + "," + (int)buf1[1] + "," + (int)buf1[2] + "," + (int)buf1[3] );
int len = ((buf1[0]&0xff)<<24) + ((buf1[1]&0xff)<<16) + ((buf1[2]&0xff)<<8) + (buf1[3]&0xff);
//System.out.println( "len=" + len );
byte[] buf2 = new byte[len];
System.arraycopy(buf1, 4, buf2, 0, len);
return buf2;
}
}
private byte[] desProcess1(int dir, byte[] source, int l)
throws Exception
{
//Convert the byte array to a character array.
char[] srcBuffer = convertByteToChar(source, l);
//Encrypt or decrypt the character array.
char[] destBuffer = desProcess(dir, srcBuffer, l);
//Convert the result character array to a byte array.
byte[] dest = convertCharToByte(destBuffer, destBuffer.length);
return dest;
}
//Encrypts or decrypts the specified part of a character array.
private char[] desProcess(int dir, char[] s, int l) throws Exception
{
//Compute the length of the result.
int rl = (s.length / 8) * 8 + (s.length % 8 == 0 ? 0 : 8);
//Allocate memory for the result.
char[] dest = new char[rl];
// Allocate a 8 bytes buffer for internal processing, because
// DES arithmetic process data 8 bytes by 8 bytes.
char[] buffer = new char[8];
int offset = 0;
while(l > 0) {
//Copy the source data to the buffer. If the length of
// source data is less then 8 bytes, fill the buffer with 0.
System.arraycopy(s, offset, buffer, 0, l > 8 ? 8 : l);
for (int i = l; i < 8; i++) {
buffer[i] = 0x0;
}
//Encrypt or decrypt this 8 characters.
desProcess8chars(dir, buffer);
System.arraycopy(buffer, 0, dest, offset, 8);
offset += 8;
l -= 8;
}
return dest;
}
//Encrypts or decrypts 8 characters supplied by a character array.
private void desProcess8chars(int dir, char[] s) throws Exception
{
char[] keyCopy = new char[8];
int[] encryptLoop = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};
int[] decryptLoop = {1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 1};
int[] loop;
char[] k = new char[6];
char c;
if (dir == DIR_ENCRYPT) {
loop = encryptLoop;
} else {
loop = decryptLoop;
}
doFirstChange(s);
System.arraycopy(codedKey, 0, keyCopy, 0, 8);
for (int i = 0; i < 16; ++i) {
setKey(dir, keyCopy, loop[i], k);
doMut(s, k);
}
for(int i = 0; i < 4; ++i) {
c = s[i + 4];
s[i + 4] = s[i];
s[i] = c;
}
doLastChange(s);
}
//Processes the original key supplied by a byte array to its final format.
private void doKey(byte[] key) throws Exception {
char[] charBuffer = convertByteToChar(key, key.length);
doKey(charBuffer);
}
//Processes the original key supplied by a character array to its final format.
private void doKey(char[] key) throws Exception {
if (key.length != 8) {
throw new Exception("Invalid key length:" + key.length);
}
for (int i = 0; i < 8; i++) {
if (key[i] > 255) {
throw new Exception("Invalid character found in the des key");
}
}
char[] t = new char[8];
for (int i = 0; i < 8; ++i) {
t[i] = 0;
}
for (int i = 0; i < 8; ++i) {
for (int j = 0; j < 8; ++j) {
t[7-j] |= (((key[i] & (0x01 << j)) >> j) << i) & 0xff;
}
}
for (int i = 0; i < 4; i++) {
codedKey[i] = t[i];
codedKey[i + 4] = t[6-i];
}
codedKey[3] &= 0xf0;
codedKey[7] = (char)(((codedKey[7] & 0x0f) << 4) & 0xff);
}
private void doFirstChange(char[] s) {
char[] t = new char[8];
for (int i = 0; i < 8; ++i) {
t[i] = 0;
}
for (int i = 0; i < 8; ++i) {
for (int j = 0; j < 8; ++j) {
t[7-j] |= (((s[i] >> j) & 0x01 ) << i) & 0xff;
}
}
for (int i = 0; i < 4; ++i) {
s[i] = t[2 * i + 1];
s[i + 4] = t[2 * i];
}
}
private void doLastChange(char[] s) {
char[] t = new char[8];
for(int i = 0; i < 8; ++i) {
t[i] = 0;
}
for(int i = 0; i < 8; ++i) {
for(int j = 0; j < 4; ++j) {
t[i] |= ((s[j] << (7 - i)) & 0x80) >> (2 * j + 1);
t[i] |= ((s[j + 4] << (7 - i)) & 0x80) >> (2 * j);
}
}
/*for(int i = 0; i < 8; ++i) {
s[i] = t[i];
}*/
System.arraycopy(t, 0, s, 0, 8);
}
private void doLeft(char[] s, int n) {
doLeft(s, 0, n);
}
private void doLeft(char[] s, int offset, int n) {
char l, t;
l = (char)((0xff << (8 - n)) & 0xff);
t = (char)((s[offset] & l) >> 4);
s[offset + 3] |= t;
for(int i = offset; i < offset + 3; i++) {
s[i] <<= n;
s[i] &= 0xff;
t = (char)((s[i + 1] & l) >> (8 - n));
s[i] |= t;
}
s[offset + 3] <<= n;
s[offset + 3] &= 0xff;
}
private void doRight(char[] s, int n) {
doRight(s, 0, n);
}
private void doRight(char[] s, int offset, int n) {
for (int i = 0; i < n; ++i) {
char l0 = (char)(s[offset] & 1);
char l1 = (char)(s[offset + 1] & 1);
s[offset] >>= 1;
s[offset + 1] >>= 1;
s[offset + 1] |= (l0 << 7) & 0xff;
l0 = (char)(s[offset + 2] & 1);
s[offset + 2] >>= 1;
s[offset + 2] |= (l1 << 7) & 0xff;
s[offset + 3] >>= 1;
s[offset + 3] |= (l0 << 7) & 0xff;
if ((s[offset + 3] & 0xf) != 0) {
s[offset] |= 0x80;
s[offset + 3] &= 0xf0;
}
}
}
private void setKey(int dir, char[] key, int n, char[] k) {
for (int i = 0; i < 6; ++i) {
k[i] = 0;
}
if (dir == DIR_ENCRYPT) {
doLeft(key, n);
doLeft(key, 4, n);
}
k[0] = (char)( ((key[1] & 4) << 5)
| ((key[2] & 0x80) >> 1)
| (key[1] & 0X20)
| ((key[2] & 1) << 4)
| ((key[0] & 0X80) >> 4)
| ((key[0] & 8) >> 1)
| ((key[0] & 0x20) >> 4)
| ((key[3] & 0X10) >> 4) );
k[1] = (char)( ((key[1] & 2) << 6)
| ((key[0] & 4) << 4)
| ((key[2] & 8) << 2)
| ((key[1] & 0x40) >> 2)
| ((key[2] & 2) << 2)
| ((key[2] & 0x20) >> 3)
| ((key[1] & 0x10) >> 3)
| ((key[0] & 0X10) >> 4) );
k[2] = (char)( ((key[3] & 0x40) << 1)
| ((key[0] & 0x01) << 6)
| ((key[1] & 0x01) << 5)
| ((key[0] & 2) << 3)
| ((key[3] & 0x20) >> 2)
| ((key[2] & 0x10) >> 2)
| ((key[1] & 0x08) >> 2)
| ((key[0] & 0x40) >> 6) );
k[3] = (char)( ((key[5] & 0x08) << 4)
| ((key[6] & 0X01) << 6)
| (key[4] & 0X20)
| ((key[5] & 0x80) >> 3)
| ((key[6] & 0x20) >> 2)
| ((key[7] & 0x20) >> 3)
| ((key[4] & 0x40) >> 5)
| ((key[5] & 0x10) >> 4) );
k[4] = (char)( ((key[6] & 0x02) << 6)
| ((key[6] & 0x80) >> 1)
| ((key[4] & 0x08) << 2)
| (key[6] & 0x10)
| ((key[5] & 0X01) << 3 )
| ((key[6] & 0x08) >> 1)
| ((key[5] & 0x20) >> 4)
| ((key[7] & 0x10) >> 4) );
k[5] = (char)( ((key[4] & 0x04) << 5)
| ((key[7] & 0X80) >> 1)
| ((key[6] & 0x40)) >> 1
| ((key[5] & 0x04) << 2)
| ((key[6] & 0x04) << 1)
| ((key[4] & 0x01) << 2)
| ((key[4] & 0x80) >> 6)
| ((key[4] & 0x10) >> 4) );
if (dir == DIR_DECRYPT) {
doRight(key, n);
doRight(key, 4, n);
}
}
private void eExpand(char[] s, char[] r) {
r[0] = (char)( ((s[4 + 3] & 0x01) << 7)
| ((s[4 + 0] & 0xf8) >> 1)
| ((s[4 + 0] & 0x18) >> 3) );
r[1] = (char)( ((s[4 + 0] & 0x07) << 5)
| ((s[4 + 0] & 0x01) << 3)
| ((s[4 + 1] & 0x80) >> 3)
| ((s[4 + 1] & 0xe0) >> 5) );
r[2] = (char)( ((s[4 + 1] & 0x18) << 3)
| ((s[4 + 1] & 0x1f) << 1)
| ((s[4 + 2] & 0x80) >> 7) );
r[3] = (char)( ((s[4 + 1] & 0x01) << 7)
| ((s[4 + 2] & 0xf8) >> 1)
| ((s[4 + 2] & 0x18) >> 3) );
r[4] = (char)( ((s[4 + 2] & 0x07) << 5)
| ((s[4 + 2] & 0x01) << 3)
| ((s[4 + 3] & 0x80) >> 3)
| ((s[4 + 3] & 0xe0) >> 5) );
r[5] = (char)( ((s[4 + 3] & 0x18) << 3)
| ((s[4 + 3] & 0x1f) << 1)
| ((s[4 + 0] & 0x80) >> 7) );
}
private void pChange(char[] s) throws Exception
{
char[] t = null;
if (s == null || s.length < 4) {
throw new Exception("Invalid parameter");
}
t = new char[4];
t[0] = (char)( ((s[1] & 0x01) << 7)
| ((s[0] & 0x02) << 5)
| ((s[2] & 0x10) << 1)
| ((s[2] & 0x08) << 1)
| (s[3] & 0x08)
| ((s[1] & 0x10) >> 2)
| ((s[3] & 0x10) >> 3)
| ((s[2] & 0x80) >> 7) );
t[1] = (char)( (s[0] & 0x80)
| ((s[1] & 0x02) << 5)
| ((s[2] & 0x02) << 4)
| ((s[3] & 0x40) >> 2)
| (s[0] & 0x08)
| ((s[2] & 0x40) >> 4)
| (s[3] & 0x02)
| ((s[1] & 0x40) >> 6) );
t[2] = (char)( ((s[0] & 0x40) << 1)
| ((s[0] & 0x01) << 6)
| ((s[2] & 0x01) << 5)
| ((s[1] & 0x04) << 2)
| ((s[3] & 0x01) << 3)
| ((s[3] & 0x20) >> 3)
| ((s[0] & 0x20) >> 4)
| ((s[1] & 0x80) >> 7) );
t[3] = (char)( ((s[2] & 0x20) << 2)
| ((s[1] & 0x08) << 3)
| ((s[3] & 0x04) << 3)
| ((s[0] & 0x04) << 2)
| ((s[2] & 0x04) << 1)
| ((s[1] & 0x20) >> 3)
| ((s[0] & 0x10) >> 3)
| ((s[3] & 0x80) >> 7) );
for(int i = 0 ; i < 4; ++i) {
s[i] = t[i];
}
}
private char findS(char[] s, int ns) {
return findS(s, 0, ns);
}
private char findS(char[] s, int offset, int ns) {
int col, num, index = 0;
if (ns == 1 || ns == 5) {
col = ((s[offset] & 0x80) >> 6 ) | ((s[offset] & 0x04) >> 2);
num = (s[offset] & 0x78) >> 3;
index = col * 16 + num;
}
if (ns == 2 || ns == 6) {
col = (s[offset] & 0x02) | ((s[offset + 1] & 0x10) >> 4);
num = ((s[offset] & 0x01) << 3) | ((s[offset + 1] & 0xe0) >> 5);
index = col * 16 + num;
}
if (ns == 3 || ns == 7) {
col = ((s[offset + 1] & 0x08) >> 2)
| ((s[offset + 2] & 0x40) >> 6);
num = ((s[offset + 1] & 0x07) << 1)
| ((s[offset + 2] & 0x80) >> 7);
index = col * 16 + num;
}
if (ns == 4 || ns == 8) {
col = ((s[offset + 2] & 0x20) >> 4) | (s[offset + 2] & 0x01);
num = ((s[offset + 2] & 0x1e) >> 1);
index = col * 16 + num;
}
return sFunctionTable[ns-1][index];
}
private void doSFunction(char[] s, char[] r) {
r[0] = (char)((findS(s, 1) << 4) | findS(s, 2));
r[1] = (char)((findS(s, 3) << 4) | findS(s, 4));
r[2] = (char)((findS(s, 3, 5) << 4) | findS(s, 3, 6));
r[3] = (char)((findS(s, 3, 7) << 4) | findS(s, 3, 8));
}
private void fFunction(char[] s, char[] k, char[] m) throws Exception
{
char[] t = new char[6];
eExpand(s, t);
for (int i = 0; i < 6; ++i) {
t[i] ^= k[i];
}
doSFunction(t, m);
pChange(m);
}
private void doMut(char[] s, char[] k) throws Exception
{
char[] t = new char[4];
fFunction(s, k, t);
for (int i = 0; i < 4; ++i) {
t[i] ^= s[i];
s[i] = s[i + 4];
s[i + 4] = t[i];
}
}
//Convert the byte array to a character array.
static char[] convertByteToChar(byte[] source, int srclen) {
if (source == null)
return null;
int len = source.length;
if (len > srclen)
len = srclen;
char[] destChar = new char[len];
for (int i = 0; i < len; i++) {
if (source[i] >= 0)
destChar[i] = (char)source[i];
else
destChar[i] = (char)(256 + source[i]);
}
return destChar;
}
//Convert the character array to a byte array.
byte[] convertCharToByte(char[] source, int srclen) {
if (source == null)
return null;
int len = source.length;
if (len > srclen)
len = srclen;
byte[] dest = new byte[len];
for (int i = 0; i < len; i++)
dest[i] = (byte)source[i];
return dest;
}
public static void main(String[] args) throws Exception
{
DES des = new DES("1234567890");
String s = "abcdefgh?й??????ž?";
//for( int i = 0; i < 10; i++ )
// s += s;
byte[] bs = s.getBytes("utf-8");
System.out.println( "byte[] len=" + bs.length );
bs = des.encrypt(bs);
for( int i = 0; i < bs.length; i ++ ) {
System.out.print(bs[i]);
System.out.print(' ');
}
System.out.println();
bs = des.decrypt(bs);
System.out.println( bs.length );
s = new String(bs, "utf-8");
System.out.println( s + "," + s.length() );
//System.out.println(new Date());
//for (int i=0; i<100000; i++) {
// bs = des.encrypt(bs, 400);//?????ȣ?8?ı???
// bs = des.decrypt(bs, 400);
//}
//System.out.println(new Date());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy