21.03.2013 Views

Problem - Kevin Tafuro

Problem - Kevin Tafuro

Problem - Kevin Tafuro

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

When you’re done using a key, you should delete it securely to prevent local attackers<br />

from recovering it from memory. (This is discussed in Recipe 13.2.)<br />

Discussion<br />

While keys in public key cryptography are represented as very large numbers (and often<br />

stored in containers such as X.509 certificates), symmetric keys are always represented<br />

as a series of consecutive bits. Algorithms operate on these binary representations.<br />

Occasionally, people are tempted to use a single 64-bit unit to represent short keys<br />

(e.g., a long long when using GCC on most platforms). Similarly, we’ve commonly<br />

seen people use an array of word-size values. That’s a bad idea because of byte-ordering<br />

issues. When representing integers, the bytes of the integer may appear most significant<br />

byte first (big-endian) or least significant byte first (little-endian). Figure 4-1<br />

provides a visual illustration of the difference between big-endian and little-endian<br />

storage:<br />

1 2 3 4<br />

Big–endian for 32-bit words<br />

Figure 4-1. Big-endian versus little-endian<br />

Endian-ness doesn’t matter when performing integer operations, because the CPU<br />

implicitly knows how integers are supposed to be represented and treats them appropriately.<br />

However, a problem arises when we wish to treat a single integer or an array<br />

of integers as an array of bytes. Casting the address of the first integer to be a pointer<br />

to char does not give the right results on a little-endian machine, because the cast<br />

does not cause bytes to be swapped to their “natural” order. If you absolutely always<br />

cast to an appropriate type, this may not be an issue if you don’t move data between<br />

architectures, but that would defeat any possible reason to use a bigger storage unit<br />

than a single byte. For this reason, you should always represent key material as an<br />

array of one-byte elements. If you do so, your code and the data will always be portable,<br />

even if you send the data across the network.<br />

You should also avoid using signed data types, simply to avoid potential printing<br />

oddities due to sign extension. For example, let’s say that you have a signed 32-bit<br />

value, 0xFF000000, and you want to shift it right by one bit. You might expect the<br />

result 0x7F800000, but you’d actually get 0xFF800000, because the sign bit gets shifted,<br />

and the result also maintains the same sign. *<br />

* To be clear on semantics, note that shifting right eight bits will always give the same result as shifting right<br />

one bit eight times. That is, when shifting right an unsigned value, the leftmost bits always get filled in with<br />

zeros. But with a signed value, they always get filled in with the original value of the most significant bit.<br />

118 | Chapter 4: Symmetric Cryptography Fundamentals<br />

4 3 2 1<br />

Little–endian for 32-bit words<br />

This is the Title of the Book, eMatter Edition<br />

Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!