3

We're looking for a way to encrypt a 16 digit number (could be 10-20 digits), with the following requirements:

  • Output is also a number
  • Output doesn't double (or greatly increase the number of digits)
  • Doesn't require pre-storing a massive mapping table
  • Ok with moderate to low security
dazhi
  • 339
  • 1
  • 3
  • 13
  • 4
    Because one of the requirments are to store hash output as number you instantly surrender your security. Also, a "16 digit number" leads me to believe you guys are trying to hash a credit card number? Ouch. Scary thought. – Dan Kanze Jun 02 '13 at 17:15
  • @DanKanze - could you elaborate a bit more on the problem with number? Why will using some number as output pose a security threat? Also, OP is asking about encryption (reversible), not about hashing (non-reversible). – Rogach Jun 02 '13 at 17:21
  • 1
    @Rogach I meant the digest of the the output is very high risk. Can be cracked with a sure fire line of permutations. – Dan Kanze Jun 02 '13 at 17:23
  • @DanKanze - Let me rephrase - you mean that the requirement for a *small number* in the output is bad, right? – Rogach Jun 02 '13 at 17:28
  • @Rogach I'm assuming that the key will be a number bc the requirement for the output is a number. – Dan Kanze Jun 02 '13 at 17:34
  • You maybe find an answer here: [Is there an encryption technique that could turn an 8-digit number into something 10 or 11 digits or less?](http://stackoverflow.com/q/3604803/237483) – Christian Ammer Jun 02 '13 at 17:39
  • @DanKanze - sorry, can't parse - what `bc` means? Anything can be represented as a number, after all. – Rogach Jun 02 '13 at 17:41
  • @Rogach Sure, anything can be represented as a number. But were talking about the encrypted output of the number. And that output would need to be encrypted with "another number" because there are very limited encryption methods that can be used when you add that constraint. At least that I know of. Care to share alternative thoughts? – Dan Kanze Jun 02 '13 at 17:50
  • don't worry, not credit card numbers! – dazhi Jun 03 '13 at 16:10
  • @dazhi Can you tell us what you will do with this encrypted number? It's possible that you don't *really* need encryption at all especially since you claim you only need "low" security. Telling us what you are trying to achieve and what you need to do with these numbers will allow us to determine whether something else could satisfy your requirements. – Nik Bougalis Jun 03 '13 at 18:52
  • Sure, I'm looking for a way to print a "transaction ID" on invoices + receipts. Users will be able to enter the transaction ID on a website for credit or rewards. So that's why I want to encrypt it, so it's not easily guessable. – dazhi Jun 04 '13 at 18:45

3 Answers3

4

Simple and very low security: Add something, then XOR the number with another number of similar size. Only viable if nobody has access to the source code. And anybody who has access to the program (even without source) and who can run it with a few samples (0, 1000, 10000, 10000000) will be able to figure it out.

Depending on language:

   uint64_t theNumber;

   uint64_t cryptbase1= 12345678909876, cryptbase2= 234567890987654;

   // encrypt 
   uint64_t encrypted= (theNumber + cryptbase1) ^ cryptbase2;

   // decrypt 
   uint64_t decrypted= (encrypted ^ cryptbase2) - cryptbase1;
Nicholaz
  • 1,419
  • 9
  • 11
  • You can also throw in a small multiplier somewhere, e.g. "((theNumber + cryptbase1) * 13) ^ cryptbase2" if you don't mind the increase in digits. – Nicholaz Jun 02 '13 at 17:30
  • 1
    Disassembling the binary would still show the XORs in the ASM code. – Hunter McMillen Jun 02 '13 at 17:31
  • Also, you can run encrypt twice or more (and then decrypt twice too). – Nicholaz Jun 02 '13 at 18:15
  • @hunter: yes, access to the encrypting program will reduce security severly, it then certainly won't withstand a talented hacker or crypto specialist more than a hour. – Nicholaz Jun 02 '13 at 18:16
3

I can imagine a 16 digit to 20 digit encryption algorithm:

Encrypt:

  1. Convert the 16 digit number into its binary representation (54 bits needed).
  2. Use a block cipher algorithm with a small blocksize (e.g. Triple-DES has a block size of 64 bits) to encrypt the 54 bits.
  3. Convert the encrypted 64 bits into its 20 digit representation.

Decrypt:

  1. Convert the 20 digit number into its binary 64 bit representation.
  2. Use the block cipher algorithm to decrypt.
  3. Convert the 64 bits into its 20 digit representation. The left 4 digits have to be 0, 16 digits remain.
Christian Ammer
  • 7,464
  • 6
  • 51
  • 108
  • One problem with this is that it can't encrypt all 20 decimal digit numbers since those need up to 66 bits. – CodesInChaos Jun 04 '13 at 19:56
  • @CodesInChaos: You are right, in this case one could try to switch to a blocksize of 3 * 32 bit ([Skip32](http://stackoverflow.com/a/513097/237483) supports such a small blocksize). This would lead to a 20 digit to 29 digit encryption algorithm. – Christian Ammer Jun 05 '13 at 06:14
1

You are probably looking at a block cypher with a block size able to hold up to 20 decimal digits. You can use Hasty Pudding cipher, which has a variable block size, or alternatively you could roll your own simple Feistel cipher with an even number of bits per block. You do not seem to need a very high level of security, so a simple Feistel cipher with four or six rounds would probably be easier.

I use a simple Feistel cipher for integer permutations, and the F function is:

// The F function for the Feistel rounds.
private int F(int num, int round) {
    // XOR with round key.
    num ^= mRoundKeys[round];
    // Square, then XOR the high and low parts.
    num *= num;
    return (num >>> HALF_SHIFT) ^ (num & LOW_16_MASK);
} // end F()

You do not seem to need anything more complex than that. If you want cryptographic security, then use Hasty Pudding, which is a lot more secure.

Any binary block of the appropriate size can be represented as decimal digits.

rossum
  • 15,344
  • 1
  • 24
  • 38