使用Vitis HLS实现和优化SPECK加解密函数
设计代码如下:
// speck_hls.cpp #include "ap_int.h" // 定义密钥和回合数 #define WORD_SIZE 16 #define KEY_SIZE 4 #define NUM_ROUNDS 22 typedef ap_uint<WORD_SIZE> half_word; typedef ap_uint<WORD_SIZE*2> word; typedef ap_uint<WORD_SIZE*4> key_type; // 定义流水线节拍 #define PIPELINE_II 1 // SPECK加密算法 void speck_encrypt(word plaintext, word* ciphertext, const half_word key_schedule[NUM_ROUNDS]) { half_word left = plaintext(WORD_SIZE*2-1, WORD_SIZE); half_word right = plaintext(WORD_SIZE-1, 0); SPECK_ENCRYPT_LOOP: for (int i = 0; i < NUM_ROUNDS; i++) { #pragma HLS PIPELINE II=PIPELINE_II left = (right + left) % (1 << WORD_SIZE); left ^= key_schedule[i]; right = (right >> 7) | (right << (WORD_SIZE - 7)); right ^= left; } *ciphertext = (left, right); } // SPECK解密算法 void speck_decrypt(word ciphertext, word* plaintext, const half_word key_schedule[NUM_ROUNDS]) { half_word left = ciphertext(WORD_SIZE*2-1, WORD_SIZE); half_word right = ciphertext(WORD_SIZE-1, 0); SPECK_DECRYPT_LOOP: for (int i = NUM_ROUNDS-1; i >= 0; i--) { #pragma HLS PIPELINE II=PIPELINE_II right ^= left; right = (right << 7) | (right >> (WORD_SIZE - 7)); left ^= key_schedule[i]; left = (left - right) % (1 << WORD_SIZE); } *plaintext = (left, right); } // 密钥扩展 void key_expansion(const key_type key, half_word key_schedule[NUM_ROUNDS]) { half_word l[NUM_ROUNDS]; half_word k = key(KEY_SIZE*WORD_SIZE-1, (KEY_SIZE-1)*WORD_SIZE); l[0] = key((KEY_SIZE-2)*WORD_SIZE-1, (KEY_SIZE-3)*WORD_SIZE); key_schedule[0] = k; KEY_EXPANSION_LOOP: for (int i = 0; i < NUM_ROUNDS-1; i++) { #pragma HLS PIPELINE II=PIPELINE_II l[i+1] = (k + l[i]) % (1 << WORD_SIZE); l[i+1] ^= i; k = (k >> 7) | (k << (WORD_SIZE - 7)); k ^= l[i+1]; key_schedule[i+1] = k; } } // 重构的顶层函数 void speck(word plaintext, word* ciphertext, word* decrypted_text, const key_type key) { #pragma HLS INTERFACE s_axilite port=return #pragma HLS INTERFACE s_axilite port=plaintext #pragma HLS INTERFACE s_axilite port=ciphertext #pragma HLS INTERFACE s_axilite port=decrypted_text #pragma HLS INTERFACE s_axilite port=key half_word key_schedule[NUM_ROUNDS]; // Key schedule calculation key_expansion(key, key_schedule); // 加密和解密操作 word ciphertext_internal; word decrypted_text_internal; speck_encrypt(plaintext, &ciphertext_internal, key_schedule); speck_decrypt(ciphertext_internal, &decrypted_text_internal, key_schedule); // 将结果写入输出 *ciphertext = ciphertext_internal; *decrypted_text = decrypted_text_internal; }
测试代码如下:
// test_speck_hls.cpp #include <iostream> #include <stdio.h> #include "ap_int.h" #define WORD_SIZE 16 #define KEY_SIZE 4 #define NUM_ROUNDS 22 typedef ap_uint<WORD_SIZE> half_word; typedef ap_uint<WORD_SIZE*2> word; typedef ap_uint<WORD_SIZE*4> key_type; void speck(word plaintext, word* ciphertext, word* decrypted_text, const key_type key); // 自动化测试函数 bool run_test(word plaintext, const key_type key) { word ciphertext; word decrypted_text; // 调用SPECK函数进行加密和解密 speck(plaintext, &ciphertext, &decrypted_text, key); // 检查解密结果是否与原始明文匹配 return (plaintext == decrypted_text); } int main() { // 测试数据 word plaintexts[] = {0x6574694c, 0x12345678, 0xABCDEF01, 0x0FEDCBA9}; key_type keys[] = {0x1918111009080100, 0x1A1B1C1D0E0F1011, 0x2021222324252627, 0x1314151607181920}; int num_tests = sizeof(plaintexts) / sizeof(plaintexts[0]); // 记录通过和失败的测试数量 int passed_tests = 0; int failed_tests = 0; // 测试每组明文和密钥 for (int i = 0; i < num_tests; i++) { bool result = run_test(plaintexts[i], keys[i]); if (result) { passed_tests++; printf("Test %d passed\n", i+1); } else { failed_tests++; printf("Test %d failed\n", i+1); } } printf("Total tests passed: %d\n", passed_tests); printf("Total tests failed: %d\n", failed_tests); return 0; }
编译结果: