轻量级加密算法PRESENT:C++实现与硬件效率深度解析
1. 项目概述为什么我们需要关注PRESENT算法如果你是一名嵌入式开发者、物联网安全工程师或者对密码学在资源受限环境下的实现感兴趣那么“轻量级加密”这个词对你来说一定不陌生。在智能门锁、可穿戴设备、工业传感器这些计算能力弱、存储空间小、电池续航要求高的场景里传统的AES高级加密标准算法有时会显得“大材小用”甚至“力不从心”。它带来的计算开销和功耗可能会成为产品设计的瓶颈。这时PRESENT算法就走进了我们的视野。它诞生于2007年的CHES加密硬件与嵌入式系统国际会议目标非常明确为极度受限的硬件环境提供一个安全、高效的加密解决方案。它后来成为了ISO/IEC 29192标准的一部分这足以证明其在轻量级密码学领域的标杆地位。简单来说PRESENT就是为了在“螺蛳壳里做道场”用极少的逻辑门Gate Equivalent, GE和时钟周期实现可靠的加密保护。我之所以花时间深入研究并用C实现它是因为在实际项目中我遇到过太多需要在MCU微控制器上实现安全功能的需求。直接套用AES库有时会发现ROM或RAM占用超标或者加密延迟影响了实时性。PRESENT提供了一个经过学术界和工业界多年检验的、更“经济”的选择。本文将带你从零开始理解PRESENT的核心原理用C实现一个清晰的版本并深入剖析其硬件效率背后的设计哲学让你不仅能“跑通代码”更能“吃透设计”。2. PRESENT算法核心原理深度拆解要高效地实现一个算法死记硬背流程是不够的必须理解其设计者每一个决策背后的意图。PRESENT的设计充满了智慧其核心思想是在保证安全性的前提下追求极致的硬件友好性。2.1 算法参数与总体结构PRESENT是一个典型的SPNSubstitution-Permutation Network替代-置换网络结构的分组密码。这种结构清晰、规整非常适合硬件并行化实现。分组长度Block Size64位。这意味着它一次加密或解密64位8字节的明文或密文。相比AES-128的128位分组它更短处理起来自然更快、更省资源。密钥长度Key Size支持80位和128位两种。80位版本是更经典、更轻量的选择本文实现将以80位密钥为例。128位版本提供了更高的安全余量。加密轮数Rounds31轮。这是一个经过安全性分析后确定的数字确保了算法能够抵抗已知的各种密码分析攻击。其加密过程可以概括为一个31次的循环每轮包含三个核心操作addRoundKey轮密钥加、sBoxLayerS盒层、pLayerP置换层。在最后一轮后会再进行一次轮密钥加操作。解密过程则是其逆过程。2.2 轮函数Round Function的三驾马车轮函数是PRESENT每一轮加密的核心理解它就理解了算法的筋骨。2.2.1 轮密钥加addRoundKey这是最简单的一步将64位的中间状态state与当前轮的64位轮密钥roundKey进行按位异或XOR操作。state state ^ roundKey;在硬件上异或门是非常基础且廉价的逻辑单元。这一步为算法注入了密钥材料是混淆的关键。2.2.2 S盒替换sBoxLayer这是算法提供“混淆”Confusion能力的主要来源。PRESENT使用一个4位输入、4位输出的S盒Substitution-box。它将64位的状态视为16个4位nibble的数据块每个数据块独立地通过这个S盒进行非线性替换。PRESENT的S盒是精心设计的其布尔表达式和差分/线性性质都经过优化以抵抗密码分析。其替换表如下输入十六进制0123456789ABCDEF输出十六进制C56B90AD3EF84712实操心得在软件实现中我们可以直接用这个16元素的查找表LUT来实现速度极快。在硬件描述语言如Verilog中也可以直接实例化这个查找表或者用组合逻辑实现其布尔表达式后者面积更优。2.2.3 P比特置换pLayer这是算法提供“扩散”Diffusion能力的主要来源。经过S盒混淆后数据位之间的关系还是局部的 within each nibble。P置换的作用是将这些位彻底“打散”让一个S盒输出的影响尽可能快地扩散到整个状态的不同位置。PRESENT的P置换规则非常简洁优雅对于状态的第i位i从0到63它将被移动到第P(i)位。其映射函数为P(i) (i * 16) mod 63 对于i 0...62P(63) 63这意味着第0位不动第1位移动到第16位第2位移动到第32位第3位移动到第48位第4位移动到第1位以此类推。你可以把它想象成一个精心设计的“洗牌”动作。设计精妙之处这个置换是比特级的而不是字节或半字节级的。它能在单轮内实现极高的扩散率。更重要的是它在硬件上的实现成本几乎为零因为它只是 wires 的重新连接不需要任何逻辑门。这是PRESENT硬件效率高的一个关键原因。2.3 密钥编排Key Schedule密钥编排算法负责从初始的80位主密钥生成31轮加密所需的64位轮密钥。对于80位密钥版本PRESENT-80其过程同样体现了硬件友好性。提取高64位当前轮密钥就是当前密钥寄存器keyRegister的高64位。密钥寄存器更新 a.循环左移61位keyRegister keyRegister 61。这是一个非常大幅度的移位确保了密钥材料的充分混合。 b.S盒替换将移位后keyRegister的高4位bits 79..76通过S盒进行替换。 c.轮常数异或将keyRegister的第19到第15位bits 19..15与一个5位的轮计数器round_counter进行异或。轮计数器从1开始每轮递增。这个过程在硬件上只需要一个移位寄存器、一个S盒实例和几个异或门非常节约。注意事项在软件实现中61位的循环移位需要小心处理因为C标准没有提供对大于数据类型宽度的循环移位直接支持。我们需要自己用位操作组合实现。3. C实现详解从理论到可运行代码理解了原理我们开始动手实现。我们的目标是写一个清晰、可读、便于学习和集成的C实现同时兼顾效率。我们将采用面向过程式的函数设计方便理解数据流。3.1 基础类型与常量定义首先我们定义一些基础类型和常量。由于PRESENT操作的是64位和80位的数据使用固定宽度的整数类型至关重要。#include cstdint #include array // 使用固定宽度整数类型确保可移植性 typedef uint64_t block_t; // 64位数据块 typedef uint64_t key80_t; // 注意uint64_t只有64位80位密钥需要特殊处理这里先用uint64_t表示高64位低16位另存。 // PRESENT 算法常量 constexpr int BLOCK_SIZE 64; constexpr int KEY_SIZE_80 80; constexpr int ROUNDS 31; // S-Box 查找表 (4-bit - 4-bit) constexpr std::arrayuint8_t, 16 SBOX {0xC, 0x5, 0x6, 0xB, 0x9, 0x0, 0xA, 0xD, 0x3, 0xE, 0xF, 0x8, 0x4, 0x7, 0x1, 0x2}; // 逆S-Box用于解密 constexpr std::arrayuint8_t, 16 SBOX_INV {0x5, 0xE, 0xF, 0x8, 0xC, 0x1, 0x2, 0xD, 0xB, 0x4, 0x6, 0x3, 0x0, 0x7, 0x9, 0xA};这里有一个关键点C标准库没有80位整数类型。我们需要用两个变量来模拟例如一个uint64_t存高64位一个uint16_t存低16位。为了代码清晰我们可以定义一个简单的结构体。3.2 核心功能函数实现3.2.1 S盒层与逆S盒层block_t sBoxLayer(block_t state, const std::arrayuint8_t, 16 sbox) { block_t output 0; for (int i 0; i 16; i) { // 依次提取每个4位片段 uint8_t nibble (state (i * 4)) 0xF; // 通过S盒替换 uint8_t substituted sbox[nibble]; // 放回原位 output | (static_castblock_t(substituted) (i * 4)); } return output; }逆S盒层函数sBoxLayerInv实现完全一样只是传入SBOX_INV表。3.2.2 P置换层与逆P置换层这是算法的精髓也是硬件零成本的关键。软件实现需要按位映射。block_t pLayer(block_t state) { block_t output 0; for (int i 0; i BLOCK_SIZE; i) { // 获取原状态第i位的值 (0 或 1) uint64_t bit (state i) 0x1; // 计算该位应该移动到的新位置 P(i) int new_pos; if (i BLOCK_SIZE - 1) { new_pos BLOCK_SIZE - 1; // P(63) 63 } else { new_pos (i * 16) % (BLOCK_SIZE - 1); } // 将这一位设置到新位置 output | (bit new_pos); } return output; }逆置换pLayerInv的逻辑是反过来的对于新状态的第j位找到是原来的哪一位i移动过来的。其映射关系为对于j 0...62, 找到i使得(i * 16) mod 63 jP_inv(63) 63。实现时可以预先计算一个逆置换表或者像下面这样逆向推导block_t pLayerInv(block_t state) { block_t output 0; for (int j 0; j BLOCK_SIZE; j) { uint64_t bit (state j) 0x1; int original_pos; if (j BLOCK_SIZE - 1) { original_pos BLOCK_SIZE - 1; } else { // 寻找满足 (i*16) % 63 j 的 i // 因为16在模63下有乘法逆元16 * 4 64 ≡ 1 mod 63所以 i j * 4 mod 63 original_pos (j * 4) % (BLOCK_SIZE - 1); } output | (bit original_pos); } return output; }性能提示在性能敏感的软件实现中pLayer和pLayerInv可以通过预先计算好的64x64的位映射表uint64_t数组来实现用一次查表和移位操作完成整个置换这比循环64次要快得多。但为了代码清晰和教学目的这里展示了位循环的版本。3.2.3 密钥编排80位版本这是实现中最容易出错的部分因为涉及80位数据的操作。// 用一个结构体表示80位密钥 struct Key80 { uint64_t high; // 高64位 uint16_t low; // 低16位 }; // 从80位密钥结构中提取当前64位轮密钥 block_t getRoundKey(const Key80 key) { // 轮密钥是密钥的高64位 return key.high; } // 更新80位密钥状态以生成下一轮密钥 void updateKeyForNextRound(Key80 key, int round_counter) { // 1. 循环左移61位 // 将80位视为一个整体高64位和低16位 uint64_t all_high key.high; uint16_t all_low key.low; // 合并成一个逻辑上的80位数进行61位左移 // 61位左移相当于高64位左移61位其溢出的部分高3位移到低16位的高位低16位左移61位相当于左移(61-6480)77位 // 更清晰的方法分两部分处理 // 左移61位相当于整个80位数组向左移动61个bit。 // 我们可以计算移动后高低位的新值 // 原 key [high(64位)][low(16位)] // 左移61位后原 high 的 高61位 移出低3位成为新 low 的高3位。 // 原 low 左移61位在80位空间内其高(61- (64-原high移出的位数))... 这个方法很绕。 // **更实用的软件实现方法**使用位数组或两个64位变量来模拟。 // 这里采用一种直观但非最优的方法将80位展开到一个10字节的数组中进行移位。 std::arrayuint8_t, 10 key_bytes{}; // 将key.high和key.low填充到key_bytes中 (小端序) for (int i 0; i 8; i) { key_bytes[i] (key.high (i * 8)) 0xFF; } key_bytes[8] key.low 0xFF; key_bytes[9] (key.low 8) 0xFF; // 循环左移61位对80位10字节 // 左移61位 移动7个完整字节(7*856位) 额外的5位 const int shift_bits 61; const int shift_bytes shift_bits / 8; // 7 const int shift_bits_in_byte shift_bits % 8; // 5 std::arrayuint8_t, 10 temp{}; for (int i 0; i 10; i) { int src_byte_idx (i shift_bytes) % 10; int src_bit_idx (i shift_bytes 1) % 10; // 为了获取下一个字节的低位来补位 uint16_t combined (key_bytes[src_byte_idx] 8) | key_bytes[src_bit_idx]; temp[i] (combined (8 - shift_bits_in_byte)) 0xFF; } key_bytes temp; // 将移位后的字节数组写回key.high和key.low key.high 0; for (int i 0; i 8; i) { key.high | (static_castuint64_t(key_bytes[i]) (i * 8)); } key.low static_castuint16_t(key_bytes[8]) | (static_castuint16_t(key_bytes[9]) 8); // 2. 将 key_bytes[0] 的高4位即现在80位密钥的最高4位通过S盒 uint8_t high_nibble (key_bytes[0] 4) 0xF; // 获取高4位 uint8_t substituted SBOX[high_nibble]; key_bytes[0] (key_bytes[0] 0x0F) | (substituted 4); // 替换高4位 // 3. 轮常数异或异或 key_bytes[4] 的低5位 (对应原描述的第19-15位) // 在10字节数组中第19-15位位于 // bit 15-8: key_bytes[1]? 需要仔细计算。 // 更准确的方法80位中bits 19-15 是第4个字节从0开始的低5位和第3个字节的最高3位让我们重新定位。 // 实际上在论文描述中是与 key[19:15] 异或。在我们10字节80位数组 key_bytes[9]...key_bytes[0] (假设key_bytes[9]是最高字节)中 // bit 79 (最高) 在 key_bytes[9]的bit7, bit 0在 key_bytes[0]的bit0。 // bits 19-15: 19/82余3, 15/81余7。所以跨越 key_bytes[2] 和 key_bytes[1]。 // 具体是 key_bytes[2]的低4位和 key_bytes[1]的最高1位这很混乱。 // **简化且正确的实现**许多开源实现采用一种更直接但等价的表述 // 将80位密钥存放在一个 uint8_t key[10] 中key[0]是最高字节。 // 循环左移61位后对 key[0] 的高4位进行S盒替换。 // 然后将 key[4] 的低5位与轮常数异或。 // 我们按照这个来并更新我们的 key_bytes 顺序令 key_bytes[0] 为最高字节。 // 上述移位操作已经是在这个约定下进行的。 // 轮常数异或 uint8_t round_const round_counter 0x1F; // 轮常数是5位 key_bytes[4] ^ round_const; // 与第4个字节从0开始异或 // 写回key结构体 key.high 0; for (int i 0; i 8; i) { key.high | (static_castuint64_t(key_bytes[i]) ((7 - i) * 8)); // 注意字节序保持一致性 } key.low (static_castuint16_t(key_bytes[8]) 8) | key_bytes[9]; }踩坑记录密钥编排的80位循环移位和位操作是软件实现中最棘手的部分。不同的实现可能对字节序高位在前还是低位在前和位序的约定不同。务必与标准测试向量对比验证。一个常见的技巧是在开发初期可以借助Python等语言的大整数特性来验证80位移位的正确性再移植到C。3.2.4 加密与解密主函数有了上面的组件加密函数就水到渠成了。block_t present_encrypt(block_t plaintext, const Key80 initial_key) { block_t state plaintext; Key80 current_key initial_key; for (int round 0; round ROUNDS; round) { // 1. addRoundKey state ^ getRoundKey(current_key); // 2. sBoxLayer state sBoxLayer(state, SBOX); // 3. pLayer state pLayer(state); // 4. 更新密钥为下一轮准备 updateKeyForNextRound(current_key, round 1); // 轮常数从1开始 } // 最后一轮后再进行一次轮密钥加 state ^ getRoundKey(current_key); return state; } block_t present_decrypt(block_t ciphertext, const Key80 initial_key) { // 解密需要先生成所有轮密钥因为过程是逆向的 std::arrayblock_t, ROUNDS 1 round_keys{}; Key80 temp_key initial_key; round_keys[0] getRoundKey(temp_key); for (int round 1; round ROUNDS; round) { updateKeyForNextRound(temp_key, round); round_keys[round] getRoundKey(temp_key); } block_t state ciphertext; // 第一轮加最后一轮密钥 state ^ round_keys[ROUNDS]; // 中间 ROUNDS-1 轮逆P层 - 逆S盒 - 加轮密钥 for (int round ROUNDS - 1; round 1; --round) { state pLayerInv(state); state sBoxLayer(state, SBOX_INV); state ^ round_keys[round]; } // 最后一轮逆P层 - 逆S盒 - 加初始轮密钥 state pLayerInv(state); state sBoxLayer(state, SBOX_INV); state ^ round_keys[0]; return state; }3.3 测试与验证实现完成后必须用标准测试向量进行验证。这是保证你的实现与算法标准一致性的唯一方法。你可以在PRESENT的原始论文或NIST的轻量级密码项目页面找到测试向量。#include iostream #include iomanip bool test_present() { // 示例测试向量 (需要替换为官方标准测试向量) Key80 test_key; test_key.high 0x0000000000000000; test_key.low 0x0000; // 80位全0密钥 block_t test_plain 0x0000000000000000; block_t expected_cipher 0x5579C1387B228445; // 这是全0密钥和全0明文加密后的一个已知结果请务必查找官方向量 block_t cipher present_encrypt(test_plain, test_key); std::cout Ciphertext: 0x std::hex std::setw(16) std::setfill(0) cipher std::endl; std::cout Expected: 0x std::hex std::setw(16) std::setfill(0) expected_cipher std::endl; if (cipher ! expected_cipher) { std::cerr Encryption test FAILED! std::endl; return false; } block_t decrypted present_decrypt(cipher, test_key); if (decrypted ! test_plain) { std::cerr Decryption test FAILED! std::endl; return false; } std::cout All tests PASSED! std::endl; return true; }4. 硬件效率解析PRESENT为何如此“轻”“轻量级”不是一个模糊的形容词在密码学中它有明确的量化指标。PRESENT的硬件效率主要体现在以下几个方面4.1 面积Area优化极简的电路设计这是PRESENT最突出的优点。在ASIC专用集成电路设计中面积直接关系到芯片成本。精简的S盒PRESENT的4位S盒布尔表达式非常简洁可以用很少的逻辑门实现大约20-30个GE。相比之下AES的8位S盒要复杂得多。零成本P置换如前所述比特置换在硬件上只是连线的重排不消耗任何逻辑门。这是SPN结构在硬件上的天然优势而AES的MixColumns操作则需要大量的异或门。紧凑的密钥编排80位版本的密钥编排主要是一个61位移位寄存器和一个S盒实例与加密轮共用额外开销极小。综合下来一个未经深度优化的PRESENT-80加密核其面积可以控制在1500 GE左右。而一个最简化的AES-128加密核面积通常在3000 GE以上。对于成本极其敏感的RFID标签、传感器节点其整个微控制器可能只有几千GE这一倍的面积差异是决定性的。4.2 功耗Power Consumption与能效Energy per Bit功耗与面积和开关活动性相关。更小的面积通常意味着更低的静态功耗。同时PRESENT算法轮数多31轮但每轮操作非常简单主要是异或和查表单次操作功耗低。在低频率下工作其动态功耗也很可观。能效是指加密每比特数据所消耗的能量。PRESENT由于其简单的操作和较短的流水线在完成一次加密31轮所需的总时钟周期和能量方面往往优于AES。这对于由电池供电、需要频繁进行加密操作的物联网设备至关重要。4.3 吞吐率Throughput与延迟Latency这是一个需要权衡的方面。高吞吐率设计可以通过流水线Pipeline实现。将31轮拆分成多个流水线阶段每个时钟周期都能输入一个新的数据块。PRESENT规整的SPN结构非常适合流水线化可以实现很高的数据吞吐率。低延迟设计如果追求一次加密的完成时间最短可以采用迭代Iterative结构即只用一套轮函数电路循环31次。这样面积最小但完成一个块加密需要31个时钟周期。PRESENT在这两种设计上都能很好地适应。下表对比了PRESENT-80与AES-128在典型硬件实现上的关键指标数据来源于相关学术论文具体数值因工艺和优化程度而异特性PRESENT-80 (迭代设计)AES-128 (迭代设计)对物联网设备的意义逻辑门数 (GE)~1,500 - 2,000~3,000 - 4,000成本更低更容易集成到微型芯片中。功耗 (μW/MHz)较低 (具体值依赖工艺)较高更长的电池寿命适合常年部署的设备。吞吐率 (Mbps 100kHz)约 0.2 Mbps (31周期/块)约 0.1 Mbps (更高轮数/更复杂轮函数)满足多数传感数据加密的带宽需求。最大频率 (MHz)通常很高逻辑深度浅受S盒和列混合路径限制可以在较低的电压和频率下工作以节能。4.4 与软件效率的关联硬件效率高的设计在软件尤其是嵌入式C语言实现上往往也有优势查找表小4位S盒的查找表只有16字节能完美放入CPU缓存访问速度极快。AES的S盒是256字节。操作规整比特置换虽然软件实现需要位操作但算法规整没有条件分支有利于CPU的流水线执行和编译优化。数据局部性好整个算法处理64位块在现代64位CPU上可以很好地利用寄存器。当然在拥有AES-NI指令集加速的现代x86 CPU上AES会快得多。但在没有硬件加速的ARM Cortex-M系列MCU上一个优化良好的PRESENT软件实现其速度和代码大小常常能与AES媲美甚至更优。5. 实战应用考量与常见问题将PRESENT集成到真实项目中除了跑通测试向量还需要考虑更多工程问题。5.1 工作模式Mode of OperationPRESENT和AES一样是分组密码不能直接加密任意长度的消息。必须结合工作模式使用如ECB、CBC、CTR、GCM等。ECB电子密码本最简单但不安全相同的明文块会产生相同的密文块会暴露数据模式。绝不应用于加密有意义的数据。CBC密码块链接需要初始化向量IV提供了更好的安全性但加密是串行的不利于并行。CTR计数器将分组密码变为流密码。可以并行加密非常适合硬件实现。需要保证计数器永不重复。针对轻量级的模式如OCB、CLOC、SILC等认证加密模式也有轻量级变体可以在提供机密性的同时提供完整性和认证。选择建议对于物联网传感数据流CTR模式通常是很好的选择因为它无填充、可并行、可随机访问。如果还需要认证可以查阅轻量级的认证加密模式。5.2 侧信道攻击Side-Channel Attacks防护PRESENT和其他密码一样在物理设备上运行时可能通过功耗、电磁辐射、时间等信息泄露密钥。这对于硬件实现尤其重要。功耗分析DPA/SPA简单的软件实现和硬件电路容易受到攻击。防护措施包括掩码Masking在算法执行过程中用随机数对中间状态进行隐藏。隐藏Hiding通过随机化操作顺序或插入伪操作使功耗轨迹与密钥的相关性降低。故障攻击通过注入故障如电压毛刺、时钟抖动来产生错误的输出从而分析密钥。需要增加冗余计算或校验机制。在资源允许的情况下如果安全性要求极高需要考虑实现这些防护措施但这会显著增加面积和功耗。5.3 常见实现陷阱与调试技巧字节序Endianness问题算法标准通常定义的是比特和字节的顺序。你的测试向量是十六进制字符串在代码中赋值给uint64_t时要明确你的系统是大端序还是小端序。不一致会导致加密结果错误。一个可靠的方法是统一将输入输出视为字节数组并按照标准文档规定的字节顺序进行处理。80位密钥处理这是最大的坑。确保你的循环移位、S盒替换、轮常数异或操作精确地作用在正确的位上。使用官方测试向量并逐轮对比中间密钥状态是调试的唯一途径。逆算法验证加解密测试必须成对进行。用随机生成的明文和密钥进行大量如10万次加解密循环验证解密后是否与原始明文一致。性能优化在确认功能正确后再考虑优化。例如将P置换预先计算成256字节的查找表因为64位中的每个字节的置换是固定的可以大幅提升软件速度。5.4 PRESENT的适用场景与局限性适用场景RFID/NFC标签面积和功耗是首要约束。无线传感器网络节点电池供电需要长期运行。智能卡/嵌入式SE安全元件资源严格受限的环境。作为更大安全协议的组件例如轻量级认证协议、密钥派生函数中需要的一个密码学原语。局限性64位分组长度在当今计算能力下64位分组可能在某些场景下存在“生日边界”问题。例如在CBC模式下加密大约2^32个块32GB数据后碰撞概率开始变得不可忽略。对于长期使用的高吞吐量链路需要更频繁地更换密钥或IV。80位密钥长度PRESENT-80的密钥长度是80位安全强度约为2^80。这对于抗穷举攻击是足够的远超当前计算能力但低于AES-128的128位。如果追求更高的安全余量应使用PRESENT-128版本。生态与审计虽然PRESENT是ISO标准但其软件和硬件实现的库、审计案例远没有AES丰富。在商业产品中使用时可能需要自己承担更多的实现审计工作。6. 总结与资源通过这个从理论到C实现再到硬件效率剖析的完整过程我希望你不仅获得了一段可以工作的PRESENT代码更重要的是理解了轻量级密码学的设计哲学在安全、效率、成本之间寻找精妙的平衡。PRESENT通过其极简的S盒、零成本的P置换和紧凑的密钥编排完美诠释了这一点。对于希望进一步探索的开发者我建议查阅原始论文Bogdanov A, et al. “PRESENT: An Ultra-Lightweight Block Cipher”. CHES 2007. 这是所有知识的源头。参考开源实现在GitHub上搜索“PRESENT cipher”可以找到多种语言和硬件描述语言Verilog/VHDL的实现对照学习。尝试硬件实现如果你有FPGA开发板尝试用Verilog实现一个PRESENT加密核综合后查看资源报告你会对“1500 GE”有更直观的感受。探索变体与模式了解基于PRESENT的认证加密模式如PRESENT-80-OCB思考如何将其应用到你的物联网项目框架中。密码学实现细节决定成败。每一次位运算的偏差都可能导致安全性的彻底丧失。因此严谨的测试、对标准的严格遵守、以及对边界情况的充分思考是从事这项工作的必备素养。希望这篇长文能成为你探索轻量级密码世界的一块坚实垫脚石。

