views:

64

answers:

4

I need to encrypt a number and I and this encrypted value will be given to a customer ask a key so I want to minimize the number of digits and make them all printable.

So I'd like the result to be either all number or all Hex characters.

The current encryption method I'm using (for non numbers) converts the characters to hex (2 hex digits each). That doubles the number of characters. I also considered just treating the input as hex (so each pair of numbers is treated as a Hex pair, but then you have ambiguity between an input of 0123 and 123 (when decrypting that leading '0' is lost.

Any suggestions?

+1  A: 

Don't conflate two different issues. Use any secure encryption algorithm (I recommend AES-256), and then use base64 encoding if the output has to be printable.

If you want to restrict it to another set (e.g. lower-case letters), use the appropriate base (e.g. hexavigesimal)

Matthew Flaschen
Although base64 is "printable" it's not really manually "type-able", so if the requirement is that they copy the code from a printed document, then base64 is not the best choice.
Dean Harding
The level of security is not critical but the # of digits is. I'm not trying to protect the pentagon here, I'm trying to keep grandma from casually stealing software. Grandma can't copy and paste and I sure don't want her trying to type in a 16 digit key.
Clay Nichols
A: 

If the requirement is that you print out a card with the "license key" on it, that they have to manually type in then I think encrypting the required values is not the best solution. There'll just be too much data.

I think a better solution is to use a simple hash algorithm on their username/email address that they've registered with to hash the result to a 128-bit value (16 bytes) and then use Base-32 to convert that into the letters A-Z and digits 2-7 (which would come out at around 26 characters).

Base32 has the advantage that it's not case-sensitive (like base 64 is) and you don't get confusion between "i" and "1" (etc).

Dean Harding
I've managed to simply the license key so it's only about 5 to 10 digits (all Hex characters)
Clay Nichols
A: 

I figured out a simple kludge: If the # of digits is odd then I prefix a placeholder Hex(F) character. Then when I decrpypt, if I see that placeholder (F) then I know it was a place holder (b/c only numbers are allowed as input to this function)

Clay Nichols
A: 

It seems that you are confusing encryption and encoding. They are completely separate concerns. Because you don't provide nearly enough information about required security to say anything about appropriate encryption I'll assume that you are talking about encoding. For encoding, it actually doesn't matter if the input is encrypted or not. The only difference is that an encrypted input almost certainly can't be compressed, so any compression should be done before encryption.

For encoding, the simplest approach is to consider the input as a large number (you ), pick a set of symbols and encode the number as base-N where N is the size of the chosen set. Because the resulting code is intended for human entry, you'll want to avoid having multiple characters with similar shapes (1,l,I / o,O,0,D / 5,S), the choice is dependent on the font used.

It's also very useful to have some error detection built in. A simple way to create good error detection is to add some bits of a good hash function to the number. For example (in pseudocode):

number_to_encode = input_number << 5 | MD5(input_number) & 0x1F
encoded_string = Base32Encode(number_to_encode)

number_to_decode = Base32Decode(encoded_string)
output_number = number_to_decode >> 5
checksum = number_to_decode & 0x1F
if MD5(output_number) & 0x1F != checksum then
    Error

You can do better than that if you have an error model, but assuming random error model it's as good as it gets, detecting more than 96% of all errors, adding only one base32 character.

Ants Aasma