Search code examples
c#stringxorkey-generator

Serial key generation xor string encryption


When I do an xor on a string I get special characters

private void btnEncryptDecrypt_Click(object sender, EventArgs e)
    {
        byte[] bytes = Encoding.UTF8.GetBytes(keyTextBox.Text);
        textTextBox.Text = string.Empty;

        foreach (byte i in bytes)
        {
            byte c = Convert.ToByte(i ^ Convert.ToByte(textBox1.Text));

            textTextBox.Text = textTextBox.Text + Convert.ToChar(c);

        }         

    }

62FA7AC4 1234567890 xor to !%QV VT#7&%$#"! /.'

I want to use it for serial key generation with only alphanumeric characters I want to pass "62FA7AC4", a date and a number between 0 and 5000 and a few random dummy numbers

Input will be "62FA7AC4"+"2500"+"21/05/2018"

Output should be something like "5QBK-J4D1-8CF6-5MW2-78FZ-2FPL-4S6S-CTGB"

What am I doing Wrong?


Solution

  • Try working with numbers, not strings:

      using System.Numerics;
    
      ... 
    
      // Let's use BigInteger for arbitrary long values
      BigInteger left = BigInteger.Parse("62FA7AC4", NumberStyles.HexNumber);
      BigInteger right = BigInteger.Parse("1234567890", NumberStyles.HexNumber);
    
      string result = (left ^ right).ToString("X");
    
      Console.Write(result);
    

    So you have

      1256AC0254
    

    Edit: As far as I can see you want alphanumeric (i.e. Base 36 == 26 letters + 10 digits output). You can use the same approach: operate with integer(s), not string(s)

      private static Random s_Random = new Random();
    
      ...
    
      BigInteger value = BigInteger.Parse(
          "0"        +                             // we don't want negative values  
          "62FA7AC4" +                             // header 
           s_Random.Next(5001).ToString("0000") +  // random in [0..5000] range
           DateTime.Today.ToString("ddMMyyyy"),    // Date like 21052018
        NumberStyles.HexNumber);                    
    

    Then do any xor (if you like):

     value ^= some_secret_value;
    

    Finally represent the value in base 36:

    private static String ToBase36(BigInteger value) {
      List<char> list = new List<char>();
    
      for (int index = 0; value > 0; value /= 36, index++) {
        if (index > 0 && index % 4 == 0)
          list.Add('-');
    
        BigInteger v = value % 36;
    
        list.Add(v < 10 ? (char)('0' + v) : (char) ('A' + v - 10));
      }
    
      list.Reverse();
    
      return string.Concat(list);
    }
    

    Test:

     BigInteger value = BigInteger.Parse(
        "0" + 
        "62FA7AC4" + 
        "2500" + 
         DateTime.Today.ToString("ddMMyyyy"), 
       NumberStyles.HexNumber);
    
     string result = ToBase36(value);
    
     Console.Write(result);
    

    Outcome:

    2443-WNC5-AVBB-M32W
    

    Edit 2: To restore the original number

    private static BigInteger FromBase36(string value) {
      BigInteger result = 0;
      BigInteger power = 1;
    
      for (int i = value.Length - 1; i >= 0; --i) {
        char item = value[i];
    
        if (item >= '0' && item <= '9') {
          result += power * (item - '0');
          power *= 36;
        }
        else if (item >= 'A' && item <= 'Z') {
          result += power * (item - 'A' + 10);
          power *= 36;
        }
        else if (item >= 'a' && item <= 'z') {
          result += power * (item - 'a' + 10);
          power *= 36;
        }
      }
    
      return result;
    }
    

    e.g.

    BigInteger value = BigInteger.Parse(
        "0"        + 
        "62FA7AC4" + 
        "2500" + 
         DateTime.Today.ToString("ddMMyyyy"), 
       NumberStyles.HexNumber);
    
    string result = ToBase36(value);
    
    BigInteger back = FromBase36(result);
    
    Console.WriteLine(string.Join(Environment.NewLine, value, result, back));
    

    Outcome:

    467412447575903165554712
    2443-WNC5-AVBB-M32W
    467412447575903165554712