1
$\begingroup$

Given a key with a certain key size (e.g., 64bits). Would I be correct to interpret this as 8 characters (since each character would be 8 bits under ASCII encoding)?

Because the ASCII scheme is limited to just 127 characters, this would mean that characters not included in the English language are not considered. Could it be instead that 64 bits has to be interpreted based on an encoding scheme such as unicode that includes many more characters? -- This would mean that 64 bits contains a much smaller number of characters since a unicode character takes more bits.

$\endgroup$
  • 1
    $\begingroup$ incidentally, this is exactly why passwords need different handling than keys $\endgroup$ – dandavis Aug 1 '16 at 20:27
  • $\begingroup$ Can you clarify? What exactly is the difference in treatment between the two? $\endgroup$ – Minaj Aug 1 '16 at 21:02
  • 1
    $\begingroup$ key's "encoding scheme" is not unicode, it's typically hex or base64, which lets us represent any 0-255 value in a couple plain chars instead of one raw "byte". we don't usually use hex-encoded strings for entering passwords, so they need different handling. Then there's the part about password alphabets being only 90-something chars instead of 255, so we need derivation to stretch the bits while possibly sandbagging the performance to avert brute-forcing. $\endgroup$ – dandavis Aug 1 '16 at 21:41
  • $\begingroup$ This means that individual bytes within a key do not necessarily map to ASCII or keyboard characters, right? But I have heard of cases where a password is used to produce a key. How is this exactly? $\endgroup$ – Minaj Aug 1 '16 at 22:01
2
$\begingroup$

"Characters" is the wrong level of abstraction here, and fixating on that can only lead you astray. Proper cryptographic keys are not passwords!

  • Passwords are normally human-chosen, and users may be expected to memorize them.
  • Cryptographic keys must not be human-chosen! And no good key is human-memorable—you should generally keep keys as copies under secure storage (which may be password-protected).

Why is this so important? Because most cryptographic algorithms expect you to choose keys uniformly at random from the whole range of allowed values. For algorithms where the key is a fixed-length bit sequence, that means any sequence of bits of the required size should be equally likely as any other.

This means that to generate a cryptographic key you must not ask humans to choose characters like you do for passwords, because humans are bad at randomness. Rather, you must use a cryptographically secure random number generator to produce an array of randomly-chosen raw bytes. So to work with keys you should stay clear of any character string types that involve character encodings like ASCII or Unicode, and learn how to work with byte arrays in the programming language of your choice. For example in Java it would be the byte[] type; in Rust it would be [u8] (byte slice) or [u8; N] (byte array of size N); in C it would be char[] (a type that in hindsight should have had a different name); etc. Or even better, you should work with a type that abstracts away from this, like Java's KeyGenerator and SecretKey.

Note that keys are sometimes serialized as base-64 or hexadecimal ASCII string, but that's just a format for, e.g., sticking them into file types like JSON that can't accept arbitrary bytes. But the algorithms want the raw byte arrays!

Also, there is something called password-based key derivation, which is the use of specialized cryptographic algorithms to turn user-selected passwords into pseudo-random cryptographic keys. Well-designed encryption programs that work off passwords don't use the user-supplied passwords directly as keys, but rather run them through such an algorithm. This is sometimes called "password-based encryption." Popular algorithms for deriving keys from passwords are:

Note that this approach trades security for user-friendliness. Users find passwords easier to (mis)use and (mis)understand than proper cryptographic keys, but they are very unlikely to choose passwords that are nearly as strong as a proper, randomly-generated key. (And the very few users who choose equivalently strong passwords are likely sophisticated enough to use proper keys!)

$\endgroup$
  • $\begingroup$ Your mention of the java byte type leads me to the next question: In java, the byte type holds integers from -127 and 128. But keys i believe should be between 0 and 255 for each byte; which requires the same amount of memory, but with different meanings. Any comment about this? $\endgroup$ – Minaj Aug 2 '16 at 0:18
  • $\begingroup$ @Minaj: That's indeed a quirk of Java's, but Java APIs that deal with unsigned bytes just pretend otherwise and implicitly treat the byte values' bit representations as the equivalent unsigned byte value. Case in point, Java uses byte[] in the character encoding methods in String—see this constructor and this method. $\endgroup$ – Luis Casillas Aug 2 '16 at 2:15
  • $\begingroup$ @Minaj: One catch that's worth mentioning though is that when you're implementing cryptographic algorithms that assume unsigned words you often have to do some funny stuff in Java to avoid getting bitten by the signed semantics. For example, to convert an int to a long with unsigned semantics (i.e., just pad the int's binary representation with zeroes), you can't to (long)myInt but rather have to do myInt & 0x00000000ffffffffL. Google's Guava library has some support for this sort of operations. $\endgroup$ – Luis Casillas Aug 2 '16 at 2:18
  • 1
    $\begingroup$ In C (and C++ etc) it's better to use unsigned char or since 1999 the effectively equivalent but more descriptive uint8_t. Plain char may be signed or unsigned depending on the implementation, so code you tested on one system may suddenly break when moved to another. For Java yes byte being signed is a nuisance but at least it's consistent so you just learn to type &0xFF everywhere. $\endgroup$ – dave_thompson_085 Aug 2 '16 at 6:01
3
$\begingroup$

Yes, 64 bits is equivalent to 8 bytes, because there are 8 bits per byte.

"Could it be instead that 64 bits has to be interpreted based on an encoding scheme such as unicode that includes many more characters? "

No - the key does not need to be encoded as either ascii or UTF. Typically crypto algorithms operate either on an array of unsigned characters, or larger words when required (i.e. unsigned long long for 64 bit words).

$\endgroup$
  • $\begingroup$ note: I'm not sure what your use case is where you got the encoding idea from. $\endgroup$ – Ella Rose Aug 1 '16 at 19:16
  • $\begingroup$ Is it not possible to have a key such as "ab1234cd"? In such a case we would need a way to convert it into 1s and 0s, which calls for an encoding scheme -- thats how I got into this whole encoding idea. $\endgroup$ – Minaj Aug 1 '16 at 21:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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