How can I take a maximum 19-digits long BigInteger and encrypt it with the following rules:

  • The result must be based on digits and lower-case English letters only.
  • All outputs must have the same length to any input. The length must be between 11 to 16 characters, depending on your method, but should be consistent for all possible inputs.
  • No easy patterns. For example, if you encrypt 000...1 and 000...2 the results should look completely different.
  • No collisions at all
  • Should be able to decrypt back to the original BigInteger.

Things that I have tried

  • Take the original number, XOR it by some key, multiply it by a factor and convert it to a base 36 string. The purpose of the factor is to expand the range so there won't be too much 0 padding. The factor must be between 1 to 36^16/10^19. The problem with this method is that a) it's not 'secure' enough, and b) close numbers have very similar results.

  • This answer. However, the result was often too short or too long, and the factor method used before didn't work here.

  • $\begingroup$ Are the inputs always non-negative? $\:$ $\endgroup$
    – user991
    Mar 20, 2013 at 20:08
  • $\begingroup$ Please also see the cross post on stackoverflow $\endgroup$
    – Maarten Bodewes
    Mar 20, 2013 at 22:19
  • $\begingroup$ Do you need to support any 19 digit integer? Or is the input limited to 64 bits? $\endgroup$ May 4, 2015 at 14:34

1 Answer 1


Well, first of all, when we do encryption, we generally insist that there is a "key" involved; this key is something that the person doing the encryption and the person doing the decryption knows, but no one else. The goal of an encryption method is that someone who doesn't know the key can't gain any information from the encrypted messages.

Note: there are methods where the key that the encryptor knows differs from the key the decryptor knows; for example, the encryption key might not be able to be used to decrypt. This comes in handy at times; I'll assume that you don't need that.

Now, the next questions are:

  • Do you care whether, if you encrypt the exact same number twice, you come up with the same encryption"? Usually, we do care (because we don't want someone looking at the encrypted messages to deduce that we sent the same plaintext message twice), however you might not (for example, you might know that you'll never actually encrypt the exact same number twice).

  • Do you care whether, if someone tweaks the ciphertext, and you decrypt that ciphertext, you get a warning that the ciphertext isn't what was encrypted? Generally, we do; we do this by adding a cryptographical checksum; if that checksum doesn't validate, we know that something's not right.

However, here is a procedure that doesn't address either of these issues:

  • First of all, a maximum 19-digits long bignum fits within 64 bits (almost exactly); the first step of the encryption process will to convert the Bignum into an 8 byte (64 bit) integer.

  • Now that we have an 8 byte integer, the easiest way to encrypt it would be to have a 3DES key, and encrypt those 8 bytes in ECB mode (in case you're wondering, ECB mode is almost always the wrong solution; this is one of the few situations where it is appropriate).

  • Now that we have an encrypted 64 bit value, we convert that value into a base-32 value (using the 10 digits and 22 lower case characters to represent the 32 digits; a 64 bit value can be represented by 13 base-32 digits; that's our encrypted text.

Decryption (as long as you have the 3DES key) is straight-forward; you just follow the procedure backwards, reversing each step.

Now, why did I leave the above two issues unaddressed? Well, that's because such an extension would cause the ciphertext to be longer. The problem with that is your limit that the ciphertext be limited to a maximum of 16 digits and lower case characters; that means that we have (at best) 18 bits or so of possible ciphertext expansion, and that's not much.

What this means is that if you do care about the above two problems, you may need to rethink your limits of the ciphertext size (or possibly expanding the ciphertext alphabet; allowing upper case characters would mean we have 31 bits to play with).

  • $\begingroup$ Same as my answer on stackoverflow really, with some added info. $\endgroup$
    – Maarten Bodewes
    Mar 20, 2013 at 22:13
  • $\begingroup$ Also: $\:$ Does he care whether, if someone tweaks the ciphertext (and if there is such a checksum $\hspace{.5 in}$ then the checksum happens to validate), the decryption of the tweaked ciphertext could be $\hspace{.7 in}$ different from but meaningfully related to the original plaintext? $\;\;$ $\endgroup$
    – user991
    Mar 21, 2013 at 16:49
  • $\begingroup$ @RickyDemer: actually, with what I suggested (using 3DES in ECB mode), the attacker would have no control over what it decrypts to (other than that it's not what the original number was) $\endgroup$
    – poncho
    Mar 21, 2013 at 17:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.