相关新闻

MySQL 5.7 频繁被 Systemd 杀死:一次惊心动魄的故障排查之旅

MySQL 5.7 频繁被 Systemd 杀死:一次惊心动魄的故障排查之旅

摘要:本文详细记录了一次 MySQL 5.7 数据库频繁宕机的问题排查全过程。从应用连接失败日志入手,逐步深入分析 systemd 服务配置、磁盘空间、启动超时等关键因素,最终通过优化 systemd 服务类型完美解决问题。适合所有遇到过数据库莫名重启的开…

2026/7/9 5:30:05阅读更多 →
GitHub AI项目实战:聚焦Agent技能化与工程化集成

GitHub AI项目实战:聚焦Agent技能化与工程化集成

🚀 30款热门AI模型一站整合,DeepSeek/GLM/Qwen 随心用,限时 5 折。 👉 点击领海量免费额度 最近在 GitHub 上找 AI 项目,是不是感觉信息过载了?每天都有几十个新项目冒出来,标题都带着“AI”…

2026/7/9 5:25:05阅读更多 →
计算机毕业设计之基于SSM框架的爱鑫助农脱贫平台系统设计与实现

计算机毕业设计之基于SSM框架的爱鑫助农脱贫平台系统设计与实现

随着世界经济信息化、全球化的到来和互联网的飞速发展,推动了各行业的改革。若想达到安全,快捷的目的,就需要拥有信息化的组织和管理模式,建立一套合理、动态的、交互友好的、高效的爱鑫助农脱贫平台系统。当前的信息管理存在工作…

