📄 blowfish.java
字号:
public Blowfish()
{
S = new int[4][256];
P = new int[18];
}
private final void BF_Decipher(int xl, int xr, int result[])
{
int Xl;
int Xr;
int temp;
int i;
Xl = xl;
Xr = xr;
for (i = Rounds+1 ; i > 1 ; --i)
{
Xl = Xl ^ P[i];
Xr = F(Xl) ^ Xr;
temp = Xl;
Xl = Xr;
Xr = temp;
}
temp = Xl;
Xl = Xr;
Xr = temp;
Xr = Xr ^ P[1];
Xl = Xl ^ P[0];
result[0] = Xl;
result[1] = Xr;
}
private final void BF_Encipher(int xl, int xr, int result[])
{
int Xl;
int Xr;
int temp;
int i;
Xl = xl;
Xr = xr;
for (i = 0; i< Rounds; ++i)
{
Xl = Xl ^ P[i];
Xr = F(Xl) ^ Xr;
temp = Xl;
Xl = Xr;
Xr = temp;
}
temp = Xl;
Xl = Xr;
Xr = temp;
Xr = Xr ^ P[Rounds];
Xl = Xl ^ P[Rounds+1];
result[0] = Xl;
result[1] = Xr;
return;
}
private final void Bits32ToBytes(int in, byte[] b)
{
for (int i=3; i >= 0; i--)
{
b[i] = (byte)(in & 0xff);
in >>= 8;
}
return;
}
private final int BytesTo32bits(byte[] b, int i)
{
int rv = 0;
for (int k=0;k<4;++k)
{
rv <<= 8;
rv |= (b[i+k] & 0xff);
}
return rv;
}
/**
* Decrypt the given input starting at the given offset and place
* the result in the provided buffer starting at the given offset.
* The input will be an exact multiple of our blocksize.
*/
protected int decryptBlock(
byte[] src,
int srcIndex,
int len,
byte[] dst,
int dstIndex)
throws BadPaddingException
{
if (len != BLOCK_SIZE)
{
throw new BadPaddingException("Datasize less than block size.");
}
int result[] = new int[2];
byte out[] = new byte[4];
int xl;
int xr;
// process the input blocks (the data will be a multiple
// of our blocksize)
// batch the units up into a 32 bit chunk and go for it
// the array is in bytes, the increment is 8x8 bits = 64
for (int i = 0; i < BLOCK_SIZE; i += 8)
{
xl = BytesTo32bits(src, srcIndex+i);
xr = BytesTo32bits(src, srcIndex+(i+4));
BF_Decipher(xl, xr, result);
// now stuff them into the destination block
Bits32ToBytes(result[0], out);
System.arraycopy(out, 0, dst, dstIndex+i, 4);
Bits32ToBytes(result[1], out);
System.arraycopy(out, 0, dst, dstIndex+(i+4), 4);
}
return BLOCK_SIZE;
}
/**
* Encrypt the given input starting at the given offset and place
* the result in the provided buffer starting at the given offset.
* The input will be an exact multiple of our blocksize.
*/
protected int encryptBlock(
byte[] src,
int srcIndex,
int len,
byte[] dst,
int dstIndex)
throws IllegalBlockSizeException
{
if (len != BLOCK_SIZE)
{
throw new IllegalBlockSizeException("Datasize less than block size.");
}
int result[] = new int[2];
byte out[] = new byte[4];
int xl;
int xr;
// process the input blocks (the data will be a multiple
// of our blocksize)
// batch the units up into a 32 bit chunk and go for it
// the array is in bytes, the increment is 8x8 bits = 64
for (int i = 0; i < len; i += BLOCK_SIZE)
{
xl = BytesTo32bits(src, srcIndex+i);
xr = BytesTo32bits(src, srcIndex+(i+4));
BF_Encipher(xl, xr, result);
// now stuff them into the destination block
Bits32ToBytes(result[0], out);
System.arraycopy(out, 0, dst, dstIndex+i, 4);
Bits32ToBytes(result[1], out);
System.arraycopy(out, 0, dst, dstIndex+(i+4), 4);
}
return BLOCK_SIZE;
}
//==================================
// Private Implementation
//==================================
private final int F(int x)
{
int a,b,c,d;
int y;
d = x & 0x00ff;
x >>= 8;
c = x & 0x00ff;
x >>= 8;
b = x & 0x00ff;
x >>= 8;
a = x & 0x00ff;
y = S[0][a] + S[1][b];
y = y ^ S[2][c];
y = y + S[3][d];
return y;
}
/**
* Re-key the cipher. If the provided Key is not compatible
* with this cipher the exception should throw an InvalidKeyException.
*
* @param inKey the key to be used.
* @exception InvalidKeyException if the key is of the wrong type.
*/
protected void setKey(Key inKey)
throws InvalidKeyException
{
if (!((inKey instanceof BlowfishKey)
|| (inKey instanceof SecretKeySpec)))
{
throw new InvalidKeyException("not a Blowfish Key");
}
byte[] key = inKey.getEncoded();
/*
* - commentary from _Applied Crypto_, Schneier, p338
* NOTE: In the literature the arrays are numbered from '1'
* the code numbers from '0'. Please be careful.
*
* (1)
* Initialise the S-boxes and the P-array, with a fixed string
* This string contains the hexadecimal digits of (pi)
*/
for (int i=0; i<256; i++)
{
S[0][i] = KS0[i];
S[1][i] = KS1[i];
S[2][i] = KS2[i];
S[3][i] = KS3[i];
}
for (int i=0; i < Rounds+2; i++)
{
P[i] = KP[i];
}
/*
* (2)
* Now, XOR P1 with the first 32 bits of the key, XOR P2 with the
* second 32-bits of the key, and so on for all bits of the key
* (up to P18). Repeatedly cycle through the key bits until the
* entire P-array has been XOR-ed with the key bits
*/
int keyLength = key.length;
int keyIndex = 0;
// declare them here so they don't get created repeatedly
int j;
int data;
for (int i=0;i< Rounds+2; i++)
{
// get the 32 bits of the key
data = 0x0000000;
for (j=0; j<4; j++)
{
// move the current data value up 8 bits, then
// OR the key material into the data, essentially
// appending the new key byte onto the data.
data = data << 8;
data |= (int) (key[keyIndex] & 0xff);
keyIndex++;
// wrap when we get to the end of the key
if (keyIndex >= keyLength)
{
keyIndex = 0;
}
}
// XOR the 32 bit chunk onto the P-array
P[i] = P[i] ^ data;
}
/*
* (3)
* Encrypt the all-zero string with the Blowfish algorithm, using
* the subkeys described in (1) and (2)
*/
int result[] = new int[2];
/*
* (4)
* Replace P1 and P2 with the output of step (3)
*
* (5)
* Encrypt the output of step(3) using the Blowfish algorithm,
* with the modified subkeys.
*
* (6)
* Replace P3 and P4 with the output of step (5)
*
* (7)
* Continue the process, replacing all elements of the P-array
* and then all four S-boxes in order, with the output of the
* continuously changing Blowfish algorithm
*/
int data_l = 0;
int data_r = 0;
for (int i=0; i< Rounds+2; i+=2)
{
BF_Encipher(data_l, data_r, result);
data_l = P[i] = result[0];
data_r = P[i+1] = result[1];
}
for (int i=0; i< 4; ++i)
{
for (int s=0; s<256; s+=2)
{
BF_Encipher(data_l, data_r, result);
data_l = S[i][s] = result[0];
data_r = S[i][s+1] = result[1];
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -