# The Burnt Textbook

You and your team have successfully intercepted a message from the enemy, which could win you the war! But the message is encrypted with a difficult cipher, and your textbook's instructions for deciphering the same are badly burnt and hardly readable. Can you still decipher the message?

The message:

5dcb 3b80 6a00 7fa7 7701 81a4 7035 3608 1533 0008 54cb d205 f0f9 ad30 79aa 2e68 3aa6 9e4a 8b40 18d3 4152 a896 7617 71d5 1c00 6274 48e3 7209 0392 0b64 aea6 d205 f0f9 d732 0a60 a6da b0e9 0040

The textbook:

When the Enemy has brought hither his Message, it will be encrypted in ####-###-#########, which can be decoded by splitting each #### into ####-###-chunks. To convert, add fifty-nine to each #### which has been #####, by keeping only the least-significant ones. One may use the Function below to get the ####-###-chunks.

The textbook's function:

#define LSB1 0x01
#define LSB2 0x03
#define LSB3 0x07
#define LSB4 0x0F
#define LSB5 0x1F

static void write_as_ascii(uint8_t *dec, uint8_t *data) {
dec[0] = (data[0] >> 3) & LSB5;
dec[1] = ((data[0] & ####) << #) | (data[1] >> 6) & ####;
dec[2] = (data[1] >> 1) & LSB5;
dec[3] = ((data[#] & LSB1) << 4) | (data[2] >> #) & ####;
dec[4] = ((data[2] & ####) << 1) | (data[3] >> 7) & LSB1;
dec[5] = (data[#] >> 2) & LSB5;
dec[6] = ((data[3] & ####) << 3) | (data[4] >> 5) & LSB3;
dec[7] = data[4] & LSB5;
}


What does the message say in English?

• Welcome to Puzzling! Is this a puzzle you created yourself? If not, please add a source (such as a link). We have an attribution policy here and unsourced puzzles will be closed and perhaps deleted. Feb 19, 2021 at 19:42
• @Acrid Before posting my answer, I will wait until the source and attribution of this puzzle are added to the question. Feb 19, 2021 at 23:01
• Hi! The puzzle was created by me, although it's less a puzzle and more just a repurposed earlier idea. I have the source code and binaries for the original project if you need proof. Feb 20, 2021 at 11:16

First of all, as indicated by the write_as_ascii() function, the message is actually a series of bytes (uint8_t), not 16-bits words. The words given are the combination of two bytes in a little endian format, meaning the least-significant byte is first (e.g. 5dcb is actually the byte CB followed by the byte 5D).

Moreover, the decoding function write_as_ascii() takes 5 bytes in input and outputs 8 bytes. Let's rewrite the encoded message this way:

    cb 5d 80 3b 00
6a a7 7f 01 77
a4 81 35 70 08
36 33 15 08 00
cb 54 05 d2 f9
68 2e a6 3a 4a
9e 40 8b d3 18
52 41 96 a8 17
76 d5 71 00 1c
74 62 e3 48 09
72 92 03 64 0b
a6 ae 05 d2 f9
f0 32 d7 60 0a
da a6 e9 b0 40
00


The cypher is actually

some kind of Base32 encoding/decoding mechanism.

Every chunk of 5 bytes must be divided into 8 chunks of 5 bits, each giving a number between 0 and 31 (2^5 - 1). Per the instructions in the textbook, every such number must then be added to 59, the result being an ASCII code between 59 (;) and 90 (Z).

The purpose of the decoding function write_as_ascii() is

to take 5 bytes in input (the data array) and isolate the 8 five-bit-chunks, which are stored into the dec array. To achieve this, it uses bit-shifting and bit-masking operations that are specific to each decoded byte.

The mapping between the input bytes data and the decoded bytes dec is as follow:
 data[0] data[1] data[2] data[3] data[4]
bits 76543210 76543210 76543210 76543210 76543210
 <dc0><dec1><dc2><dec3><dec4><dc5><dec6><dc7>

Once the decoding function write_as_ascii() has been applied to each byte from the original message, we get this array of bytes:

25 13 14 24 0 14 24 0
13 10 19 23 30 0 11 23
20 18 0 19 10 28 0 8
 6 24 25 17 10 2 0 0
25 13 10 0 11 20 23 25
30 0 24 10 27 10 19 25
13 0 23 10 12 14 18 10
19 25 0 8 23 20 24 24
10 9 0 25 13 10 0 23
14 27 10 23 2 0 0 28
14 17 17 14 6 18 0 9
14 10 9 0 6 25 0 11
20 26 23 0 11 20 23 25
30 0 25 13 14 24 0 10
27 10 19 14 19 12 2 0

Once you add fifty-nine and display the resulting number as an ASCII character, your get:

84 T 72 H 73 I 83 S 59 ; 73 I 83 S 59 ;
72 H 69 E 78 N 82 R 89 Y 59 ; 70 F 82 R
79 O 77 M 59 ; 78 N 69 E 87 W 59 ; 67 C
65 A 83 S 84 T 76 L 69 E 61 = 59 ; 59 ;
84 T 72 H 69 E 59 ; 70 F 79 O 82 R 84 T
89 Y 59 ; 83 S 69 E 86 V 69 E 78 N 84 T
72 H 59 ; 82 R 69 E 71 G 73 I 77 M 69 E
78 N 84 T 59 ; 67 C 82 R 79 O 83 S 83 S
69 E 68 D 59 ; 84 T 72 H 69 E 59 ; 82 R
73 I 86 V 69 E 82 R 61 = 59 ; 59 ; 87 W
73 I 76 L 76 L 73 I 65 A 77 M 59 ; 68 D
73 I 69 E 68 D 59 ; 65 A 84 T 59 ; 70 F
79 O 85 U 82 R 59 ; 70 F 79 O 82 R 84 T
89 Y 59 ; 84 T 72 H 73 I 83 S 59 ; 69 E
86 V 69 E 78 N 73 I 78 N 71 G 61 = 59 ;

Thus, yielding the following message:

THIS IS HENRY FROM NEW CASTLE.
THE FORTY SEVENTH REGIMENT CROSSED THE RIVER.
WILLIAM DIED AT FOUR FORTY THIS EVENING.

• Damn, wasn't expecting it to be that quick. Impressive. Feb 22, 2021 at 15:30
• Thank you @Acrid. Actually, most of the puzzles here aren't provided with a textbook, burnt or not, and you would be amazed how several people here are even faster than me. Welcome on PSE! :-) Feb 22, 2021 at 15:52