• Hello and welcome to our new forums. We upgraded our forum sites to a more robust and modern system which we hope you will enjoy. Be sure to check out your profile by clicking the button on the top right and configure your preferences, signature, time zone, avatar, etc. as you wish. If you need help with using this new forum'ware try the help link on the bottom right.

    Click here to review your account now.

IDEA crypt

cardmaker

New member
Joined
Jan 12, 2019
Messages
1
Programming Experience
Beginner
Using IDEA I need to encrypt a block (8 bytes). some example in net like https://github.com/LexBritvin/IdeaCipher are for entire files, I just need a block.

So far I have this code but the encrypt result is wrong:


Code:
byte[] data = new byte[8] { 0x50,0x5E,0xAF,0x43,0xA0,0xDF,0x32,0x29};
    string charKey = "3BD1955BEAA4428ADCC576F4DB752D00";

    bool encrypt = true;
    private static int blockSize = 8;

    private void button1_Click(object sender, EventArgs e)
    {
        Idea idea = new Idea(charKey, encrypt);
        BlockStreamCrypter bsc = new BlockStreamCrypter(idea, encrypt);
        bsc.crypt(data,0);
    }

    private class BlockStreamCrypter
    {
        Idea idea;
        bool encrypt;
        // data of the previous ciphertext block
        byte[] prev;
        byte[] newPrev;
        public BlockStreamCrypter(Idea idea, bool encrypt)
        {
            this.idea = idea;
            this.encrypt = encrypt;
            prev = new byte[blockSize];
            newPrev = new byte[blockSize];
        }
        public void crypt(byte[] data, int pos)
        {
            if (encrypt)
            {
                xor(data, pos, prev);
                idea.crypt(data, pos);
                Array.Copy(data, pos, prev, 0, blockSize);
            }

            else
            {
                Array.Copy(data, pos, newPrev, 0, blockSize);
                idea.crypt(data, pos);
                xor(data, pos, prev);
                byte[] temp = prev;
                prev = newPrev;
                newPrev = temp;
            }

            string fff = BitConverter.ToString(data);
            MessageBox.Show(fff);
        }
    }

    private static void xor(byte[] a, int pos, byte[] b)
    {
        for (int p = 0; p < blockSize; p++)
        {
            a[pos + p] ^= b[p];
        }
    }[/XCODE]

Also the namespace:
[XCODE]
namespace Idea_crypt
{
class Idea
{
    // Number of rounds.
    internal static int rounds = 8;
    // Internal encryption sub-keys.
    internal int[] subKey;

    public Idea(String charKey, bool encrypt)
    {
        byte[] key = generateUserKeyFromCharKey(charKey);
        // Expands a 16-byte user key to the internal encryption sub-keys.
        int[] tempSubKey = expandUserKey(key);
        if (encrypt)
        {
            subKey = tempSubKey;
        }
        else
        {
            subKey = invertSubKey(tempSubKey);
        }
    }

    /**
     * Encrypts or decrypts a block of 8 data bytes.
     *
     * @param data
     *    Buffer containing the 8 data bytes to be encrypted/decrypted.
     */
    public void crypt(byte[] data)
    {
    crypt(data, 0);
    }

    /**
     * Encrypts or decrypts a block of 8 data bytes.
     *
     * @param data
     *    Data buffer containing the bytes to be encrypted/decrypted.
     * @param dataPos
     *    Start position of the 8 bytes within the buffer.
     */
    public void crypt(byte[] data, int dataPos)
    {
        int x0 = ((data[dataPos + 0] & 0xFF) << 8) | (data[dataPos + 1] & 0xFF);
        int x1 = ((data[dataPos + 2] & 0xFF) << 8) | (data[dataPos + 3] & 0xFF);
        int x2 = ((data[dataPos + 4] & 0xFF) << 8) | (data[dataPos + 5] & 0xFF);
        int x3 = ((data[dataPos + 6] & 0xFF) << 8) | (data[dataPos + 7] & 0xFF);
        //
        int p = 0;
        for (int round = 0; round < rounds; round++)
        {
            int y0 = mul(x0, subKey[p++]);
            int y1 = add(x1, subKey[p++]);
            int y2 = add(x2, subKey[p++]);
            int y3 = mul(x3, subKey[p++]);
            //
            int t0 = mul(y0 ^ y2, subKey[p++]);
            int t1 = add(y1 ^ y3, t0);
            int t2 = mul(t1, subKey[p++]);
            int t3 = add(t0, t2);
            //

x0 = y0 ^ t2;
            x1 = y2 ^ t2;
            x2 = y1 ^ t3;
            x3 = y3 ^ t3;
        }
        //
        int r0 = mul(x0, subKey[p++]);
        int r1 = add(x2, subKey[p++]);
        int r2 = add(x1, subKey[p++]);
        int r3 = mul(x3, subKey[p++]);
        //
        data[dataPos + 0] = (byte)(r0 >> 8);
        data[dataPos + 1] = (byte)r0;
        data[dataPos + 2] = (byte)(r1 >> 8);
        data[dataPos + 3] = (byte)r1;
        data[dataPos + 4] = (byte)(r2 >> 8);
        data[dataPos + 5] = (byte)r2;
        data[dataPos + 6] = (byte)(r3 >> 8);
        data[dataPos + 7] = (byte)r3;
    }

