-
-
Save odzhan/f0cb8657060199b93540f710f4883485 to your computer and use it in GitHub Desktop.
FEAL Block Cipher Implementations from Handbook of Cryptography.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// FEAL-8 Block Cipher | |
// | |
#include <stdio.h> | |
#include <stdint.h> | |
// Define the Sd function as per equation (7.6) | |
uint8_t Sd(uint8_t x, uint8_t y, uint8_t d) { | |
uint16_t sum = x + y + d; // Sum could be up to 0x1FE | |
uint8_t s = sum & 0xFF; // Ignore the carry out of the top bit (mod 256) | |
// Left rotate the result by 2 bits | |
return ((s << 2) | (s >> 6)) & 0xFF; | |
} | |
// Define S0 and S1 functions | |
uint8_t S0(uint8_t x, uint8_t y) { | |
return Sd(x, y, 0); | |
} | |
uint8_t S1(uint8_t x, uint8_t y) { | |
return Sd(x, y, 1); | |
} | |
// Implement the fK function as per Table 7.9 for key schedule | |
uint32_t fK(uint32_t A, uint32_t B) { | |
// Extract bytes A0, A1, A2, A3 from A | |
uint8_t A0 = (A >> 24) & 0xFF; | |
uint8_t A1 = (A >> 16) & 0xFF; | |
uint8_t A2 = (A >> 8) & 0xFF; | |
uint8_t A3 = A & 0xFF; | |
// Extract bytes B0, B1, B2, B3 from B | |
uint8_t B0 = (B >> 24) & 0xFF; | |
uint8_t B1 = (B >> 16) & 0xFF; | |
uint8_t B2 = (B >> 8) & 0xFF; | |
uint8_t B3 = B & 0xFF; | |
// Compute intermediate values | |
uint8_t t1 = A0 ^ A1; | |
uint8_t t2 = A2 ^ A3; | |
// Compute U components | |
uint8_t U1 = S1(t1, t2 ^ B0); | |
uint8_t U2 = S0(t2, U1 ^ B1); | |
uint8_t U0 = S0(A0, U1 ^ B2); | |
uint8_t U3 = S1(A3, U2 ^ B3); | |
// Combine U0, U1, U2, U3 into a 32-bit word | |
uint32_t U = ((uint32_t)U0 << 24) | ((uint32_t)U1 << 16) | ((uint32_t)U2 << 8) | U3; | |
return U; | |
} | |
// Implement the f function as per Table 7.9 for encryption | |
uint32_t f(uint32_t A, uint16_t Y) { | |
// Extract bytes A0, A1, A2, A3 from A | |
uint8_t A0 = (A >> 24) & 0xFF; | |
uint8_t A1 = (A >> 16) & 0xFF; | |
uint8_t A2 = (A >> 8) & 0xFF; | |
uint8_t A3 = A & 0xFF; | |
// Extract bytes Y0, Y1 from Y | |
uint8_t Y0 = (Y >> 8) & 0xFF; | |
uint8_t Y1 = Y & 0xFF; | |
// Compute intermediate values | |
uint8_t t1 = (A0 ^ A1) ^ Y0; | |
uint8_t t2 = (A2 ^ A3) ^ Y1; | |
// Compute output components | |
uint8_t F1 = S1(t1, t2); | |
uint8_t F2 = S0(t2, F1); | |
uint8_t F0 = S0(A0, F1); | |
uint8_t F3 = S1(A3, F2); | |
// Combine F0, F1, F2, F3 into a 32-bit word | |
uint32_t F = ((uint32_t)F0 << 24) | ((uint32_t)F1 << 16) | ((uint32_t)F2 << 8) | F3; | |
return F; | |
} | |
// Key schedule: Compute sixteen 16-bit subkeys Ki from 64-bit key K | |
void key_schedule(uint64_t K, uint16_t Ki[16]) { | |
uint32_t U[11]; // U(-2) to U(8), indices 0 to 10 | |
int i; | |
// Initialize U(-2), U(-1), U(0) | |
U[0] = 0; // U(-2) = 0 | |
U[1] = (uint32_t)(K >> 32); // U(-1) = k1...k32 (first 32 bits of K) | |
U[2] = (uint32_t)(K & 0xFFFFFFFF); // U(0) = k33...k64 (last 32 bits of K) | |
// Key extension loop | |
for (i = 1; i <= 8; i++) { | |
uint32_t temp = U[i + 1] ^ U[i - 1]; // U(i−1) ⊕ U(i−3) | |
U[i + 2] = fK(U[i], temp); // U(i) ← fK(U(i−2), temp) | |
// Extract U0, U1, U2, U3 from U[i + 2] | |
uint8_t U0 = (U[i + 2] >> 24) & 0xFF; | |
uint8_t U1 = (U[i + 2] >> 16) & 0xFF; | |
uint8_t U2 = (U[i + 2] >> 8) & 0xFF; | |
uint8_t U3 = U[i + 2] & 0xFF; | |
// Compute subkeys Ki | |
Ki[2 * i - 2] = ((uint16_t)U0 << 8) | U1; // K2i−2 = (U0, U1) | |
Ki[2 * i - 1] = ((uint16_t)U2 << 8) | U3; // K2i−1 = (U2, U3) | |
} | |
} | |
// Encryption function | |
uint64_t encrypt(uint64_t M, uint16_t Ki[16]) { | |
uint32_t L[9], R[9]; | |
int i; | |
// Divide plaintext M into ML and MR | |
uint32_t ML = (uint32_t)(M >> 32); | |
uint32_t MR = (uint32_t)(M & 0xFFFFFFFF); | |
// Step 3: XOR initial subkeys | |
L[0] = ML ^ (((uint32_t)Ki[8] << 16) | Ki[9]); // (K8, K9) | |
R[0] = MR ^ (((uint32_t)Ki[10] << 16) | Ki[11]); // (K10, K11) | |
// Step 4: R0 ← R0⊕L0 | |
R[0] = R[0] ^ L[0]; | |
// Feistel rounds | |
for (i = 1; i <= 8; i++) { | |
L[i] = R[i - 1]; | |
uint32_t temp = f(R[i - 1], Ki[i - 1]); // Ki−1 | |
R[i] = L[i - 1] ^ temp; | |
} | |
// Step 6: L8 ← L8⊕R8 | |
L[8] = L[8] ^ R[8]; | |
// Step 7: XOR final subkeys | |
R[8] = R[8] ^ (((uint32_t)Ki[12] << 16) | Ki[13]); // (K12, K13) | |
L[8] = L[8] ^ (((uint32_t)Ki[14] << 16) | Ki[15]); // (K14, K15) | |
// Step 8: C ← (R8, L8) (Note the order is exchanged) | |
uint64_t C = ((uint64_t)R[8] << 32) | L[8]; | |
return C; | |
} | |
int main() { | |
uint64_t K; // 64-bit key input | |
uint64_t M; // 64-bit plaintext input | |
uint64_t C; // 64-bit ciphertext output | |
uint16_t Ki[16]; // 16 subkeys K0 to K15 | |
int i; | |
// Example 64-bit key and plaintext (you can modify these as needed) | |
K = 0x0123456789ABCDEFULL; | |
M = 0ULL; | |
// Compute subkeys | |
key_schedule(K, Ki); | |
// Display subkeys | |
printf("Subkeys Ki:\n"); | |
for (i = 0; i < 16; i++) { | |
printf("K%d: %04X\n", i, Ki[i]); | |
} | |
printf("\n"); | |
// Encrypt plaintext | |
C = encrypt(M, Ki); | |
// Display ciphertext | |
printf("Plaintext M: %016llX\n", M); | |
printf("Ciphertext C: %016llX\n", C); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// FEAL-N Block Cipher | |
// | |
#include <stdio.h> | |
#include <stdint.h> | |
#include <stdlib.h> | |
// Define the Sd function as per equation (7.6) | |
uint8_t Sd(uint8_t x, uint8_t y, uint8_t d) { | |
uint16_t sum = x + y + d; // Sum could be up to 0x1FE | |
uint8_t s = sum & 0xFF; // Ignore the carry out of the top bit (mod 256) | |
// Left rotate the result by 2 bits | |
return ((s << 2) | (s >> 6)) & 0xFF; | |
} | |
// Define S0 and S1 functions | |
uint8_t S0(uint8_t x, uint8_t y) { | |
return Sd(x, y, 0); | |
} | |
uint8_t S1(uint8_t x, uint8_t y) { | |
return Sd(x, y, 1); | |
} | |
// Implement the fK function as per Table 7.9 for key schedule | |
uint32_t fK(uint32_t A, uint32_t B) { | |
// Extract bytes A0, A1, A2, A3 from A | |
uint8_t A0 = (A >> 24) & 0xFF; | |
uint8_t A1 = (A >> 16) & 0xFF; | |
uint8_t A2 = (A >> 8) & 0xFF; | |
uint8_t A3 = A & 0xFF; | |
// Extract bytes B0, B1, B2, B3 from B | |
uint8_t B0 = (B >> 24) & 0xFF; | |
uint8_t B1 = (B >> 16) & 0xFF; | |
uint8_t B2 = (B >> 8) & 0xFF; | |
uint8_t B3 = B & 0xFF; | |
// Compute intermediate values | |
uint8_t t1 = A0 ^ A1; | |
uint8_t t2 = A2 ^ A3; | |
// Compute U components | |
uint8_t U1 = S1(t1, t2 ^ B0); | |
uint8_t U2 = S0(t2, U1 ^ B1); | |
uint8_t U0 = S0(A0, U1 ^ B2); | |
uint8_t U3 = S1(A3, U2 ^ B3); | |
// Combine U0, U1, U2, U3 into a 32-bit word | |
uint32_t U = ((uint32_t)U0 << 24) | ((uint32_t)U1 << 16) | ((uint32_t)U2 << 8) | U3; | |
return U; | |
} | |
// Implement the f function as per Table 7.9 for encryption | |
uint32_t f(uint32_t A, uint16_t Y) { | |
// Extract bytes A0, A1, A2, A3 from A | |
uint8_t A0 = (A >> 24) & 0xFF; | |
uint8_t A1 = (A >> 16) & 0xFF; | |
uint8_t A2 = (A >> 8) & 0xFF; | |
uint8_t A3 = A & 0xFF; | |
// Extract bytes Y0, Y1 from Y | |
uint8_t Y0 = (Y >> 8) & 0xFF; | |
uint8_t Y1 = Y & 0xFF; | |
// Compute intermediate values | |
uint8_t t1 = (A0 ^ A1) ^ Y0; | |
uint8_t t2 = (A2 ^ A3) ^ Y1; | |
// Compute output components | |
uint8_t F1 = S1(t1, t2); | |
uint8_t F2 = S0(t2, F1); | |
uint8_t F0 = S0(A0, F1); | |
uint8_t F3 = S1(A3, F2); | |
// Combine F0, F1, F2, F3 into a 32-bit word | |
uint32_t F = ((uint32_t)F0 << 24) | ((uint32_t)F1 << 16) | ((uint32_t)F2 << 8) | F3; | |
return F; | |
} | |
// Key schedule: Compute N + 8 sixteen-bit subkeys Ki from 64-bit key K | |
void key_schedule(uint64_t K, uint16_t *Ki, int N) { | |
int total_subkeys = N + 8; | |
int num_U_values = (N / 2) + 4 + 2; // U(-2) to U((N/2)+3) | |
uint32_t *U = malloc(num_U_values * sizeof(uint32_t)); // Dynamic allocation for U array | |
int i; | |
// Initialize U(-2), U(-1), U(0) | |
U[0] = 0; // U(-2) = 0 | |
U[1] = (uint32_t)(K >> 32); // U(-1) = k1...k32 (first 32 bits of K) | |
U[2] = (uint32_t)(K & 0xFFFFFFFF); // U(0) = k33...k64 (last 32 bits of K) | |
// Key extension loop | |
for (i = 1; i <= (N / 2) + 4; i++) { | |
uint32_t temp = U[i + 1] ^ U[i - 1]; // U(i−1) ⊕ U(i−3) | |
U[i + 2] = fK(U[i], temp); // U(i) ← fK(U(i−2), temp) | |
// Extract U0, U1, U2, U3 from U[i + 2] | |
uint8_t U0 = (U[i + 2] >> 24) & 0xFF; | |
uint8_t U1 = (U[i + 2] >> 16) & 0xFF; | |
uint8_t U2 = (U[i + 2] >> 8) & 0xFF; | |
uint8_t U3 = U[i + 2] & 0xFF; | |
// Compute subkeys Ki | |
Ki[2 * i - 2] = ((uint16_t)U0 << 8) | U1; // K2i−2 = (U0, U1) | |
Ki[2 * i - 1] = ((uint16_t)U2 << 8) | U3; // K2i−1 = (U2, U3) | |
} | |
free(U); | |
} | |
// Encryption function for FEAL-N | |
uint64_t encrypt(uint64_t M, uint16_t *Ki, int N) { | |
uint32_t *L = malloc((N + 1) * sizeof(uint32_t)); | |
uint32_t *R = malloc((N + 1) * sizeof(uint32_t)); | |
int i; | |
// Divide plaintext M into ML and MR | |
uint32_t ML = (uint32_t)(M >> 32); | |
uint32_t MR = (uint32_t)(M & 0xFFFFFFFF); | |
// Step 3: XOR initial subkeys | |
L[0] = ML ^ (((uint32_t)Ki[N] << 16) | Ki[N + 1]); // (KN, KN+1) | |
R[0] = MR ^ (((uint32_t)Ki[N + 2] << 16) | Ki[N + 3]); // (KN+2, KN+3) | |
// Step 4: R0 ← R0⊕L0 | |
R[0] = R[0] ^ L[0]; | |
// Feistel rounds | |
for (i = 1; i <= N; i++) { | |
L[i] = R[i - 1]; | |
uint32_t temp = f(R[i - 1], Ki[i - 1]); // Ki−1 | |
R[i] = L[i - 1] ^ temp; | |
} | |
// Step 6: L_N ← L_N⊕R_N | |
L[N] = L[N] ^ R[N]; | |
// Step 7: XOR final subkeys | |
R[N] = R[N] ^ (((uint32_t)Ki[N + 4] << 16) | Ki[N + 5]); // (KN+4, KN+5) | |
L[N] = L[N] ^ (((uint32_t)Ki[N + 6] << 16) | Ki[N + 7]); // (KN+6, KN+7) | |
// Step 8: C ← (R_N, L_N) (Note the order is exchanged) | |
uint64_t C = ((uint64_t)R[N] << 32) | L[N]; | |
free(L); | |
free(R); | |
return C; | |
} | |
int main() { | |
uint64_t K; // 64-bit key input | |
uint64_t M; // 64-bit plaintext input | |
uint64_t C; // 64-bit ciphertext output | |
uint16_t *Ki; // Subkeys Ki | |
int i; | |
int N; // Number of rounds | |
// Set the number of rounds (must be even) | |
N = 8; // Example: FEAL-16 | |
// Calculate the total number of subkeys needed | |
int total_subkeys = N + 8; | |
// Allocate memory for subkeys | |
Ki = malloc(total_subkeys * sizeof(uint16_t)); | |
// Example 64-bit key and plaintext (you can modify these as needed) | |
K = 0x0123456789ABCDEFULL; | |
M = 0ULL; | |
// Compute subkeys | |
key_schedule(K, Ki, N); | |
// Display subkeys | |
printf("Subkeys Ki:\n"); | |
for (i = 0; i < total_subkeys; i++) { | |
printf("K%d: %04X\n", i, Ki[i]); | |
} | |
printf("\n"); | |
// Encrypt plaintext | |
C = encrypt(M, Ki, N); | |
// Display plaintext and ciphertext | |
printf("Plaintext M: %016llX\n", M); | |
printf("Ciphertext C: %016llX\n", C); | |
// Clean up | |
free(Ki); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// FEAL-NX Block Cipher | |
// | |
#include <stdio.h> | |
#include <stdint.h> | |
#include <stdlib.h> | |
// Define the Sd function as per equation (7.6) | |
uint8_t Sd(uint8_t x, uint8_t y, uint8_t d) { | |
uint16_t sum = x + y + d; // Sum could be up to 0x1FE | |
uint8_t s = sum & 0xFF; // Ignore the carry out of the top bit (mod 256) | |
// Left rotate the result by 2 bits | |
return ((s << 2) | (s >> 6)) & 0xFF; | |
} | |
// Define S0 and S1 functions | |
uint8_t S0(uint8_t x, uint8_t y) { | |
return Sd(x, y, 0); | |
} | |
uint8_t S1(uint8_t x, uint8_t y) { | |
return Sd(x, y, 1); | |
} | |
// Implement the fK function as per Table 7.9 for key schedule | |
uint32_t fK(uint32_t A, uint32_t B) { | |
// Extract bytes A0, A1, A2, A3 from A | |
uint8_t A0 = (A >> 24) & 0xFF; | |
uint8_t A1 = (A >> 16) & 0xFF; | |
uint8_t A2 = (A >> 8) & 0xFF; | |
uint8_t A3 = A & 0xFF; | |
// Extract bytes B0, B1, B2, B3 from B | |
uint8_t B0 = (B >> 24) & 0xFF; | |
uint8_t B1 = (B >> 16) & 0xFF; | |
uint8_t B2 = (B >> 8) & 0xFF; | |
uint8_t B3 = B & 0xFF; | |
// Compute intermediate values | |
uint8_t t1 = A0 ^ A1; | |
uint8_t t2 = A2 ^ A3; | |
// Compute U components | |
uint8_t U1 = S1(t1, t2 ^ B0); | |
uint8_t U2 = S0(t2, U1 ^ B1); | |
uint8_t U0 = S0(A0, U1 ^ B2); | |
uint8_t U3 = S1(A3, U2 ^ B3); | |
// Combine U0, U1, U2, U3 into a 32-bit word | |
uint32_t U = ((uint32_t)U0 << 24) | ((uint32_t)U1 << 16) | ((uint32_t)U2 << 8) | U3; | |
return U; | |
} | |
// Implement the f function as per Table 7.9 for encryption | |
uint32_t f(uint32_t A, uint16_t Y) { | |
// Extract bytes A0, A1, A2, A3 from A | |
uint8_t A0 = (A >> 24) & 0xFF; | |
uint8_t A1 = (A >> 16) & 0xFF; | |
uint8_t A2 = (A >> 8) & 0xFF; | |
uint8_t A3 = A & 0xFF; | |
// Extract bytes Y0, Y1 from Y | |
uint8_t Y0 = (Y >> 8) & 0xFF; | |
uint8_t Y1 = Y & 0xFF; | |
// Compute intermediate values | |
uint8_t t1 = (A0 ^ A1) ^ Y0; | |
uint8_t t2 = (A2 ^ A3) ^ Y1; | |
// Compute output components | |
uint8_t F1 = S1(t1, t2); | |
uint8_t F2 = S0(t2, F1); | |
uint8_t F0 = S0(A0, F1); | |
uint8_t F3 = S1(A3, F2); | |
// Combine F0, F1, F2, F3 into a 32-bit word | |
uint32_t F = ((uint32_t)F0 << 24) | ((uint32_t)F1 << 16) | ((uint32_t)F2 << 8) | F3; | |
return F; | |
} | |
// Key schedule for FEAL-NX: Compute N + 8 sixteen-bit subkeys Ki from 128-bit key K | |
void key_schedule(uint64_t KL, uint64_t KR, uint16_t *Ki, int N) { | |
int total_subkeys = N + 8; | |
int num_U_values = (N / 2) + 4 + 2; // U(-2) to U((N/2)+3) | |
uint32_t *U = malloc(num_U_values * sizeof(uint32_t)); // Dynamic allocation for U array | |
int i; | |
// Split KR into KR1 and KR2 | |
uint32_t KR1 = (uint32_t)(KR >> 32); | |
uint32_t KR2 = (uint32_t)(KR & 0xFFFFFFFF); | |
// Initialize U(-2), U(-1), U(0) | |
U[0] = 0; // U(-2) = 0 | |
U[1] = (uint32_t)(KL >> 32); // U(-1) = KL high 32 bits | |
U[2] = (uint32_t)(KL & 0xFFFFFFFF); // U(0) = KL low 32 bits | |
// Key extension loop | |
for (i = 1; i <= (N / 2) + 4; i++) { | |
uint32_t Qi; | |
// Define Qi based on i mod 3 | |
if (i % 3 == 1) { | |
Qi = KR1 ^ KR2; | |
} else if (i % 3 == 2) { | |
Qi = KR1; | |
} else { // i % 3 == 0 | |
Qi = KR2; | |
} | |
uint32_t temp = U[i + 1] ^ U[i - 1] ^ Qi; // Modified with Qi | |
U[i + 2] = fK(U[i], temp); // U(i) ← fK(U(i−2), temp) | |
// Extract U0, U1, U2, U3 from U[i + 2] | |
uint8_t U0 = (U[i + 2] >> 24) & 0xFF; | |
uint8_t U1 = (U[i + 2] >> 16) & 0xFF; | |
uint8_t U2 = (U[i + 2] >> 8) & 0xFF; | |
uint8_t U3 = U[i + 2] & 0xFF; | |
// Compute subkeys Ki | |
Ki[2 * i - 2] = ((uint16_t)U0 << 8) | U1; // K2i−2 = (U0, U1) | |
Ki[2 * i - 1] = ((uint16_t)U2 << 8) | U3; // K2i−1 = (U2, U3) | |
} | |
free(U); | |
} | |
// Encryption function for FEAL-NX | |
uint64_t encrypt(uint64_t M, uint16_t *Ki, int N) { | |
uint32_t *L = malloc((N + 1) * sizeof(uint32_t)); | |
uint32_t *R = malloc((N + 1) * sizeof(uint32_t)); | |
int i; | |
// Divide plaintext M into ML and MR | |
uint32_t ML = (uint32_t)(M >> 32); | |
uint32_t MR = (uint32_t)(M & 0xFFFFFFFF); | |
// Step 3: XOR initial subkeys | |
L[0] = ML ^ (((uint32_t)Ki[N] << 16) | Ki[N + 1]); // (KN, KN+1) | |
R[0] = MR ^ (((uint32_t)Ki[N + 2] << 16) | Ki[N + 3]); // (KN+2, KN+3) | |
// Step 4: R0 ← R0⊕L0 | |
R[0] = R[0] ^ L[0]; | |
// Feistel rounds | |
for (i = 1; i <= N; i++) { | |
L[i] = R[i - 1]; | |
uint32_t temp = f(R[i - 1], Ki[i - 1]); // Ki−1 | |
R[i] = L[i - 1] ^ temp; | |
} | |
// Step 6: L_N ← L_N⊕R_N | |
L[N] = L[N] ^ R[N]; | |
// Step 7: XOR final subkeys | |
R[N] = R[N] ^ (((uint32_t)Ki[N + 4] << 16) | Ki[N + 5]); // (KN+4, KN+5) | |
L[N] = L[N] ^ (((uint32_t)Ki[N + 6] << 16) | Ki[N + 7]); // (KN+6, KN+7) | |
// Step 8: C ← (R_N, L_N) (Note the order is exchanged) | |
uint64_t C = ((uint64_t)R[N] << 32) | L[N]; | |
free(L); | |
free(R); | |
return C; | |
} | |
int main() { | |
uint64_t KL; // Left 64 bits of the 128-bit key | |
uint64_t KR; // Right 64 bits of the 128-bit key | |
uint64_t M; // 64-bit plaintext input | |
uint64_t C; // 64-bit ciphertext output | |
uint16_t *Ki; // Subkeys Ki | |
int i; | |
int N; // Number of rounds | |
// Set the number of rounds (must be even) | |
N = 32; // Example: FEAL-NX with N = 16 | |
// Calculate the total number of subkeys needed | |
int total_subkeys = N + 8; | |
// Allocate memory for subkeys | |
Ki = malloc(total_subkeys * sizeof(uint16_t)); | |
// Example 128-bit key and plaintext (you can modify these as needed) | |
KL = 0x0123456789ABCDEFULL; | |
KR = 0x0123456789ABCDEFULL; | |
M = 0; | |
// Compute subkeys | |
key_schedule(KL, KR, Ki, N); | |
// Display subkeys | |
printf("Subkeys Ki:\n"); | |
for (i = 0; i < total_subkeys; i++) { | |
printf("K%d: %04X\n", i, Ki[i]); | |
} | |
printf("\n"); | |
// Encrypt plaintext | |
C = encrypt(M, Ki, N); | |
// Display plaintext and ciphertext | |
printf("Plaintext M: %016llX\n", M); | |
printf("Ciphertext C: %016llX\n", C); | |
// Clean up | |
free(Ki); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment