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 decrypt the encrypted number back to the original number.

It is important that it isn't obvious if 2 encrypted numbers are in order. So for instance if I encrypt 0000000000001 it should look totally different when encrypted than 000000000002. It doesn't have to be the most secure thing in the world, but the more secure the better.

I've been looking around a lot but haven't found anything that seems to be a perfect fit. From what I've seen some type of XOR might be the easiest way to go, but I'm not sure how to do this.

Is it essential that your result be a numeric value? Also, what are your security requirements? Rule #1 of encryption is "do not rely on your own encryption"
–
MatthewJan 26 '11 at 19:46

It is ideal that the result be a numeric value, but not an absolute requirement. The result will be printed on packaging and entered into a website. If alphanumeric was the only option, then that would be okay but could only include a-z and 0-9 no special characters. As for security requirements, I don't think we'll have a team of hackers trying to crack this routine. We're not really protecting anything critical, so I'd say its more important that its not easily distinguishable that the numbers are in order (as mentioned above) than it being totally secure.
–
JimJan 26 '11 at 21:15

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.

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:

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.

So when I Xor 2 5 character numbers (for example) sometimes I get a 6 digit result. It just shouldn't be this tough. I'm either doing the Xor wrong or sometimes they add up to greater than 9. Any chance you could put in a 5 line code sample?
–
JimJan 26 '11 at 22:26

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.

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.