Schala_Zeal
Schala_Zeal

Reputation: 3

Is this a known Algorithm?

Basically I'm trying to recreate a program where I input an info (1 to 8 bytes) to get an output info (1 to 7 bytes), I know that's happening some bit-manipulation, but I can't find a definitive pattern to create the Algorithm.

Below some methods that I created for the bit-manipulation:

public byte ChangeMSB(byte input)
        {
            byte[] output = { 0x00 };
            var bits = new BitArray(new byte[] { input });
            bits.Set(bits.Length - 1, true);
            bits.CopyTo(output, 0);
            return output[0];
        }

public byte RightShiftBits(byte input, int count)
        {
            byte[] output = { 0x00 };
            var bits = new BitArray(new byte[] { input });
            bits.RightShift(count);
            bits.CopyTo(output, 0);
            return output[0];
        }

public byte LeftShiftBits(byte input, int count)
        {
            byte[] output = { 0x00 };
            var bits = new BitArray(new byte[] { input });
            bits.LeftShift(count);
            bits.CopyTo(output, 0);
            return output[0];
        }

public byte OrBits(byte firstByte, byte secondByte)
        {
            byte[] ORed = { 0x00 };
            var firstBits = new BitArray(new byte[] { firstByte });
            var secondBits = new BitArray(new byte[] { secondByte });
            var ORedBits = firstBits.Or(secondBits);
            ORedBits.CopyTo(ORed, 0);
            return ORed[0];
        }

Then I tried to create an algorithm, but it doesn't work on every situation:

public byte[] Try(byte[] input)
        {
            byte[] output;
            switch (input.Length)
            {
                case 1:
                    return input;
                case 8:
                    output = new byte[input.Length - 1];
                    break;
                default:
                    output = new byte[input.Length];
                    break;
            }
            Array.Copy(input, output, output.Length);
            for (int i = 0; i < output.Length; i++)
            {
                if (i != output.Length - 1)
                {
                    output[i] = ChangeMSB(output[i]);
                }
                output[i] = RightShiftBits(output[i], i);
                if (i + 1 != output.Length && !input[i].Equals(input[i + 1]))
                {
                    output[i] = ChangeMSB(output[i]);
                }
                if (i == 6 && input.Length == 8)
                {
                    output[i] = OrBits(output[i], LeftShiftBits(input[input.Length - 1], 1));
                    break;
                }
            }
            return output;
        }

public byte[] Try2(byte[] input)
        {
            byte[] output;
            switch (input.Length)
            {
                case 1:
                    return input;
                case 8:
                    output = new byte[input.Length - 1];
                    break;
                default:
                    output = new byte[input.Length];
                    break;
            }
            Array.Copy(input, output, output.Length);
            for (int i = 0; i < output.Length; i++)
            {
                int operation = 0;
                for (int j = i; j > 0; j--)
                {
                    if (i > 0)
                    {
                        operation = (int)output[i] / 2;
                        output[i] = (byte)operation;
                    }
                    
                    if (IsOdd(output[i]) && i != output.Length - 1)
                    {
                        output[i] = ChangeMSB(output[i]);
                    }
                }
                output[0] = ChangeMSB(output[0]);
                if (i == 6 && input.Length == 8)
                {
                    operation = (int)output[i] + input[input.Length - 1] * 2;
                    output[i] = (byte)operation;
                    break;
                }
            }
            return output;
        }

I only found 2 patterns:

k

output[6] = OrBits(RightShiftBits(input[6], 6), LeftShiftBits(input[7], 1)) or (int)input[6]/2^6 + (int)input[7]*2;

Below some tests with the original Program with hex values: Encoding: GSM 7-bit Default Alphabet

input = 41 (A) | output = 41;
input = 41 41 (AA) | output = C1 20;
input = 41 41 41 (AAA) | output = C1 60 10;
input = 41 42 43 44 45 46 47 (ABCDEFG) | output = 41 E1 90 58 34 1E 01;
input = 41 42 43 44 45 46 47 48 (ABCDEFGH) | output = 41 E1 90 58 34 1E 91;
input = 48 47 46 45 44 43 42 41 (HGFEDCBA) | output = C8 A3 B1 48 1C 0A 83;
input = 4D 43 4B (MCK) | output = CD E1 12;

These are my outputs using the same inputs:

output = 41;
output = C1 20;
output = C1 60 10;
output = C1 E1 B0 98 8C 86 01;
output = C1 E1 B0 98 8C 86 91;
output = C8 E3 B1 98 8C 86 83;
output = CD E1 12;

Upvotes: 0

Views: 72

Answers (1)

Mathias Rav
Mathias Rav

Reputation: 2973

Your input is a string of 7-bit values, and your output is what you obtain when you put the 7-bit values together and read off 8 bits at a time.

An easy way to obtain this encoding is by putting the 7-bit values into a single "long" variable (which holds up to 64 bits) using left shifts. Then you can read off 8 bits at a time using right shifts.

byte[] input = {0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47};
long x = 0;
for (int i = 0; i < input.Length; i += 1) x |= ((long)input[i]) << (7 * i);
byte[] output = new byte[(input.Length * 7 + 7) / 8];
for (int i = 0; i < output.Length; i += 1) output[i] = (byte)(x >> (8 * i));
for (int i = 0; i < output.Length; i += 1) Console.Write("{0:X} ", output[i]);

Prints: 41 E1 90 58 34 1E 1

Upvotes: 1

Related Questions