    // Expands a 16-byte user key to the internal encryption sub-keys.
    private static int[] expandUserKey(byte[] userKey)
    {
        if (userKey.Length != 16)
        {
            throw new ArgumentException("Key length must be 128 bit", "key");
        }
        int[] key = new int[rounds * 6 + 4];
        for (int i = 0; i < userKey.Length / 2; i++)
        {

  key[i] = ((userKey[2 * i] & 0xFF) << 8) | (userKey[2 * i + 1] & 0xFF);
        }
        for (int i = userKey.Length / 2; i < key.Length; i++)
        {
            key[i] = ((key[(i + 1) % 8 != 0 ? i - 7 : i - 15] << 9) | (key[(i + 2) % 8 < 2 ? i - 14 : i - 6] >> 7)) & 0xFFFF;
        }
        return key;
    }

    // Inverts decryption/encrytion sub-keys to encrytion/decryption sub-keys.
    private static int[] invertSubKey(int[] key)
    {
        int[] invKey = new int[key.Length];
        int p = 0;
        int i = rounds * 6;
        invKey[i + 0] = mulInv(key[p++]);
        invKey[i + 1] = addInv(key[p++]);
        invKey[i + 2] = addInv(key[p++]);
        invKey[i + 3] = mulInv(key[p++]);
        for (int r = rounds - 1; r >= 0; r--)
        {
            i = r * 6;
            int m = r > 0 ? 2 : 1;
            int n = r > 0 ? 1 : 2;
            invKey[i + 4] = key[p++];
            invKey[i + 5] = key[p++];
            invKey[i + 0] = mulInv(key[p++]);
            invKey[i + m] = addInv(key[p++]);
            invKey[i + n] = addInv(key[p++]);
            invKey[i + 3] = mulInv(key[p++]);
        }
        return invKey;

   }

    // Addition in the additive group.
    // The arguments and the result are within the range 0 .. 0xFFFF.
    private static int add(int a, int b)
    {
        return (a + b) & 0xFFFF;
    }

    // Multiplication in the multiplicative group.
    // The arguments and the result are within the range 0 .. 0xFFFF.
    private static int mul(int a, int b)
    {
        long r = (long)a * b;
        if (r != 0)
        {
            return (int)(r % 0x10001) & 0xFFFF;
        }
        else
        {
            return (1 - a - b) & 0xFFFF;
        }
    }

    // Additive Inverse.
    // The argument and the result are within the range 0 .. 0xFFFF.
    private static int addInv(int x)
    {
        return (0x10000 - x) & 0xFFFF;
    }

    // Multiplicative inverse.
    // The argument and the result are within the range 0 .. 0xFFFF.
    // The following condition is met for all values of x: mul(x, mulInv(x)) == 1
    private static int mulInv(int x)
    {
        if (x <= 1)
        {
            return x;
        }
        int y = 0x10001;
        int t0 = 1;
        int t1 = 0;
        while (true)
        {
            t1 += y / x * t0;
            y %= x;
            if (y == 1)
            {
                return 0x10001 - t1;
            }
            t0 += x / y * t1;
            x %= y;
            if (x == 1)
            {
                return t0;
            }
        }
    }
    // Generates a 16-byte binary user key from a character string key.
    private static byte[] generateUserKeyFromCharKey(String charKey)
    {
        int nofChar = 0x7E - 0x21 + 1;    // Number of different valid characters
        int[] a = new int[8];
        for (int p = 0; p < charKey.Length; p++)
        {
            int c = charKey[p];

            for (int i = a.Length - 1; i >= 0; i--)
            {
                c += a[i] * nofChar;
                a[i] = c & 0xFFFF;
                c >>= 16;
            }
        }
        byte[] key = new byte[16];
        for (int i = 0; i < 8; i++)
        {
            key[i * 2] = (byte)(a[i] >> 8);
            key[i * 2 + 1] = (byte)a[i];
        }
        return key;
    }
}
}
when encrypt above data the result must be B93A652F011657A1
anyone can help?
 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
2,202
Location
Sydney, Australia
Programming Experience
10+
Encryption is performed on byte arrays. If you have an example that encrypts a file then it must read some or all of that file into a byte array and then encrypt that. If you had a file containing just those eight bytes then it would be exactly the same thing. I can't speak for others but I'm not prepared to follow the link you provided try to find the examples, examine them, work out what they're doing and then compare that to the rather large block of code that you have posted. For me to take a closer look, you'd need to narrow it down a bit.
 
Top Bottom