5

I looked into so many examples and tried several articles. But none of them solved my issue.

I want to encrypt my Primary Column Value in Database(INTEGER Value) and show it in the URL. I want my URL to be simple and readable, so I don't want lengthy encryption values. Mostly, I am looking around 5 to 7 characters in length.

Is this possible ? If so, what would be the best approach ?

Encrypt and decrypt a string

http://www.codeproject.com/Tips/306620/Encryption-Decryption-Function-in-Net-using-MD-Cry

Community
  • 1
  • 1
Chatra
  • 2,989
  • 7
  • 40
  • 73
  • Your question lacks a lot of info. What type is your column? what is the max length of the content? – Gusman Feb 06 '16 at 22:49
  • The .NET framework has bunch of ciphers in the [`System.Security.Cryptography`](https://msdn.microsoft.com/en-us/library/system.security.cryptography\(v=vs.110\).aspx) namespace. – cbr Feb 06 '16 at 22:51
  • @Gusman I mentioned INTEGER value in caps. – Chatra Feb 06 '16 at 23:01
  • Also, if that's an integer, why you need to cypher it?? Something so simple can just be XORed and then converted in a string, it will have a max length of 10 chars. – Gusman Feb 06 '16 at 23:10
  • @Gusman I think it is straight forward, if I mention as INT. Same length as INT. I clearly mentioned that I want 5 to 7 characters in length. – Chatra Feb 06 '16 at 23:10
  • An INT can have different lengths, in MySQL you explicitly set it's length, so no, it's not straight. – Gusman Feb 06 '16 at 23:11
  • Do you really need to "encrypt and decrypt" or will "encode and decode" be sufficient? Is there some secret information you're trying to protect here? – Jim Lewis Feb 06 '16 at 23:12
  • @Gusman I don't want to show that Primary value to the outside users. So, I want to cypher it. Max length of that value is 6 – Chatra Feb 06 '16 at 23:12
  • Ok, I have one idea ,let me write it. – Gusman Feb 06 '16 at 23:14
  • @JimLewis I tried encoding and decoding. but still the length is too big.http://stackoverflow.com/questions/7368136/decoding-from-base64-in-c-sharp/7368168#7368168 – Chatra Feb 06 '16 at 23:16

2 Answers2

5

As per you requirements, your integers will have no more than 6 chars (999999) and the encoding should be max 7 chars, so a XOR of 24 bits will do it:

Beware this method is esily reversible by a bruteforce attack, but will hide the real numbers for the majority of the mortals.

First we use a three byte key (the values are just examples, take the ones you like the most:

byte[] theKey = new byte[]{ 34, 56, 98 }; 

Then to encode the integer we take the first three bytes (the fourth byte is not necessary as your INT will not use it, only 20 bits can store up to 1M, so the nearest byte count are three) and we XOR each one with the correpsonding byte at the key:

int cyphered = ((theValue & 0xff) ^ theKey[0]) | 
               ((((theValue >> 8) & 0xff) ^ theKey[1]) << 8) | 
               ((((theValue >> 16) & 0xff) ^ theKey[2]) << 16);

And finally, to make the URL's homogeneous you convert it to an string and pad it with zeroes:

string finalValue = cyphered.ToString().PadLeft(7, '0');

To reverse the value just XOR it again with the key:

int cyphered = int.Parse(theStringYouReceived);

int decyphered = ((cyphered & 0xff) ^ theKey[0]) | 
                 ((((cyphered >> 8) & 0xff) ^ theKey[1]) << 8)| 
                 ((((cyphered >> 16) & 0xff) ^ theKey[2]) << 16);

As I say, it's not precissely an AES256 security cipher (:D) but at least will hide the numbers from the curious.

EDIT: here is the test case, it works as expected:

            byte[] theKey = new byte[] { 34, 56, 98 }; 
            int theValue = 1413;

            int cyphered = ((theValue & 0xff) ^ theKey[0]) |
           ((((theValue >> 8) & 0xff) ^ theKey[1]) << 8) |
           ((((theValue >> 16) & 0xff) ^ theKey[2]) << 16);

            string finalValue = cyphered.ToString().PadLeft(7, '0');

            int scyphered = int.Parse(finalValue);

            int decyphered = ((scyphered & 0xff) ^ theKey[0]) |
                             ((((scyphered >> 8) & 0xff) ^ theKey[1]) << 8) |
                             ((((scyphered >> 16) & 0xff) ^ theKey[2]) << 16);
Gusman
  • 14,905
  • 2
  • 34
  • 50
  • Isn't cyphered and decyphere code not the same ? Because it is not converting back to original value – Chatra Feb 06 '16 at 23:31
  • It's the same and it will convert to the original value, that's the magic of XOR, A XOR B = C, A XOR C = B. let me execute the code to see if there is any error. – Gusman Feb 06 '16 at 23:33
  • Yes, there is an error, I forgot to return back the displacement, let me correct it. – Gusman Feb 06 '16 at 23:37
  • still there is as error, it is not converting to correct value – Chatra Feb 07 '16 at 00:03
  • It works, gimme an example of the key, the int, the string you got and the value decyphered and I can check it. – Gusman Feb 07 '16 at 00:04
  • The Key is same as you mentioned here. Integer value I am passing is 1413. When it cyphers, the value 0000255 but when convert back the value is 6437085 – Chatra Feb 07 '16 at 00:14
  • You have something wrong, the cipher pass will return 6438311, and the decipher will return 1413, executed and checked. – Gusman Feb 07 '16 at 00:20
  • How can I modify the code that it generates a 6-digit cyphered int instead of 7-digit? – Hotschke May 16 '20 at 09:00
0

You can of course roll your own, but the following library looks like it might be useful based on the info provided.

http://hashids.org/net/

Obviously consider your security requirements and whether this sufficiently meets them.

Alan Macdonald
  • 1,872
  • 20
  • 36