2026/7/9 5:25:05阅读更多 →
为什么顶尖创意工作室悄悄弃用DALL-E?——从品牌一致性、迭代效率到版权链溯源,一场被低估的生产力革命正在发生

为什么顶尖创意工作室悄悄弃用DALL-E?——从品牌一致性、迭代效率到版权链溯源,一场被低估的生产力革命正在发生

更多请点击: https://codechina.net 第一章:一场静默的工具迁移:创意工作室为何集体转向Midjourney 当Adobe Firefly在2023年夏季发布时,多数设计团队曾期待它成为生成式设计的新支点。然而三个月后,行业调研显示——…

2026/7/9 6:35:09阅读更多 →
Deb to IPA:终极免费工具,3分钟将Linux应用转换为iOS IPA文件

Deb to IPA:终极免费工具,3分钟将Linux应用转换为iOS IPA文件

Deb to IPA:终极免费工具,3分钟将Linux应用转换为iOS IPA文件 【免费下载链接】deb-to-ipa ▶️ Convert an application from a deb to an IPA with a GitHub workflow. 项目地址: https://gitcode.com/gh_mirrors/de/deb-to-ipa 你是否曾梦想过…

2026/7/9 6:35:09阅读更多 →
电竞比赛主板如何兼顾多显卡扩展与性价比?2026年四大品牌选购风向标

