Encrypt a number to another number of the same length

前端 未结 6 1507
逝去的感伤
逝去的感伤 2021-01-13 03:59

I need a way to take a 12 digit number and encrypt it to a different 12 digit number (no characters other than 0123456789). Then at a later point I need to be able to decryp

相关标签:
6条回答
  • 2021-01-13 04:29

    If there's enough wriggle-room in the requirements that you can accept 16 hexadecimal digits as the encrypted side, just interpret the 12 digit decimal number as a 64bit plaintext and use a 64 bit block cipher like Blowfish, Triple-DES or IDEA.

    0 讨论(0)
  • 2021-01-13 04:32

    One more way for simple encryption, you can just substruct each number from 10.

    For example initial numbers: 123456

    10-1 = 9 10-2 = 8 10-3 = 7 etc.

    and you will get 987654

    You can combine it with XOR for more secure encryption.

    0 讨论(0)
  • 2021-01-13 04:33

    What you're talking about is kinda like a one-time pad. A key the same length as the plaintext and then doing some modulo math on each individual character.

    A xor B = C
    C xor B = A
    

    or in other words

    A xor B xor B = A
    

    As long as you don't use the same key B on multiple different inputs (e.g. B has to be unique, every single time you encrypt), then in theory you can never recover the original A without knowing what B was. If you use the same B multiple times, then all bets are off.

    comment followup:

    You shouldn't end up with more bits aftewards than you started with. xor just flips bits, it doesn't have any carry functionality. Ending up with 6 digits is just odd... As for code:

    $plaintext = array(digit1, digit2, digit3, digit4, digit5, digit6);
    $key = array(key1, key2, key3, key4, key5, key6);
    $ciphertext = array()
    
    # encryption
    foreach($plaintext as $idx => $char) {
       $ciphertext[$idx] = $char xor $key[$idx];
    }
    
    # decryption
    foreach($ciphertext as $idx => $char) {
       $decrypted[$idx] = $char xor $key[$idx];
    }
    

    Just doing this as an array for simplicity. For actual data you'd work on a per-byte or per-word basis, and just xor each chunk in sequence. You can use a key string shorter than the input, but that makes it easier to reverse engineer the key. In theory, you could use a single byte to do the xor'ing, but then you've just basically achieved the bit-level equivalent of rot-13.

    0 讨论(0)
  • 2021-01-13 04:42

    anyone with reflector or ildasm will be able to hack such an encryption algorithm.

    I don't know what is your business requirement but you have to know that.

    0 讨论(0)
  • 2021-01-13 04:44

    I ended up solving this thanks to you guys using "FPE from a prefix cipher" from the wikipedia page http://en.wikipedia.org/wiki/Format-preserving_encryption. I'll give the basic steps below to hopefully be helpful for someone in the future.

    NOTE - I'm sure any expert will tell you this is a hack. The numbers seemed random and it was secure enough for what I needed, but if security is a big concern use something else. I'm sure experts can point to holes in what I did. My only goal for posting this is because I would have found it useful when doing my search for an answer to the problem. Also only use this in situations where it couldn't be decompiled.

    I was going to post steps, but its too much to explain. I'll just post my code. This is my proof of concept code I still need to clean up, but you'll get the idea. Note my code is specific to a 12 digit number, but adjusting for others should be easy. Max is probably 16 with the way I did it.

    public static string DoEncrypt(string unencryptedString)
    {
        string encryptedString = "";
        unencryptedString = new string(unencryptedString.ToCharArray().Reverse().ToArray());
        foreach (char character in unencryptedString.ToCharArray())
        {
            string randomizationSeed = (encryptedString.Length > 0) ? unencryptedString.Substring(0, encryptedString.Length) : "";
            encryptedString += GetRandomSubstitutionArray(randomizationSeed)[int.Parse(character.ToString())];
        }
    
        return Shuffle(encryptedString);
    }
    
    public static string DoDecrypt(string encryptedString)
    {
        // Unshuffle the string first to make processing easier.
        encryptedString = Unshuffle(encryptedString);
    
        string unencryptedString = "";
        foreach (char character in encryptedString.ToCharArray().ToArray())
            unencryptedString += GetRandomSubstitutionArray(unencryptedString).IndexOf(int.Parse(character.ToString()));
    
        // Reverse string since encrypted string was reversed while processing.
        return new string(unencryptedString.ToCharArray().Reverse().ToArray());
    }
    
    private static string Shuffle(string unshuffled)
    {
        char[] unshuffledCharacters = unshuffled.ToCharArray();
        char[] shuffledCharacters = new char[12];
        shuffledCharacters[0] = unshuffledCharacters[2];
        shuffledCharacters[1] = unshuffledCharacters[7];
        shuffledCharacters[2] = unshuffledCharacters[10];
        shuffledCharacters[3] = unshuffledCharacters[5];
        shuffledCharacters[4] = unshuffledCharacters[3];
        shuffledCharacters[5] = unshuffledCharacters[1];
        shuffledCharacters[6] = unshuffledCharacters[0];
        shuffledCharacters[7] = unshuffledCharacters[4];
        shuffledCharacters[8] = unshuffledCharacters[8];
        shuffledCharacters[9] = unshuffledCharacters[11];
        shuffledCharacters[10] = unshuffledCharacters[6];
        shuffledCharacters[11] = unshuffledCharacters[9];
        return new string(shuffledCharacters);
    }
    
    private static string Unshuffle(string shuffled)
    {
        char[] shuffledCharacters = shuffled.ToCharArray();
        char[] unshuffledCharacters = new char[12];
        unshuffledCharacters[0] = shuffledCharacters[6];
        unshuffledCharacters[1] = shuffledCharacters[5];
        unshuffledCharacters[2] = shuffledCharacters[0];
        unshuffledCharacters[3] = shuffledCharacters[4];
        unshuffledCharacters[4] = shuffledCharacters[7];
        unshuffledCharacters[5] = shuffledCharacters[3];
        unshuffledCharacters[6] = shuffledCharacters[10];
        unshuffledCharacters[7] = shuffledCharacters[1];
        unshuffledCharacters[8] = shuffledCharacters[8];
        unshuffledCharacters[9] = shuffledCharacters[11];
        unshuffledCharacters[10] = shuffledCharacters[2];
        unshuffledCharacters[11] = shuffledCharacters[9];
        return new string(unshuffledCharacters);
    }
    
    public static string DoPrefixCipherEncrypt(string strIn, byte[] btKey)
    {
        if (strIn.Length < 1)
            return strIn;
    
        // Convert the input string to a byte array 
        byte[] btToEncrypt = System.Text.Encoding.Unicode.GetBytes(strIn);
        RijndaelManaged cryptoRijndael = new RijndaelManaged();
        cryptoRijndael.Mode =
        CipherMode.ECB;//Doesn't require Initialization Vector 
        cryptoRijndael.Padding =
        PaddingMode.PKCS7;
    
    
        // Create a key (No IV needed because we are using ECB mode) 
        ASCIIEncoding textConverter = new ASCIIEncoding();
    
        // Get an encryptor 
        ICryptoTransform ictEncryptor = cryptoRijndael.CreateEncryptor(btKey, null);
    
    
        // Encrypt the data... 
        MemoryStream msEncrypt = new MemoryStream();
        CryptoStream csEncrypt = new CryptoStream(msEncrypt, ictEncryptor, CryptoStreamMode.Write);
    
    
        // Write all data to the crypto stream to encrypt it 
        csEncrypt.Write(btToEncrypt, 0, btToEncrypt.Length);
        csEncrypt.Close();
    
    
        //flush, close, dispose 
        // Get the encrypted array of bytes 
        byte[] btEncrypted = msEncrypt.ToArray();
    
    
        // Convert the resulting encrypted byte array to string for return 
        return (Convert.ToBase64String(btEncrypted));
    }
    
    private static List<int> GetRandomSubstitutionArray(string number)
    {
        // Pad number as needed to achieve longer key length and seed more randomly.
        // NOTE I didn't want to make the code here available and it would take too longer to clean, so I'll tell you what I did. I basically took every number seed that was passed in and prefixed it and  postfixed it with some values to make it 16 characters long and to get a more unique result. For example:
        // if (number.Length = 15)
        //    number = "Y" + number;
        // if (number.Length = 14)
        //    number = "7" + number + "z";
        // etc - hey I already said this is a hack ;)
    
        // We pass in the current number as the password to an AES encryption of each of the
        // digits 0 - 9. This returns us a set of values that we can then sort and get a 
        // random order for the digits based on the current state of the number.
        Dictionary<string, int> prefixCipherResults = new Dictionary<string, int>();
        for (int ndx = 0; ndx < 10; ndx++)
            prefixCipherResults.Add(DoPrefixCipherEncrypt(ndx.ToString(), Encoding.UTF8.GetBytes(number)), ndx);
    
        // Order the results and loop through to build your int array.
        List<int> group = new List<int>();
        foreach (string key in prefixCipherResults.Keys.OrderBy(k => k))
            group.Add(prefixCipherResults[key]);
    
        return group;
    }
    
    0 讨论(0)
  • 2021-01-13 04:46

    For example you can add digits of your number with digits some const (214354178963...whatever) and apply "~" operator (reverse all bits) this is not safely but ensure you can decrypt your number allways.

    0 讨论(0)
提交回复
热议问题