十六进制字符串上的XOR

时间:2017-10-03 22:21:39

标签: c#

我必须进行XOR来计算解密密钥。

我的预期关键是" 0123456789ABCDEFFEDCBA9876543210"我的样本输入是

(" 8D10DA193E98524379264ADFFD043632"和" C339F7EB7339FAC87FAF0478B500422")。第二个样本是(" 00000000000000000000000000000000"和" 0123456789ABCDEFFEDCBA9876543210")

因此,当我将我的第一个样本XOR得到这样的结果时就会出现这种情况" 7123456789ABCDEFFEDCBA9876543210"对于我的第二个样本,我得到的是#34; 123456789ABCDEFFEDCBA9876543210"领先的零正在被切断。

我尝试了各种各样的东西,但这里是我确定的代码:

static void Main(string[] args)
        {
            const string bdk1 = "8D10DA193E98524379264ADFFD043632";
            const string bdk2 = "C339F7EB7339FAC87FAF0478B500422";

            //const string bdk1 = "00000000000000000000000000000000";
            //const string bdk2 = "0123456789ABCDEFFEDCBA9876543210";

            const string expected = "0123456789ABCDEFFEDCBA9876543210";

            BigInteger b1 = BigInteger.Parse(bdk1, NumberStyles.HexNumber);
            BigInteger b2 = BigInteger.Parse(bdk2, NumberStyles.HexNumber);

            BigInteger actual = b1 ^ b2;
            string stringRet = actual.ToString("X");//.PadLeft(expected.Length, '0');

            Console.WriteLine("Expected: " + expected);
            Console.WriteLine("Actual  : " + stringRet);

            Console.ReadLine(); 
        }
    }

3 个答案:

答案 0 :(得分:4)

我建议你解决问题,因为这是一个数据驱动的任务,所以使用以数据为中心的设计。所以从一个将字节数组表示为十六进制字符串的类开始。

class HexString
{
    private byte[] _data;
}

您需要能够从字节数组和字符串构造它,因此为两者添加构造函数。我们的原始存储空间为byte[],因此第一个构造函数是微不足道的。第二个构造函数使用一些LINQ-fu来进行转换:

public class HexString
{
    private byte[] _data;

    public HexString(byte[] data)
    {
        _data = data;
    }

    public HexString(string data)
    {
        if ((data.Length & 1)!= 0) throw new ArgumentException("Hex string must have an even number of digits.");

        _data = Enumerable.Range(0, data.Length)
            .Where(x => x % 2 == 0)
            .Select(x => Convert.ToByte(data.Substring(x, 2), 16))
            .ToArray();
    }
}

如果您无法读取它,则无用,因此请覆盖ToString(),以便您可以通过控制台输出它。在这个示例中,我使用了一个小技巧和BitConverter

    public override string ToString()
    {
        string hex = BitConverter.ToString(_data);
        return hex.Replace("-","");
    }

你需要能够对它进行异或,所以overload the XOR operator。请注意,有问题的值是字节流,而不是数字,因此我们将使用LINQ的Zip()方法一次一个地对每个字节进行异或运算以组合数组:

    static public HexString operator ^(HexString LHS, HexString RHS)
    {
        return new HexString
            (
                LHS._data.Zip
                    ( 
                        RHS._data, 
                        (a, b) => (byte)(a ^ b)
                    )
                .ToArray()
            );
    } 

完成所有这些后,您的主程序变得非常短(应该如此):

public class Program
{
    static public void Main()
    {
        HexString bdk1 = new HexString("8D10DA193E98524379264ADFFD043632");
        HexString bdk2 = new HexString("8C339F7EB7339FAC87FAF0478B500422");

        const string expected = "0123456789ABCDEFFEDCBA9876543210";

        HexString actual = bdk1 ^ bdk2;

        Console.WriteLine("Expected: " + expected);
        Console.WriteLine("Actual  : " + actual);

        Console.ReadLine(); 
    }

输出:

Expected: 0123456789ABCDEFFEDCBA9876543210
Actual  : 0123456789ABCDEFFEDCBA9876543210

请参阅DotNetFiddle上的完整解决方案。

答案 1 :(得分:1)

您正在将一个数字(BitInteger类型)转换为字符串。当然它不会有任何前导零。如果将其转换为字符串,也不会有任何其他数字。

如果由于某种原因确实需要一个前导零,唯一的方法是将转换结果的剩余字符串长度用“0”填充。

或者使用此ToString重载:

number.ToString("X" + totalLengthYouNeed);

答案 2 :(得分:0)

这类似于组合Guids。您可以尝试将字符串转换为字节数组,然后将字节数组xor组合在一起。如果它有帮助,下面是Guids。稍加修改可能会让你到达目的地。

private Guid xorCombineGuids(Guid g1, Guid g2)
{
    var g1Bytes = g1.ToByteArray();
    var g2Bytes = g2.ToByteArray();
    int length = g1.ToByteArray().Count();
    byte[] xoredGuidBytes = new byte[length];
    for (int i = 0; i < g1.ToByteArray().Count(); i++)
    {
        xoredGuidBytes[i] = (byte)(g1Bytes[i] ^ g2Bytes[i]);
    }
    return new Guid(xoredGuidBytes);
}

我还会指出:How can I convert a hex string to a byte array?