How can I convert a normal alphabetical text (say hi
) to a 64 bit or 128 bit binary digit input for DES?
-
6$\begingroup$ Can you tell me are you familiar with commonplace text encodings such as ASCII and UTF-8? $\endgroup$– DannyNiuOct 23, 2020 at 6:42
2 Answers
What's asked requires choices not explicit in the question:
1. Character encoding into bytes
The most common and recommendable convention nowadays is UTF-8, which encodes any character as a sequence of 1 to 4 bytes, including any ASCII character as 1 byte. For these, UTF-8 is compatible with many other earlier conventions that encode each character to a single byte. The Latin alphabet and Arabic numerals are encoded incrementally, per the poor man's ASCII table
a
$\to$ 0x61 b
$\to$ 0x62 … z
$\to$ 0x7a
A
$\to$ 0x41 B
$\to$ 0x42 … Z
$\to$ 0x4a
0
$\to$ 0x30 1
$\to$ 0x31 … 9
$\to$ 0x39
$\to$ 0x20 (space)
Note: the prefix 0x introduces hexadecimal in this answer, and some common computer languages.
Therefore, the two-character hi
gets encoded to the two bytes 0x68 0x69 per UTF-8, ASCII, ISO/IEC 8859-1, Windows-1252, and many others conventions.
Encoding and decoding is built into many common computer languages, e.g. in Python
bytes('Hi😷', 'UTF-8')
equals b'\x48\x69\xf0\x9f\x98\xb7'
and
b'\x48\x69\xf0\x9f\x98\xb7'.decode('UTF-8')
yields 'Hi😷'
.
Other conventions are still in wide use, e.g. per UTF-16 LE with surrogate pair support, the three-character 'Hi😷'
encodes to 0x48 0x00 0x69 0x00 0x3d 0xd8 0x37 0xde.
2. Padding
That is handling the last byte(s) to form the last (perhaps only) block for the cipher, of 64 bits or 8 bytes in the context of DES. There are several conventions around, the most common being:
- Zero-padding. For a block cipher with $w$ bytes ($w=8$ in the case of DES), it is added $0$ to $w-1$ bytes at 0x00, as necessary to reach a multiple of $w$. That's fine for encodings (including UTF-8) that assign to byte 0x00 a no-operation or end meaning, but is not usable for arbitrary bytestring, because the decoder facing a last block ending in 0x00 won't know if that byte needs to be kept or removed.
hi
per UTF-8 is padded to 0x68 0x69 0x00 0x00 0x00 0x00 0x00 0x00. - Various bytes padding, the most common of which nowadays being PKCS#7 padding. For a block cipher with $w$ bytes ($w=8$ in the case of DES), it is added $1$ to $w$ bytes which common value is the number of bytes added in order to reach a multiple of $w$.
hi
per UTF-8 is padded to 0x68 0x69 0x06 0x06 0x06 0x06 0x06 0x06.
Note: The decoder handling the last block (if any) should get the value $x$ of the last byte, remove that byte, then remove the $(w-1+x)\bmod w$ byte(s) before that, thus leaving $0$ to $w-1$ bytes. That's compatible with some common variant of PKCS#7 padding such as ANSI X9.23, and minimizes the risk of padding oracle attacks. - Bit padding. It's common in cryptography for MACs, hashes, and sometime encryption (I know no official name; it's ISO/IEC 9797-1 Padding Method 2 in a DES MAC context). For a block cipher with $b$ bits ($b=64$ in the case of DES), it is added a single bit at one, then $0$ to $b-1$ bit(s) at zero as necessary to get to a multiple of 64 bits. In most contexts including DES, the bits are converted into bytes per big-endian convention, so that the single bit at one becomes byte 0x80.
hi
per UTF-8 is padded to 0x68 0x69 0x80 0x00 0x00 0x00 0x00 0x00.
Finally, there's a specific
Bit numbering per the DES specification
and it matters when doing one's implementation of DES from scratch for educational purposes. Each of the 8 bytes is turned to 8 bits per big-endian binary, leading to a sequence of 64 bits numbered from 1 to 64. Bit $i\in[1,\,64]$ belongs to the byte at offset $\lfloor(i-1)/8\rfloor$ and extractible by shifting that right by $(64-i)\bmod8$ bit(s) then keeping the low-order bit.
In C: (blockOf8Bytes[(i-1)&7]>>((64-i)&7))&1
(the 64
can be omitted).
Thus hi
per UTF-8 with zero padding is
0110100001101001000000000000000000000000000000000000000000000000
with the seven bits 2, 3, 5, 10, 11, 13, 16 set (at 1) and the other fifty-seven bits clear (at 0).
Note: Except in the insecure ECB mode of operation, the plaintext would be combined (likely, by exclusive-OR) with something before entering the DES block cipher.
Note: The question mentions “(…) 128 bit binary digit input for DES”, but nothing that requires more than one 64-bit block for hi
.
Note: DES is insecure as a design choice due to its 56-bit key. It is obsolete at least for bulk encryption purposes in all its forms, including 3DES with 168-bit key, due to its 64-bit block size.
-
3$\begingroup$ Padding and DES bit numbering are specific to cryptography, which arguably makes the question on-topic. I detailed the problem of encoding even though it is less specific (making questions on encoding off-topic), because it causes issues to increasingly many aspiring cryptographers with no idea of how computers manipulate text. $\endgroup$– fgrieu ♦Oct 23, 2020 at 14:27
-
$\begingroup$ W.R.T. bit padding: did you ever notice that the bit ordering in bytes is still from most significant to least significant for little endian machines? You write
01 00
for value 1 instead of80 00
or at least10 00
. So80
still makes the most sense even for little endian. I never understood using01
. I mean, you can see that the bit is on the right side instead of the left? Of course, with bits not being directly addressable from memory, the whole idea of "left" and "right" is somewhat muddled, but at least we humans have a convention. $\endgroup$– Maarten Bodewes ♦Nov 22, 2020 at 1:27
First of all you should not use DES, it is not secure and, arguably, never has been secure as the key size of 56 bits is well below 128 bits. The strength of the key after analysis is even less than that.
All block ciphers operate on blocks of binary input. For DES you'd have an input / output of 64 bit / 8 byte. However, using just DES is not secure; you need to use a block cipher mode of operation. If you'd use ECB or CBC you'd need to pad any message to a multiple of 64 bit / 8 byte. Generally PKCS#5 padding is used for that. For other modes such as CFB or OFB you can have binary plaintext messages of any size (usually in bytes).
So as the plaintext is binary, how can you get from text to binary? Well, that's simple: you'd use a character encoding such as US-ASCII or the compatible UTF-8 scheme. This is also how plain text files (as you would create in Notepad) are stored on your computer's hard disk. File storage is binary too after all.
Generally your programming environment would allow you to do this using explicit encoding functions. You can also program a basic ASCII encoder yourself, simply set the byte to 41h (hex) + the zero based index of the character in the English alphabet for uppercase. For lowercase you'd do the same thing starting with 61h. Decimal digits are starting at 30h for the zero.
-
$\begingroup$ I stole from you in an update of my answer. Imitation is the sincerest form of flattery. $\endgroup$– fgrieu ♦Oct 25, 2020 at 9:14
-