电竞比赛主板如何兼顾多显卡扩展与性价比?2026年四大品牌选购风向标

2026年的电竞主板市场,正在经历一场从“参数竞赛”到“生态竞争”的深刻转变。据行业研究机构数据,全球游戏级主板市场规模预计达127.5亿美元,年复合增长率保持在8.30%。然而,受内存与硬盘价格持续攀升影响,2026年4月中…

2026/7/9 6:35:09阅读更多 →
${PROJECT_NAME} 技术文档

${PROJECT_NAME} 技术文档

${PROJECT_NAME} 技术文档 【免费下载链接】idea-markdown Markdown language support for IntelliJ IDEA (abandonned). 项目地址: https://gitcode.com/gh_mirrors/id/idea-markdown 概述 ${PROJECT_DESCRIPTION} 安装指南 环境要求安装步骤配置说明 API参考 类和…

2026/7/9 6:35:09阅读更多 →
村长团队教你用Blender+Sollumz制作GTA5全域可互动游泳水源超细实操教程

村长团队教你用Blender+Sollumz制作GTA5全域可互动游泳水源超细实操教程

BlenderSollumz制作GTA5全域可互动游泳水源完整超细实操教程一、前期全部必备软件工具提前装好(一步都不能漏)1. 提前下载安装稳定版Blender软件,优先选择3.3至4.0之间的版本,这个区间版本适配所有GTA5模组水源制作插件&#xff0…

2026/7/9 6:35:09阅读更多 →
WarcraftHelper:魔兽争霸III现代优化插件完整指南

WarcraftHelper:魔兽争霸III现代优化插件完整指南

WarcraftHelper:魔兽争霸III现代优化插件完整指南 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper 还在为经典魔兽争霸III在现代电脑上的兼…

2026/7/9 6:30:09阅读更多 →
从GitHub安全案例解析常见漏洞与防护实践

从GitHub安全案例解析常见漏洞与防护实践

1. 项目概述:从GitHub Trending看安全实战 最近在GitHub Trending上看到一个项目,叫 skills4/skills ,它因为一些安全漏洞案例被大家讨论。这其实是一个挺典型的场景:一个旨在展示或教授某种技能的仓库,本身却成了安…

2026/7/9 5:56:19阅读更多 →
MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

# MLT 2026启示:因果推理与概率建模驱动下一代LLM应用## 一、背景与挑战:从“黑箱预测”到“可信推理”2026年6月,第7届机器学习与趋势国际会议(MLT 2026)将在悉尼召开。会议议程中,“因果与可解释机器学习…

2026/7/8 7:00:12阅读更多 →
通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

1. 项目概述与漏洞背景最近在梳理一些历史OA系统的安全风险时,通达OA v11.6版本中的一个老漏洞又进入了我的视线。这个漏洞位于/general/bi_design/appcenter/report_bi.func.php文件中,是一个典型的SQL注入点。虽然这个漏洞的利用方式看起来并不复杂&am…

2026/7/9 2:47:07阅读更多 →
Three.js 着色器光效教程

Three.js 着色器光效教程

着色器光效 Shader Light ▶ 在线运行案例 案例合集: 三维可视化功能案例(threehub.cn)开源仓库github地址: https://github.com/z2586300277/three-cesium-examples400个案例代码: 网盘链接 你将学到什么 ShaderMaterial 自…

2026/7/9 0:04:37阅读更多 →
如何5分钟掌握CS2智能库存管理:开源工具CASEMOVE终极指南

如何5分钟掌握CS2智能库存管理:开源工具CASEMOVE终极指南

如何5分钟掌握CS2智能库存管理:开源工具CASEMOVE终极指南 【免费下载链接】casemove A dedicated desktop app that enables you to move items in and out of storage units in CS2. 项目地址: https://gitcode.com/gh_mirrors/ca/casemove 还在为CS2存储单…

2026/7/9 0:04:37阅读更多 →
GBase 8a vs MySQL 8.0:ALTER TABLE语法与限制的5点关键差异对比

GBase 8a vs MySQL 8.0:ALTER TABLE语法与限制的5点关键差异对比

GBase 8a与MySQL 8.0:ALTER TABLE语法差异深度解析与实战指南1. 两种数据库的ALTER TABLE能力全景对比在数据库架构设计和运维过程中,表结构变更(DDL操作)是不可避免的需求。GBase 8a作为国产分析型数据库代表,与开源M…

2026/7/9 0:04:37阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/8 6:59:54阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/8 13:42:39阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/8 13:42:39阅读更多 →