Related
#include <stdio.h>
#include <stdint.h>
#define Nb 4
#define Nk 4
#define Nr 10
uint8_t state[4 * Nb];
uint8_t w[Nb * (Nr + 1) * 4];
#define mul2(x) ((x << 1) ^ (((x >> 7) & 1) * 0x1b))
#define mul3(x) (mul2(x) ^ x)
#define mul9(x) (mul2(mul2(mul2(x))) ^ x)
#define mul11(x) (mul2(mul2(mul2(x)) ^ x) ^ x)
#define mul13(x) (mul2(mul2(mul2(x) ^ x)) ^ x)
#define mul14(x) (mul2(mul2(mul2(x) ^ x) ^ x))
i dont want to use lookup table for xor multiplications so used this above method as reference to caliculate the values runtime
uint8_t sbox[256] = {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
};
uint8_t inv_sbox[256] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
};
uint8_t rcon[256] = {
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39,
0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8,
0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef,
0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc,
0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b,
0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3,
0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94,
0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20,
0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35,
0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f,
0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04,
0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63,
0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d
};
uint32_t sub_bytes_word(uint32_t word) {
uint8_t* bytes = (uint8_t*)&word;
for (int i = 0; i < 4; i++) {
bytes[i] = sbox[bytes[i]];
}
return word;
}
uint32_t inv_sub_bytes_word(uint32_t word) {
uint8_t* bytes = (uint8_t*)&word;
for (int i = 0; i < 4; i++) {
bytes[i] = inv_sbox[bytes[i]];
}
return word;
}
uint32_t rot_word(uint32_t word) {
return (word << 8) | (word >> 24);
}
uint32_t sub_word(uint32_t word) {
return sub_bytes_word(word);
}
uint32_t inv_word(uint32_t word) {
return inv_sub_bytes_word(word);
}
void key_expansion(uint8_t* key) {
for (int i = 0; i < Nk; i++) {
w[i] = key[4 * i] << 24 | key[4 * i + 1] << 16 | key[4 * i + 2] << 8 | key[4 * i + 3];
}
for (int i = Nk; i < 4 * (Nr + 1); i++) {
uint32_t temp = w[i - 1];
if (i % Nk == 0) {
temp = sub_word(rot_word(temp)) ^ rcon[i / Nk - 1];
} else if (Nk > 6 && i % Nk == 4) {
temp = sub_word(temp);
}
w[i] = w[i - Nk] ^ temp;
}
for (int i = 0; i < 4 * (Nr + 1); i++) {
w[i] = inv_word(w[i]);
}
}
void sub_bytes() {
for (int i = 0; i < 4 * Nb; i++) {
state[i] = sbox[state[i]];
}
}
void shift_rows() {
uint8_t temp[4 * Nb];
for (int i = 0; i < 4 * Nb; i++) {
temp[i] = state[i];
}
for (int i = 0; i < Nb; i++) {
state[i] = temp[i];
state[i + 4] = temp[i + 4];
state[i + 8] = temp[i + 8];
state[i + 12] = temp[i + 12];
}
state[1] = temp[5];
state[5] = temp[9];
state[9] = temp[13];
state[13] = temp[1];
state[2] = temp[10];
state[6] = temp[14];
state[10] = temp[2];
state[14] = temp[6];
state[3] = temp[15];
state[7] = temp[3];
state[11] = temp[7];
state[15] = temp[11];
}
void mix_columns() {
uint8_t temp[4 * Nb];
for (int i = 0; i < 4 * Nb; i++) {
temp[i] = state[i];
}
for (int i = 0; i < Nb; i++) {
state[0 + 4 * i] = mul2(temp[0 + 4 * i]) ^ mul3(temp[1 + 4 * i]) ^ temp[2 + 4 * i] ^ temp[3 + 4 * i];
state[1 + 4 * i] = temp[0 + 4 * i] ^ mul2(temp[1 + 4 * i]) ^ mul3(temp[2 + 4 * i]) ^ temp[3 + 4 * i];
state[2 + 4 * i] = temp[0 + 4 * i] ^ temp[1 + 4 * i] ^ mul2(temp[2 + 4 * i]) ^ mul3(temp[3 + 4 * i]);
state[3 + 4 * i] = mul3(temp[0 + 4 * i]) ^ temp[1 + 4 * i] ^ temp[2 + 4 * i] ^ mul2(temp[3 + 4 * i]);
}
}
void add_round_key(int round) {
for (int i = 0; i < 4 * Nb; i++) {
state[i] ^= w[round * 4 * Nb + i];
}
}
void aes_round(int round) {
sub_bytes();
shift_rows();
mix_columns();
add_round_key(round);
}
void inv_sub_bytes() {
for (int i = 0; i < 4 * Nb; i++) {
state[i] = inv_sbox[state[i]];
}
}
void inv_shift_rows() {
uint8_t temp[4 * Nb];
for (int i = 0; i < 4 * Nb; i++) {
temp[i] = state[i];
}
for (int i = 0; i < Nb; i++) {
state[i] = temp[i];
state[i + 4] = temp[i + 4];
state[i + 8] = temp[i + 8];
state[i + 12] = temp[i + 12];
}
state[1] = temp[13];
state[5] = temp[1];
state[9] = temp[5];
state[13] = temp[9];
state[2] = temp[10];
state[6] = temp[14];
state[10] = temp[2];
state[14] = temp[6];
state[3] = temp[7];
state[7] = temp[11];
state[11] = temp[15];
state[15] = temp[3];
}
void inv_mix_columns() {
uint8_t temp[4 * Nb];
for (int i = 0; i < 4 * Nb; i++) {
temp[i] = state[i];
}
for (int i = 0; i < Nb; i++) {
state[0 + 4 * i] = mul14(temp[0 + 4 * i]) ^ mul11(temp[1 + 4 * i]) ^ mul13(temp[2 + 4 * i]) ^ mul9(temp[3 + 4 * i]);
state[1 + 4 * i] = mul9(temp[0 + 4 * i]) ^ mul14(temp[1 + 4 * i]) ^ mul11(temp[2 + 4 * i]) ^ mul13(temp[3 + 4 * i]);
state[2 + 4 * i] = mul13(temp[0 + 4 * i]) ^ mul9(temp[1 + 4 * i]) ^ mul14(temp[2 + 4 * i]) ^ mul11(temp[3 + 4 * i]);
state[3 + 4 * i] = mul11(temp[0 + 4 * i]) ^ mul13(temp[1 + 4 * i]) ^ mul9(temp[2 + 4 * i]) ^ mul14(temp[3 + 4 * i]);
}
}
void inv_aes_round(int round) {
add_round_key(round);
inv_mix_columns();
inv_shift_rows();
inv_sub_bytes();
}
Here i tried encrypt and decrypt the plain text
void encrypt(uint8_t* plaintext, uint8_t* key) {
for (int i = 0; i < 4 * Nb; i++) {
state[i] = plaintext[i];
}
key_expansion(key);
add_round_key(0);
for (int i = 1; i <= Nr; i++) {
aes_round(i);
}
}
void decrypt(uint8_t* ciphertext, uint8_t* key) {
for (int i = 0; i < 4 * Nb; i++) {
state[i] = ciphertext[i];
}
key_expansion(key);
add_round_key(Nr);
for (int i = Nr - 1; i >= 1; i--) {
inv_aes_round(i);
}
inv_aes_round(0);
}
My main function
int main() {
// Set key and plaintext
uint8_t key[16] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};
uint8_t plaintext[16] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};
uint8_t ciphertext[16];
uint8_t decrypted[16];
// Plaintext
printf("Original plaintext: ");
for (int i = 0; i < 16; i++) {
printf("%02x ", plaintext[i]);
}
printf("\n");
// Encrypt plaintext
encrypt(plaintext, key);
printf("Ciphertext: ");
for (int i = 0; i < 4 * Nb; i++) {
printf("%02x ", state[i]);
ciphertext[i] = state[i];
}
printf("\n");
// Decrypt ciphertext
decrypt(ciphertext, key);
printf("Decrypted: ");
for (int i = 0; i < 4 * Nb; i++) {
printf("%02x ", state[i]);
decrypted[i] = state[i];
}
printf("\n");
return 0;
}
i have tried improving the code many times by assigning seperate functions to implement but every time my output is wrong .\
This is my output ; whatever i tried iam not able to get correct decrypt . iam not sure where i did mistake .
Original plaintext: 01 23 45 67 89 ab cd ef 01 23 45 67 89 ab cd ef
Ciphertext: ec d5 9c a4 41 cb cb e5 08 02 a3 cc 7c 39 be 74
Decrypted: 37 b8 75 c5 01 5c 74 14 b4 e9 11 d8 3c 16 cd c2
typedef struct _utf8_multibyte {
uint8_t bytes[4]; /* always max of 4 */
int used; /* how many of the 4 bytes are used */
} utf8_multibyte_t;
typedef struct _utf8_string {
uint8_t *raw; /* raw string buffer */
uint32_t *chars; /* codepoints comprising the string */
uint64_t length; /* number of codepoints in string */
} utf8_string_t;
...
utf8_string_t *utf8_init(unsigned char *s) {
utf8_string_t *str = (utf8_string_t*)malloc(sizeof(utf8_string_t*));
if (!str) {
perror("utf8_string_t init");
return NULL;
}
str->raw = (uint8_t*)malloc(strlen(s) * sizeof(uint8_t));
if (!str->raw) {
perror("malloc raw");
return NULL;
}
memcpy(str->raw, s, strlen(s));
str->length = utf8_strlen(s);
str->chars = (uint32_t*)malloc(str->length * sizeof(uint32_t));
if (!str->chars) {
perror("malloc chars");
return NULL;
}
uint8_t *p = s;
utf8_multibyte_t mb;
mb_clear(&mb);
int j = 0;
while (*p != '\0') {
int len = utf8len(*p);
mb.used = len;
mb.bytes[0] = *p++;
for (int i = 1; i < len; ++i) mb.bytes[i] = *p++;
uint32_t cp = utf8_decode(&mb);
str->chars[j++] = cp;
printf("%x ", str->chars[j - 1]);
mb_clear(&mb);
}
return str;
}
I am testing if the initialization is going correctly with this code:
unsigned char data[] = {
0xe5, 0xbd, 0xbc, 0xe5, 0xa5, 0xb3, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0xa2, 0xe3, 0x82, 0xa4, 0xe3,
0x82, 0xb9, 0xe3, 0x82, 0x92, 0xe9, 0xa3, 0x9f, 0xe3, 0x81, 0xb9, 0xe3, 0x81, 0x9f, 0xe3, 0x81,
0x8b, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x89, 0xe8, 0xb2, 0xb7,
0xe3, 0x81, 0x84, 0xe3, 0x81, 0xab, 0xe5, 0x87, 0xba, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x91, 0xe3,
0x81, 0xbe, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0x9f, 0xe3, 0x80, 0x82, 0x0
};
unsigned char data1[] = {
0xe5, 0xbd, 0xbc, 0xe5, 0xa5, 0xb3, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0xa2, 0xe3, 0x82, 0xa4, 0xe3,
0x82, 0xb9, 0xe3, 0x82, 0x92, 0xe9, 0xa3, 0x9f, 0xe3, 0x81, 0xb9, 0xe3, 0x81, 0x9f, 0xe3, 0x81,
0x8b, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x89, 0xe8, 0xb2, 0xb7,
0xe3, 0x81, 0x84, 0xe3, 0x81, 0xab, 0xe5, 0x87, 0xba, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x91, 0xe3,
0x81, 0xbe, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0x9f, 0xe3, 0x80, 0x82, 0x0
};
utf8_string_t *str1 = utf8_init(data);
utf8_string_t *str2 = utf8_init(data1);
printf("%d %d\n", str1->length, str2->length);
/*utf8_free(str1);
utf8_free(str2);*/
One of the strings sometimes doesn't get initialized and when it does it reports it's length as 0 when it should be 25. I tried printing out the codepoints from the strings as they're initialized and they're completely ok so I am led to believe it's got something to do with the raw string allocation but I am not sure.
I know this has something to do with my memory management but I have been staring at this code for 2 days and still cannot figure out where my mistake is. Please help me.
EDIT:
I think I managed to fix it thanks to the recommendations in the comments. Here's the updated code:
utf8_string_t *utf8_init(const uint8_t *s) {
utf8_string_t *str = malloc(sizeof(utf8_string_t));
if (!str) {
free(str);
return NULL;
}
uint64_t rawlen = strlen_uchar(s);
str->raw = malloc((rawlen + 1) * sizeof(uint8_t));
if (!str->raw) {
free(str->raw);
free(str);
return NULL;
}
memcpy(str->raw, s, rawlen + 1);
str->length = utf8_strlen(s);
str->chars = malloc(str->length * sizeof(uint32_t));
if (!str->chars) {
free(str->raw);
free(str->chars);
free(str);
return NULL;
}
uint8_t *p = (uint8_t*)s;
utf8_multibyte_t mb;
mb_clear(&mb);
int j = 0;
while (*p != '\0') {
int len = utf8len(*p);
mb.used = len;
mb.bytes[0] = *p++;
for (int i = 1; i < len; ++i) mb.bytes[i] = *p++;
uint32_t cp = utf8_decode(&mb);
str->chars[j++] = cp;
mb_clear(&mb);
}
return str;
}
Please do tell if there are still parts of it which might bring about undefined behavior/bugs.
Here as most rated answer (Implementing CRC8 on Arduino to write to MLX90614) is a good example of CRC-8 calculation/finding using a lookup table. I would like to know what is the polynomial used to generate those table values.
So given the table, how can I recover the polynomial? I tried using this nice calculator of tables, but cannot get the same values.
static const uint8_t crc_table[] = {
0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31,
0x24, 0x23, 0x2a, 0x2d, 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65,
0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, 0xe0, 0xe7, 0xee, 0xe9,
0xfc, 0xfb, 0xf2, 0xf5, 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd,
0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 0xa8, 0xaf, 0xa6, 0xa1,
0xb4, 0xb3, 0xba, 0xbd, 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2,
0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea, 0xb7, 0xb0, 0xb9, 0xbe,
0xab, 0xac, 0xa5, 0xa2, 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a,
0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, 0x1f, 0x18, 0x11, 0x16,
0x03, 0x04, 0x0d, 0x0a, 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42,
0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a, 0x89, 0x8e, 0x87, 0x80,
0x95, 0x92, 0x9b, 0x9c, 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4,
0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, 0xc1, 0xc6, 0xcf, 0xc8,
0xdd, 0xda, 0xd3, 0xd4, 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c,
0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, 0x19, 0x1e, 0x17, 0x10,
0x05, 0x02, 0x0b, 0x0c, 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34,
0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, 0x76, 0x71, 0x78, 0x7f,
0x6a, 0x6d, 0x64, 0x63, 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b,
0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, 0xae, 0xa9, 0xa0, 0xa7,
0xb2, 0xb5, 0xbc, 0xbb, 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83,
0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, 0xe6, 0xe1, 0xe8, 0xef,
0xfa, 0xfd, 0xf4, 0xf3
};
uint8_t
crc8(uint8_t *p, uint8_t len)
{
uint16_t i;
uint16_t crc = 0x0;
while (len--) {
i = (crc ^ *p++) & 0xFF;
crc = (crc_table[i] ^ (crc << 8)) & 0xFF;
}
return crc & 0xFF;
}
Well, the link you provided shows the exact same table for the (default) polynomial 0x07, which is (x^8) + x^2 + x + 1. So this should already answer your question.
With the above being said, for a general "target" table, you can very easily brute force the needed polynomial.
I'll let the code speak for itself, here's a working example:
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
static const uint8_t target[256] = {
// ... fill in the values here ...
};
void compute_table(uint8_t table[256], uint8_t polynomial) {
uint8_t crc = 0x80;
size_t i, j;
memset(table, 0, 256);
for (i = 1; i < 256; i <<= 1) {
if (crc & 0x80)
crc = (crc << 1) ^ polynomial;
else
crc <<= 1;
for (j = 0; j < i; j++)
table[i + j] = crc ^ table[j];
}
}
int main(void) {
uint8_t table[256];
uint8_t poly;
bool found;
size_t i;
for (poly = 1; poly != 0; poly++) {
compute_table(table, poly);
found = true;
for (i = 0; i < 256; i++) {
if (table[i] != target[i]) {
found = false;
break;
}
}
if (found)
printf("Found polynomial: 0x%02x\n", poly);
}
return 0;
}
And indeed, plugging in the table you provide, the above code outputs:
Found polynomial: 0x07
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
unsigned char table[256] = {0};
void crc_table_create(unsigned char *pdata, unsigned char factor)
{
unsigned char temp;
for (int i = 0; i < 256; i++)
{
pdata[i] = i;
}
for (int i = 0; i < 256; i++)
{
for (int j = 7; j >= 0; j--)
{
temp = pdata[i] & 0x80; // take the MSB bit
if (temp) // the MSB bit is 1
{
pdata[i] = pdata[i] << 1;
pdata[i] ^= factor;
}
else
{
pdata[i] = pdata[i] << 1;
}
}
// printf("table[%i]= 0x%02x", i, table[i]);
// getchar();
}
}
int main(void)
{
int i, j = 0;
uint8_t poly = 0x07; // X8 + X2 + X1 + 1 (100000111B the MSB bit is mute, so it turn to 0x07)
crc_table_create(table, poly);
for (i = 0; i < 256; i++)
{
if (i % 12 == 0) {
printf("\n");
}
printf("0x%02x, ", table[i]);
}
printf("\n");
return 1;
}
Here is the CRC8 table generater, after run it, the 'table[256]' is the result, enjoy!
I'm trying to use simple encryption/decryption (treyfer) for a project of mine, but there's no reference implementation of decryption available. What I've got (based off of the Wikipedia implementation) is:
uint8_t rotl(uint8_t x) {
return (x << 1) | (x >> 7);
}
uint8_t rotr(uint8_t x) {
return (x >> 1) | (x << 7);
}
void encrypt (uint8_t text[8], uint8_t key[8]) {
int r, i;
uint8_t t;
for (r=0; r<NUMROUNDS; r++) {
text[8] = text[0];
for (i=0; i<8; i++) {
text[i+1] = rotl((text[i+1] + sbox[(key[i] + text[i]) % 256]));
}
text[0] = text[8];
}
}
void decrypt (uint8_t text[8], uint8_t key[8]) {
int r, i;
uint8_t t;
for (r=0; r<NUMROUNDS; r++) {
text[8] = text[0];
for (i=8; i>=0; --i) {
text[i+1] = rotr(text[i+1]) - sbox[(key[i] + text[i]) % 256];
}
text[0] = text[8];
}
}
void printhex(uint8_t text[8]) {
for(int i = 0; i < 8; i++) {
printf("%02x", text[i]);
}
}
int main() {
char text[8+1] = "AAAAAAAA";
char key[8+1] = "AAAAAAAA";
puts("plaintext:");
printhex(text);
puts("\nkey:");
printhex(key);
puts("\nencrypted:");
encrypt(text, key);
printhex(text);
puts("\ndecrypted:");
decrypt(text, key);
printhex(text);
}
Where Sbox is the AES S-box, and NUMROUNDS = 128
However, when I run this, I get wildly different results for the plaintext and the decrypted value, suggesting either my encryption or decryption is incorrect, but I can't quite see how. Hoping I haven't missed anything too painful.
The output I get is:
plaintext:
4141414141414141
key:
4141414141414141
encrypted:
658ed27d394127a0
decrypted:
a0460a65d755953f
I assume your implementation is based on this: https://en.wikipedia.org/wiki/Treyfer
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#define NUMROUNDS 100
static const uint8_t sbox[256] = {
//0 1 2 3 4 5 6 7 8 9 A B C D E F
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 };
void treyfer_encrypt(uint8_t text[8], uint8_t const key[8])
{
unsigned i;
uint8_t t = text[0];
for (i = 0; i < 8*NUMROUNDS; i++) {
t += key[i%8];
t = sbox[t] + text[(i+1)%8];
text[(i+1) % 8] = t = (t << 1) | (t >> 7); /* Rotate left 1 bit */
}
}
void encrypt(uint8_t text[8], uint8_t const key[8])
{
unsigned int i = 0;
unsigned int j = 0;
uint8_t t = 0;
t = text[0];
for (j = 0; j < NUMROUNDS; j++)
{
for (i = 0; i < 8; i++)
{
t = t + key[i];
t = sbox[t] + text[(i + 1) % 8];
t = (t << 1) | (t >> 7);
text[(i + 1) % 8] = t;
}
}
}
void decrypt(uint8_t text[8], uint8_t const key[8])
{
int i = 0;
int j = 0;
uint8_t top = 0;
uint8_t bottom = 0;
for (j = 0; j < NUMROUNDS; j++)
{
for (i = 7; i >= 0; i--)
{
top = text[i] + key[i];
top = sbox[top];
bottom = text[(i + 1) % 8];
bottom = (bottom >> 1) | (bottom << 7);
text[(i + 1) % 8] = bottom - top;
}
}
}
void printhex(uint8_t text[8]) {
int i;
for(i = 0; i < 8; i++) {
printf("%02x", text[i]);
}
}
int main() {
uint8_t text[8] = "AAAAAAAA";
uint8_t text2[8] = "AAAAAAAA";
uint8_t key[8] = "AAAAAAAA";
puts("plaintext:");
printhex(text);
puts("\nkey:");
printhex(key);
puts("\n\nref encrypted:");
treyfer_encrypt(text, key);
printhex(text);
puts("\n\nencrypted:");
encrypt(text2, key);
printhex(text2);
puts("\n\ndecrypted:");
decrypt(text2, key);
printhex(text2);
puts("\n");
}
results
plaintext:
4141414141414141
key:
4141414141414141
ref encrypted:
cc3121ccab578d93
encrypted:
cc3121ccab578d93
decrypted:
4141414141414141
I'm stumped by the compiler error "error: array must be initialized with a brace-enclosed initializer". None of the other examples of this problem seem to related to this. I haven't touched C in about 14 years, so I think the term "rust" is a bit generous. I'm sure I've just missed something silly.
typedef uint8_t DeviceAddress[8];
DeviceAddress Probe01 = { 0x28, 0xFF, 0x87, 0x5A, 0x91, 0x15, 0x04, 0xE0 };
DeviceAddress Probe02 = { 0x28, 0xFF, 0x97, 0x5E, 0x91, 0x15, 0x04, 0x92 };
DeviceAddress Probe03 = { 0x28, 0xFF, 0xCD, 0x81, 0x91, 0x15, 0x01, 0x1E };
DeviceAddress Probe04 = { 0x28, 0xFF, 0xA6, 0x69, 0x91, 0x15, 0x04, 0x15 };
DeviceAddress Probe05 = { 0x28, 0xFF, 0xD8, 0x7E, 0x91, 0x15, 0x04, 0x64 };
struct DeviceInfo {
DeviceAddress addr;
const char * name;
};
struct DeviceInfo devices[5] = {
{.addr = Probe01, .name = "Pump1"},
{.addr = Probe02, .name = "Pump2"},
{.addr = Probe03, .name = "Pump3"},
{.addr = Probe04, .name = "Pump4"},
{.addr = Probe05, .name = "Pump5"}
};
struct DeviceInfo devices[5] = {
{.addr = Probe01, .name = "Pump1"},
{.addr = Probe02, .name = "Pump2"},
{.addr = Probe03, .name = "Pump3"},
{.addr = Probe04, .name = "Pump4"},
{.addr = Probe05, .name = "Pump5"}
};
Here, addr is of type DeviceAddress, which is just a uint8_t array. You can't assign into an array in C, so the compiler is telling you that assigning Probe1 into the field addr is invalid; it needs its own brace-enclosed array initializer there.
You have a couple of options. You could get rid of Probe01, Probe02, etc altogether and just initialize the arrays as the compiler suggests:
struct DeviceInfo devices[5] = {
{.addr = { 0x28, 0xFF, 0x87, 0x5A, 0x91, 0x15, 0x04, 0xE0 }, .name = "Pump1" },
...
};
Another option, which is a bit roundabout, is to have two typedefs:
typedef uint8_t DeviceAddress[8];
typedef uint8_t * DeviceAddress_P;
struct DeviceInfo {
DeviceAddress_P addr;
const char * name;
};
And use the pointer type in the struct, initializing it to point to the first element of the array you created:
DeviceAddress Probe01 = { 0x28, 0xFF, 0x87, 0x5A, 0x91, 0x15, 0x04, 0xE0 };
struct DeviceInfo devices[5] = {
{.addr = Probe01, .name = "Pump1"},
...
};
However, this way, the struct just points to an external array, which is probably not desirable.
If you use "Probe0x" just as helpers to make think clearer as asked by #M.M, you can initialise the array devices of type Struct DeviceInfo as fallow:
struct DeviceInfo devices[5] = {
{{ 0x28, 0xFF, 0x87, 0x5A, 0x91, 0x15, 0x04, 0xE0 }, "Pump1"},
{{ 0x28, 0xFF, 0x97, 0x5E, 0x91, 0x15, 0x04, 0x92 }, "Pump2"},
{{ 0x28, 0xFF, 0xCD, 0x81, 0x91, 0x15, 0x01, 0x1E }, "Pump3"},
{{ 0x28, 0xFF, 0xA6, 0x69, 0x91, 0x15, 0x04, 0x15 }, "Pump4"},
{{ 0x28, 0xFF, 0xD8, 0x7E, 0x91, 0x15, 0x04, 0x64 }, "Pump5"}
};