📄 idea.java
字号:
package au.net.aba.crypto.provider;
/*
* $Id: IDEA.java,v 1.13 1999/02/17 01:40:13 leachbj Exp $
* $Author: leachbj $
*
* Copyright (C) 1996-1998 Australian Business Access Pty Ltd.
* All rights reserved.
*
* Use, modification, copying and distribution of this software is subject the
* terms and conditions of the ABA Public Licence. See the file
* "PUBLIC_LICENCE" for additional information.
*
* If you have not received a copy of the Public Licence, you must destroy all
* copies of this file immediately.
*
* $Source: /aba/CVSROOT/jdk1.1/src/au.net.aba/crypto/provider/IDEA.java,v $
* $Revision: 1.13 $
* $Date: 1999/02/17 01:40:13 $
* $State: Exp $
*/
import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.*;
import java.security.*;
import java.security.spec.*;
import au.net.aba.crypto.spec.*;
/**
* A class that provides IDEA public key encryption operations,
* such as encoding data and generating keys.
*/
public class IDEA extends BlockCipher
{
public final static String ident = "$Id: IDEA.java,v 1.13 1999/02/17 01:40:13 leachbj Exp $";
//====================================
// Useful constants
//====================================
protected static final int Rounds = 8;
protected static final int UserKeyLen = 8; // 8wrds =128bit
protected static final int KeyLen = (Rounds * 6) + 4;
protected static final int MulModulus = 0x10001;
protected static final int MulMask = 0xffff;
/**
* The data bytes that constitute the key.
*/
public int[] encr = null;
public int[] decr = null;
int AddInv(
int x )
{
return (-x) & MulMask;
}
//==================================
// Private Implementation
//==================================
int bytes2int(
byte[] b,
int off)
{
return ((b[off] << 8) & 0xff00) + (b[off+1] & 0xff);
}
/**
* 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.");
}
do_idea_1blk(decr, src, srcIndex, dst, dstIndex);
return BLOCK_SIZE;
}
void do_idea_1blk(
int[] key,
byte[] src,
int soff,
byte[] dst,
int doff)
{
int round = Rounds;
int koff = 0;
int x0, x1, x2, x3, t0, t1;
x0 = bytes2int(src, soff+0);
x1 = bytes2int(src, soff+2);
x2 = bytes2int(src, soff+4);
x3 = bytes2int(src, soff+6);
do
{
x0 = MulMod16(x0, key[koff++]);
x1 += key[koff++]; x1 &= MulMask;
x2 += key[koff++]; x2 &= MulMask;
x3 = MulMod16(x3, key[koff++]);
t0 = x2;
x2 = MulMod16(x0^x2, key[koff++]);
t1 = x1;
x1 = MulMod16((x1^x3)+x2, key[koff++]);
x2 += x1; x2 &= MulMask;
x0 ^= x1;
x3 ^= x2;
x1 ^= t0;
x2 ^= t1;
}
while (--round > 0);
x0 = MulMod16(x0, key[koff++]);
t0 = x1;
x1 = x2 + key[koff++]; x1 &= MulMask;
x2 = t0 + key[koff++]; x2 &= MulMask;
x3 = MulMod16(x3, key[koff++]);
dst[doff++] = (byte) ((x0 >>> 8) & 0xff);
dst[doff++] = (byte) (x0 & 0xff);
dst[doff++] = (byte) ((x1 >>> 8) & 0xff);
dst[doff++] = (byte) (x1 & 0xff);
dst[doff++] = (byte) ((x2 >>> 8) & 0xff);
dst[doff++] = (byte) (x2 & 0xff);
dst[doff++] = (byte) ((x3 >>> 8) & 0xff);
dst[doff++] = (byte) (x3 & 0xff);
}
/**
* 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.");
}
do_idea_1blk(encr, src, srcIndex, dst, dstIndex);
return BLOCK_SIZE;
}
int MulInv(
int x)
{
int t0, t1, q, y;
x &= MulMask;
if (x <= 1) // Since zero and one are self inverse
return x;
t1 = (int) (0x10001L / x); // Since x >= 2, the result is 16bit
y = (int) (0x10001L % x);
if (y == 1)
return (1 - t1) & MulMask;
t0 = 1;
do
{
q = (x / y);
x %= y;
t0 = (t0 + (q * t1)) & MulMask;
if (x == 1)
return t0;
q = y / x;
y = y % x;
t1 = (t1 + (q * t0)) & MulMask;
}
while (y != 1);
return (1 - t1) & MulMask;
}
int MulMod16(
int a,
int b)
{
int p;
a &= MulMask;
b &= MulMask;
if (a == 0)
{
a = MulModulus - b;
}
else if (b == 0)
{
a = MulModulus - a;
}
else
{
// a *= b;
// b = a >>> 16;
// if ((a & MulMask) >= b)
// a -= b;
// else
// a += MulModulus - b;
p = a * b;
b = p & MulMask;
a = p >>> 16;
a = b - a + (b < a ? 1 : 0);
}
return a & MulMask;
}
/**
* prepare key data necessary for decryption.
*/
void prepare_decr()
{
int lo, hi,
i;
int t;
decr = new int[KeyLen];
lo = 0;
hi = 6 * Rounds;
t = MulInv(encr[lo]);
decr[lo++] = MulInv(encr[hi]);
decr[hi++] = t;
t = AddInv(encr[lo]);
decr[lo++] = AddInv(encr[hi]);
decr[hi++] = t;
t = AddInv(encr[lo]);
decr[lo++] = AddInv(encr[hi]);
decr[hi++] = t;
t = MulInv(encr[lo]);
decr[lo++] = MulInv(encr[hi]);
decr[hi] = t;
for (i = (Rounds - 1) / 2; i != 0; i--)
{
t = encr[lo];
decr[lo++] = encr[hi -= 5];
decr[hi++] = t;
t = encr[lo];
decr[lo++] = encr[hi];
decr[hi] = t;
t = MulInv(encr[lo]);
decr[lo++] = MulInv(encr[hi -= 5]);
decr[hi++] = t;
t = AddInv(encr[lo]);
decr[lo++] = AddInv(encr[++hi]);
decr[hi--] = t;
t = AddInv(encr[lo]);
decr[lo++] = AddInv(encr[hi]);
decr[hi++] = t;
t = MulInv(encr[lo]);
decr[lo++] = MulInv(encr[++hi]);
decr[hi] = t;
}
if (Rounds % 2 == 0)
{
t = encr[lo];
decr[lo++] = encr[hi -= 5];
decr[hi++] = t;
t = encr[lo];
decr[lo++] = encr[hi];
decr[hi] = t;
decr[lo] = MulInv(encr[lo]);
lo++;
t = AddInv(encr[lo]);
decr[lo] = AddInv(encr[lo + 1]);
lo++;
decr[lo++] = t;
decr[lo] = MulInv(encr[lo]);
}
else
{
decr[lo] = encr[lo];
lo++;
decr[lo] = encr[lo];
}
}
/**
* prepare the key data necessary for encryption
*
* @param the user supplied data
*/
void prepare_encr(
short[] data)
{
int i;
encr = new int[KeyLen];
for (i = 0; i < UserKeyLen; i++)
{
encr[i] = data[i] & MulMask;
}
for (i = UserKeyLen; i < KeyLen; i++)
{
if ((i & 7) < 6) // encr[8-13], encr[16-21], ...
{
encr[i] = ((encr[i - 7] & 127) << 9
| encr[i - 6] >>> 7) & MulMask;
}
else if ((i & 7) == 6) // encr[14], encr[22], ...
{
encr[i] = (((encr[i - 7] & 127) << 9)
| (encr[i - 14] >>> 7)) & MulMask;
}
else // encr[15], encr[21], ...
{
encr[i] = ((encr[i - 15] & 127) << 9
| encr[i-14] >>> 7) & MulMask;
}
}
}
/**
* 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 IDEAKey)
|| (inKey instanceof SecretKeySpec)))
{
throw new InvalidKeyException("not an IDEA Key");
}
byte[] rawKey = inKey.getEncoded();
// Now make sure the key is long enough and convert it to
// short[] from byte[].
short[] data = new short[UserKeyLen];
byte[] bdata = new byte[UserKeyLen * 2];
for (int length = 0; length < (UserKeyLen * 2);
length += rawKey.length)
{
System.arraycopy(rawKey, 0,
bdata, length,
rawKey.length < (bdata.length-length)
? rawKey.length :
bdata.length - length);
}
for (int length = 0; length < UserKeyLen; length++)
{
data[length] = (short) (
((bdata[2*length] << 8) & 0xff00) +
(bdata[(2*length) + 1] & 0xff)
);
}
// Build the encryption - we always need this
prepare_encr(data);
// if necessary build the decryption schedule
if (mode == Cipher.DECRYPT_MODE)
{
prepare_decr();
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -