赞
踩
本人一直想找时间系统整理一下之前做过的一些实验,便于后续用到的时候可以尽快的使用,po出来也便于大家交流学习,有问题欢迎交流指正,与诸君共勉!
【现代密码学】实验二 SM4分组密码算法
(1)掌握SM4分组密码算法的扩散和混淆原理;
(2)熟悉分组密码算法的4种工作模式;
(3)了解SM4分组密码算法的雪崩效应。
SM4算法:
SM4算法是用于WAPI的分组密码算法,是2006年我国国家密码管理局公布的国内第一个商用密码算法。
SM4是分组密码算法,其中,数据分组长度为128比特,密钥分组长度也为128比特。加密算法与密钥扩展算法都采用32轮迭代结构,以字节(8位)和字(32位)为单位进行数据处理。
SM4密码算法的基本运算有模2加和循环移位。
(1)模二加:记为⊕,为32位逐比特异或运算。
(2)循环移位:<<<i,把32位字循环左移i位。
(1)S盒
S盒是以字节为单位的非线性替换,其密码学的作用是混淆,它的输入和输出都是8位的字节。设输入字节位a,输出字节为b,则S盒的运算可表示为
S盒的替换规则如表1所示,例如输入为EF,则输出为第E行和第F列交叉处的值84,即S(EF)=84。
表1 SM4密码算法的S盒
(2)非线性变换τ
非线性变换τ是以字为单位的非线性替换,它由4个S盒并置构成。设输入为A=(a0,a1,a2,a3)(4个32位的字),输出为B=(b0,b1,b2,b3)(4个32位的字),则
(3)线性变换部件L
线性变换部件LS是以字为处理单位的线性变换,其输入输出都是32位的字,它的密码学作用是扩散。
设L的输入为字B,输出为字C,则
(4)合成变换T
合成变换T由非线性变换τ和线性变换L复合而成,数据处理的单位是字。设输入为字X,则先对X进行非线性τ变换,再进行线性L变换。记为
由于合成变换T是非线性变换和线性变换L的复合,所以它综合起到混淆和扩散的作用,从而可提高密码的安全性。
轮函数由上述基本密码部件构成。设轮函数F的输入为4个32单位字(X0,X1,X2,X3),共128位,轮密钥为一个32位的字rk。输出也是一个32位的字,由下式给出:
F(X0,X1,X2,X3,rk)= X0⊕T(X1⊕X2⊕X3⊕rk)
根据公式(3),有
F(X0,X1,X2,X3,rk)= X0⊕L(τ(X1⊕X2⊕X3⊕rk))
记B=(X1⊕X2⊕X3⊕rk),根据式(1)和式(2),有
F(X0,X1,X2,X3,rk)=
轮函数的结构如图1、图2所示。
加密算法采用32轮迭代结构,每轮使用一个轮密钥。
设输入的明文为4个字(X0,X1,X2,X3)(128比特长),输入的轮密钥为rki(i=0,1,...,31),共32个字。输出的密文为4个字(Y0,Y1,Y2,Y3)(128比特长)。加密算法可描述如下:
为了与解密算法需要的顺序一致,同时也与人们的习惯顺序一致,在加密算法之后还需要一个反序处理R:
加密算法的框图如图1、图2所示。
图2 SM4算法的加密算法和轮函数结构图
解密算法与加密算法相同,只是轮密钥的使用顺序相反,解密轮密钥是加密轮密钥的逆序。
算法的输入为密文(Y0,Y1,Y2,Y3)和轮密钥rki(i=31,30,...,0),输出为明文(X0,X1,X2,X3),则(Y0,Y1,Y2,Y3)=X35,X34,X33,X32。为了便于与加密算法对照,解密算法中仍然用Xi表示密文,于是可得到如下的解密算法。
解密算法:
与加密算法之后需要一个反序处理同样的道理,在解密算法之后也需要一个反序处理R:
(X0,X1,X2,X3)=R(X3,X2,X1,X0)
SM4算法加密时输入128位的密钥,采用32轮迭代结构,每一轮使用一个32位的轮密钥,共使用32个轮密钥。使用密钥扩展算法,从加密密钥产生出32个轮密钥。
在密钥扩展中使用如下的常数:
共使用32个固定参数CKi,每个CKi是一个字,其产生规则如下:
设为的第j个字节,即,
则
这32个固定参数如下(十六进制):
0070E15, 1C232A31, 383F464D, 545B6269
70777E85, 8C939AA1, A8AFB6BD, C4CBD2D9
E0E7EEF5, FC030A11, 181F262D, 343B4249
50575E65, 6C737A81, 888F969D, A4ABB2B9
C0C7CED5, DCE3EAF1, F8FF060D, 141B2229
30373E45, 4C535A61, 686F767D, 848B9299
A0A7AEB5, BCC3CAD1, D8DFE6ED, F4FB0209
10171E25, 2C333A41, 484F565D, 646B7279
设输入的加密密钥为MK=(MK0,MK1,MK2,MK3),输出轮密钥为rki(i=0,1,...,31),密钥扩展算法可描述如下,其中,Ki(i=0,1,...,35)为中间数据:
a. (
b.
其中的变换与加密算法轮函数中的T基本相同,只将其中的线性变化L修改为以下的:
密钥扩展算法的结构与加密算法的结构类似,也是采用了32轮的迭代处理。
工作模式:
从国密算法中可以知道,分组加密是对128比特的明文输入和128比特的加密密钥进行处理,生成128比特的密文输出,即分组加密算法只能加密固定长度的明文分组块。
但实际情况往往是明文的长度会远超过密码分组的长度,因此需要对分组加密算法进行迭代,才能将明文全部加密,采用的迭代方法就是分组加密算法的加密工作模式。
Electronic CodeBook mode,电子密码本模式
ECB模式是将明文分成固定长度的组块,然后对每个明文分组块使用相同的密钥进行独立加密或解密,且该加密的结果将直接作为密文分组。
ECB模式是最简单的分组加密算法的一种工作模式。
ECB模式的工作原理:
图3 ECB模式加密过程
CBC(Cipher Block Chaining)模式,即密码分组链接模式。该模式首先将明文分组与前一个密文分组进行XOR运算,然后再进行加密。只有第一个明文分组特殊,需要提前为其生成一个与分组长度相同的比特序列,进行XOR运算,这个比特序列称为初始化向量(Initialization Vector),简称IV。
CBC模式的加密过程:
CFB(Cipher FeedBack)模式,即密文反馈模式。该模式首先将前一个密文分组进行加密,再与当前明文分组进行XOR运算,来生成密文分组。同样CFB模式也需要一个IV。
OFB(Output FeedBack)模式,即输出反馈模式。该模式会产生一个密钥流,即将密码算法的前一个输出值,做为当前密码算法的输入值。该输入值再与明文分组进行XOR运行,计算得出密文分组。该模式需要一个IV,进行加密后做为第一个分组的输入。
扩散就是让明文中的每一位影响密文中的许多位,或者说让密文中的每一位受明文中的许多位的影响.这样可以隐蔽明文的统计特性。
混淆就是将密文与密钥之间的统计关系变得尽可能复杂,使得对手即使获取了关于密文的一些统计特性,也无法推测密钥。使用复杂的非线性代替变换可以达到比较好的混淆效果,而简单的线性代替变换得到的混淆效果则不理想。
雪崩效应
雪崩效应(avalanche effect),密码学术语,指加密算法(尤其是块密码和加密散列函数)的一种理想属性。雪崩效应是指当输入发生最微小的改变(例如,反转一个二进制位)时,也会导致输出的不可区分性改变(输出中每个二进制位有50%的概率发生反转)。
实验基本方法:
(1)用java语言编写SM4分组密码算法;
(2)编程实现对文件的加密,加密模式为电码本或分组链接模式;
(3)额外要求:编程实现密码反馈模式和输出反馈模式。
说明:
(1)SM4分组密码算法可以自编,也可以网上下载现成算法;
(2)工作模式的程序可以自编,也可以利用cryptopp加密包编程。
实验步骤:
(1)编程实现SM4分组密码算法;
(2)改变1位明文观察输出SM4分组密码算法的32轮输出;
(3)改变1位密钥观察输出SM4分组密码算法的32轮输出;
(4)在电码本模式、分组链接模式、密码反馈模式和输出反馈模式中,在最少128个分组的明文中,观察当一个密文分组错误时,还原的明文有几个分组错误。
- sm4.h文件
- #pragma once
- #ifdef __cplusplus
- #endif
- #include <stdbool.h>
- #include <stdint.h>
- #include <string>
-
- void sm4_ecb_encrypt(const uint8_t key[16], size_t len, const uint8_t *plain, uint8_t *cipher);
- void sm4_ecb_decrypt(const uint8_t key[16], size_t len, const uint8_t *cipher, uint8_t *plain);
-
- void sm4_cbc_encrypt(const uint8_t key[16], const uint8_t iv[16], size_t len, const uint8_t *plain, uint8_t *cipher);
- void sm4_cbc_decrypt(const uint8_t key[16], const uint8_t iv[16], size_t len, const uint8_t *cipher, uint8_t *plain);
-
- void sm4_cfb_encrypt(const uint8_t key[16], const uint8_t iv[16], size_t len, const uint8_t *plain, uint8_t *cipher);
- void sm4_cfb_decrypt(const uint8_t key[16], const uint8_t iv[16], size_t len, const uint8_t *cipher, uint8_t *plain);
-
- void sm4_ofb_encrypt(const uint8_t key[16], const uint8_t iv[16], size_t len, const uint8_t *plain, uint8_t *cipher);
- void sm4_ofb_decrypt(const uint8_t key[16], const uint8_t iv[16], size_t len, const uint8_t *cipher, uint8_t *plain);
-
-
-
- #define SM4_MIN_MODE SM4_ECB_MODE
- #define SM4_ECB_MODE 1
- #define SM4_CBC_MODE 2
- #define SM4_CFB_MODE 3
- #define SM4_OFB_MODE 4
- #define SM4_MAX_MODE SM4_OFB_MODE
-
- typedef struct {
- uint32_t rkey[32];
- uint8_t iv[16];
- uint8_t mode;
- } sm4_ctx_t;
-
- void sm4_close(sm4_ctx_t *ctx);
- int sm4_init(sm4_ctx_t *ctx, uint8_t mode, const uint8_t key[16], const uint8_t iv[16]);
- int sm4_encrypt(sm4_ctx_t *ctx, size_t len, const uint8_t *plain, uint8_t *cipher);
- int sm4_decrypt(sm4_ctx_t *ctx, size_t len, const uint8_t *cipher, uint8_t *plain);
-
- # ifdef __cplusplus
-
- # endif
-
- #ifndef __MasterEncoder_H__
- #define __MasterEncoder_H__
- #include <mutex>
- #include <string>
- using namespace std;
- class MasterEncoder
- {
- public:
- static MasterEncoder* getInstance();
- MasterEncoder();
- ~MasterEncoder();
-
- void setSignAndKey(char* sign, int signLen, unsigned char key);
-
- void decode(unsigned char* data, long size);
- void encode(unsigned char* data, long size);
-
- void writePDF(const string& filePath, unsigned char* data, long size);
- unsigned char* readPDF(const string& filepath, long& size);
-
- public:
- void encodePDF(const string& pdfPath, const string& savePath);
- void decodePDF(const string& pdfPath, const string& savePath);
- unsigned char* decodePDF(const string& pdfPath, long& size);
-
- private:
- static MasterEncoder* _instance;
- static mutex _mtx;
-
- unsigned char _codeKey;
- char* _sign;
- int _signLen;
-
- };
-
-
- #endif // !MasterEncoder
-
- sm4.cpp文件
- #include "sm4.h"
- #include <stdio.h>
- #include<iostream>
- /** SBox */
- static const uint8_t SBOX[256] = {
- 0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7,
- 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,
- 0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3,
- 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
- 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a,
- 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62,
- 0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95,
- 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6,
- 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba,
- 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8,
- 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b,
- 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35,
- 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2,
- 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87,
- 0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52,
- 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e,
- 0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5,
- 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1,
- 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55,
- 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3,
- 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60,
- 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f,
- 0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f,
- 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51,
- 0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f,
- 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8,
- 0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd,
- 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0,
- 0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e,
- 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84,
- 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20,
- 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48,
- };
-
- /** 数据类型转换(char to int)八位(字节数组)转32位(字) */
- static inline uint32_t _load_le_u32(const uint8_t bs[4]) {
- return *(uint32_t*)bs;
- }
- /** 数据类型转换(char to int)八位(字节数组)转32位(字) */
- static inline uint32_t _load_be_u32(const uint8_t bs[4]) {
- return ((uint32_t)bs[0] << 24) | ((uint32_t)bs[1] << 16) | ((uint32_t)bs[2] << 8) | bs[3];
- }
- /** 数据类型转换(int to char)32位(字)转八位(字节数组) */
- static inline void _store_le_u32(const uint32_t x, uint8_t bs[4]) {
- *(uint32_t*)bs = x;
- }
- /** 数据类型转换(int to char)32位(字)转八位(字节数组) */
- static inline void _store_be_u32(const uint32_t x, uint8_t bs[4]) {
- bs[0] = (x >> 24) & 0xff;
- bs[1] = (x >> 16) & 0xff;
- bs[2] = (x >> 8) & 0xff;
- bs[3] = (x) & 0xff;
- }
- /** 数据类型转换(char to int)八位(字节数组)转64位*/
- static inline void _store_le_u64(const uint64_t x, uint8_t bs[8]) {
- *(uint64_t*)bs = x;
- }
- /** 数据类型转换(char to int)八位(字节数组)转64位*/
- static inline void _store_be_u64(const uint64_t x, uint8_t bs[8]) {
- bs[0] = (x >> 56) & 0xff;
- bs[1] = (x >> 48) & 0xff;
- bs[2] = (x >> 40) & 0xff;
- bs[3] = (x >> 32) & 0xff;
- bs[4] = (x >> 24) & 0xff;
- bs[5] = (x >> 16) & 0xff;
- bs[6] = (x >> 8) & 0xff;
- bs[7] = (x) & 0xff;
- }
- /**将x左移n位 */
- static inline uint32_t _lshift(uint32_t x, int n) {
- return (x << n) | (x >> (32 - n));
- }
- /**将x右移n位 */
- static inline uint32_t _rshift(uint32_t x, int n) {
- return (x << (32 - n)) | (x >> n);
- }
-
- /**求out和in按位异或的结果 结果存在out*/
- static inline void _xor_block(uint8_t *out, const uint8_t *in, size_t len) {
- for (size_t i = 0; i < len; ++i) {
- out[i] ^= in[i];
- }
- }
- /*转一位16进制*/
- static inline char _hex(uint8_t n) {
- static const char HEX[16] = {
- '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
- };
- return HEX[n];
- }
- // expand uint8 data to hex format in place, so data should have len * 2 space
- //八位扩展到16位形式
- static inline void _expand_hex(uint8_t *data, size_t len) {
- for (size_t i = 0; i < len; ++i) {
- size_t j = len - 1 - i;
- uint8_t x = data[j];
- data[j * 2] = (uint8_t)_hex((x >> 4) & 0xf);
- data[j * 2 + 1] = (uint8_t)_hex(x & 0xf);
- }
- }
- /**
- * .
- *
- * \param x 32位输入
- * \return
- */
- static uint32_t _sbox(uint32_t x) {
- uint8_t u[4];
- *(uint32_t *)u = x;
- u[0] = SBOX[u[0]];
- u[1] = SBOX[u[1]];
- u[2] = SBOX[u[2]];
- u[3] = SBOX[u[3]];
- return *(uint32_t *)u;
- }
-
- /** 线性变换L.输入输出都是32位的字*/
- static inline uint32_t _st1(uint32_t x) {
- x = _sbox(x);
- return x ^ _lshift(x, 2) ^ _lshift(x, 10) ^ _lshift(x, 18) ^ _lshift(x, 24);
- }
-
- /** 密码扩展算法使用的线性变换.*/
- static inline uint32_t _st2(uint32_t x) {
- x = _sbox(x);
- return x ^ _lshift(x, 13) ^ _lshift(x, 23);
- }
-
- /**常数FK*/
- static const uint32_t FK[4] = {
- 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc,
- };
-
- /**32个固定参数CK_i,每个CK_i是一个字*/
- static const uint32_t CK[32] = {
- 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
- 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
- 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
- 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
- 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
- 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
- 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
- 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279,
- };
-
- /**
- * 密钥扩展算法得到轮密钥.
- * \param key 初始密钥
- * \param rkey 轮密钥
- */
- static void sm4_calc_key(const uint8_t key[16], uint32_t rkey[32]) {
- uint32_t x[5];
- /**
- * 将输入的密钥每32比特合并(得到MK_0,MK_1,MK_2,MK_3),
- */
- x[0] = _load_be_u32(key);
- x[1] = _load_be_u32(key + 4);
- x[2] = _load_be_u32(key + 8);
- x[3] = _load_be_u32(key + 12);
- /**
- * 并异或FK 得到(K_0,K_1,K_2,K_3)
- ( K_0,K_1,K_2,K_3)=(MK_0⊕FK_0,MK_1⊕FK_1,MK_2⊕FK_2,MK_3⊕FK_3)
- */
- x[0] ^= FK[0];
- x[1] ^= FK[1];
- x[2] ^= FK[2];
- x[3] ^= FK[3];
- /**
- * 32轮密钥拓展
- * For i=0,1,...,31 Do rk_i=K_(i+4)=K_i⊕T' (K_(i+1)⊕K_(i+2)⊕K_(i+3)⊕CK_i)
- */
- cout << "轮密钥生成!" << endl;
-
- for (int i = 0; i < 32; ++i) {
- uint32_t *y0 = x + (i % 5);
- uint32_t *y1 = x + ((i + 1) % 5);
- uint32_t *y2 = x + ((i + 2) % 5);
- uint32_t *y3 = x + ((i + 3) % 5);
- uint32_t *y4 = x + ((i + 4) % 5);
-
- *y4 = *y0 ^ _st2(*y1 ^ *y2 ^ *y3 ^ CK[i]);
- rkey[i] = *y4;
- cout << "第" << i + 1 << "个轮密钥: ";
- printf("%02x", rkey[i]);
- cout << endl;
- }
-
- }
-
- /**对轮密钥进行反序变换.*/
- static inline void sm4_rev_key(uint32_t rkey[32]) {
- for (int i = 0; i < 16; ++i) {
- uint32_t t = rkey[i];
- rkey[i] = rkey[31 - i];
- rkey[31 - i] = t;
- }
- }
-
- /**
- * 用轮密钥对 in 加密 为 out
- * \param rkey
- * \param in
- * \param out
- */
- static void sm4_calc_block(const uint32_t rkey[32], const uint8_t in[16], uint8_t out[16]) {
- /*
- cout << endl << "输 入 明 文: ";
- for (int i = 0; i < 16; i++)
- printf("%02x ", in[i]);
- cout << endl;
- */
- uint32_t x[5];
- // 将32比特数拆分成4个8比特数
- x[0] = _load_be_u32(in);
- x[1] = _load_be_u32(in + 4);
- x[2] = _load_be_u32(in + 8);
- x[3] = _load_be_u32(in + 12);
-
- for (int i = 0; i < 32; ++i) {
- uint32_t *y0 = x + (i % 5);
- uint32_t *y1 = x + ((i + 1) % 5);
- uint32_t *y2 = x + ((i + 2) % 5);
- uint32_t *y3 = x + ((i + 3) % 5);
- uint32_t *y4 = x + ((i + 4) % 5);
- //轮函数F(X_0, X_1, X_2, X_3, rk) = X_0⊕L(τ(X_1⊕X_2⊕X_3⊕rk))
- // cout << "第" << i+1 << "个轮密钥rkey["<<i<<"]: ";
-
- *y4 = *y0 ^ _st1(*y1 ^ *y2 ^ *y3 ^ rkey[i]);
- //cout << y1;
- /*
- cout << "第" << i + 1 << "轮输出: ";
- _store_be_u32(x[0], out);
- _store_be_u32(x[4], out + 4);
- _store_be_u32(x[3], out + 8);
- _store_be_u32(x[2], out + 12);
- printf("%02x ", x[2]); printf("%02x ", x[3]); printf("%02x ", x[4]); printf("%02x ", x[0]);
- cout << endl;
- //printf("%02x ", y1); printf("%02x ", y2); printf("%02x ", y3); printf("%02x ", y4);
- */
- }
- _store_be_u32(x[0], out);
- _store_be_u32(x[4], out + 4);
- _store_be_u32(x[3], out + 8);
- _store_be_u32(x[2], out + 12);
- cout << "最终该分组加密结果(将第32轮结果反序后):" << endl;
- // cout << "最终加密结果(将第32轮结果反序后):" << endl;
- printf("%02x ", x[0]); printf("%02x ", x[4]); printf("%02x ", x[3]); printf("%02x ", x[2]);
- cout << endl;
- }
-
-
- /** ECB模式 加密 (已生成的轮密钥做参数)(过程调用 功能函数)*/
- static inline void _ecb(const uint32_t* rkey, size_t len, const uint8_t* in, uint8_t* out) {
- for (size_t i = 0; i < len; i += 16) {
- sm4_calc_block(rkey, in + i, out + i);//加密
- }
- }
-
- /**
- * ECB模式加密.(初始密钥做参数)
- * \param key 初始密钥
- * \param len
- * \param plain 明文
- * \param cipher 密文
- */
- void sm4_ecb_encrypt(const uint8_t key[16], size_t len, const uint8_t* plain, uint8_t* cipher) {
- uint32_t rkey[32];
- sm4_calc_key(key, rkey);//初始化轮密钥
- _ecb(rkey, len, plain, cipher);
- // memset(rkey, 0, sizeof(rkey));
- }
- /**
- * ECB模式解密
- * \param key 初始密钥
- * \param len
- * \param cipher 密文
- * \param plain 明文
- */
- void sm4_ecb_decrypt(const uint8_t key[16], size_t len, const uint8_t* cipher, uint8_t* plain) {
- uint32_t rkey[32];
- sm4_calc_key(key, rkey);//初始化轮密钥
- sm4_rev_key(rkey);
- _ecb(rkey, len, cipher, plain);
- // memset(rkey, 0, sizeof(rkey));
- }
-
- /**CBC模式 加密(已生成的轮密钥做参数).工具函数 */
- static inline void _cbc_encrypt(const uint32_t *rkey, uint8_t *iv, size_t len, const uint8_t *plain, uint8_t *cipher) {
- for (size_t i = 0; i < len; i += 16) {
- _xor_block(iv, plain + i, 16);//iv和plain异或 结果存在iv
- sm4_calc_block(rkey, iv, cipher + i); //加密
- memcpy(iv, cipher + i, 16);
- }
- }
-
- /** CBC 模式 解密 工具函数*/
- static inline void _cbc_decrypt(const uint32_t *rkey, uint8_t *iv, size_t len, const uint8_t *cipher, uint8_t *plain) {
- for (size_t i = 0; i < len; i += 16) {
- sm4_calc_block(rkey, cipher + i, plain + i);
- _xor_block(plain + i, iv, 16);
- memcpy(iv, cipher + i, 16);
- }
- }
-
-
- /**
- * CBC 密码块链 (Cipher Block Chaining) 模式 加密
- * 无法单独对一个中间的明文分组进行加密
- 明文的微小改变会导致其后全部密文分组发生改变
- * \param key 初始密钥
- * \param iv 初始向量
- * \param len 分组数
- * \param plain 明文
- * \param cipher 密文
- */
- void sm4_cbc_encrypt(const uint8_t key[16], const uint8_t iv[16], size_t len, const uint8_t* plain, uint8_t* cipher) {
- uint32_t rkey[32];
- sm4_calc_key(key, rkey);//初始化轮密钥
- uint8_t out[16];
- memcpy(out, iv, 16);
- _cbc_encrypt(rkey, out, len, plain, cipher);
- // memset(rkey, 0, sizeof(rkey));
- // memset(out, 0, sizeof(out));
- }
-
- /**
- * CBC 密码块链 (Cipher Block Chaining) 模式 解密算法.
- * \param key 初始密钥
- * \param iv 初始向量
- * \param len 分组数
- * \param cipher 密文
- * \param plain 明文
- */
- void sm4_cbc_decrypt(const uint8_t key[16], const uint8_t iv[16], size_t len, const uint8_t* cipher, uint8_t* plain) {
- uint32_t rkey[32];
- sm4_calc_key(key, rkey);
- sm4_rev_key(rkey);
- uint8_t out[16];
- memcpy(out, iv, 16);
- _cbc_decrypt(rkey, out, len, cipher, plain);
- // memset(rkey, 0, sizeof(rkey));
- // memset(out, 0, sizeof(out));
- }
-
-
- /**
- * CFB模式 加密.(工具函数)
- 加密:将前一个密文分组(或初始化向量 IV)进行再加密;
- 将明文分组和上一步处理得到的再加密的密文分组进行异或。
- */
- static inline void _cfb_encrypt(const uint32_t *rkey, uint8_t *iv, size_t len, const uint8_t *plain, uint8_t *cipher) {
- for (size_t i = 0; i < len; i += 16) {
- sm4_calc_block(rkey, iv, cipher + i);
- _xor_block(cipher + i, plain + i, 16);
- memcpy(iv, cipher + i, 16);
- }
- }
-
-
- /**
- * CFB模式的解密过程几乎就是颠倒的CBC模式的加密过程。.
- * CFB模式 解密.(工具函数)
- * \param rkey
- * \param iv
- * \param len
- * \param cipher
- * \param plain
- */
- static inline void _cfb_decrypt(const uint32_t *rkey, uint8_t *iv, size_t len, const uint8_t *cipher, uint8_t *plain) {
- for (size_t i = 0; i < len; i += 16) {
- sm4_calc_block(rkey, iv, plain + i);
- _xor_block(plain + i, cipher + i, 16);
- memcpy(iv, cipher + i, 16);
- }
- }
-
-
- /**
- * CFB模式 加密
- * \param key
- * \param iv
- * \param len
- * \param plain
- * \param cipher
- */
- void sm4_cfb_encrypt(const uint8_t key[16], const uint8_t iv[16], size_t len, const uint8_t *plain, uint8_t *cipher) {
- uint32_t rkey[32];
- sm4_calc_key(key, rkey);
- uint8_t out[16];
- memcpy(out, iv, 16);
- _cfb_encrypt(rkey, out, len, plain, cipher);
- // memset(rkey, 0, sizeof(rkey));
- // memset(out, 0, sizeof(out));
- }
- /**
- * CFB解密函数.
- * \param key 初始密钥
- * \param iv 初始向量
- * \param len 分组数
- * \param cipher 密文
- * \param plain 明文
- */
- void sm4_cfb_decrypt(const uint8_t key[16], const uint8_t iv[16], size_t len, const uint8_t *cipher, uint8_t *plain) {
- uint32_t rkey[32];
- sm4_calc_key(key, rkey);
- uint8_t out[16];
- memcpy(out, iv, 16);
- _cfb_decrypt(rkey, out, len, cipher, plain);
- }
-
-
- /**
- * .OFB模式 加密.(工具函数)
- * 加密:先将初始化向量 IV 用密钥加密生成密钥流
- 再将密钥流与明文流异或得到密文流
- * \param rkey
- * \param iv
- * \param len 明文分组数
- * \param in
- * \param out
- *//**OFB模式 加密.(工具函数)*/
- static inline void _ofb(const uint32_t* rkey, uint8_t* iv, size_t len, const uint8_t* in, uint8_t* out) {
- for (size_t i = 0; i < len; i += 16) {
- sm4_calc_block(rkey, iv, out + i);
- memcpy(iv, out + i, 16);
- _xor_block(out + i, in + i, 16);
- }
- }
-
- /**
- * OFB模式 加密.
- * \param key 初始密钥
- * \param iv 初始向量
- * \param len 长度
- * \param plain 明文
- * \param cipher 密文
- */
- void sm4_ofb_encrypt(const uint8_t key[16], const uint8_t iv[16], size_t len, const uint8_t *plain, uint8_t *cipher) {
- uint32_t rkey[32];
- sm4_calc_key(key, rkey);
- uint8_t out[16];
- memcpy(out, iv, 16);
- _ofb(rkey, out, len, plain, cipher);
- // memset(rkey, 0, sizeof(rkey));
- // memset(out, 0, sizeof(out));
- }
- /**
- * OFB模式 解密
- * \param key 初始密钥
- * \param iv 初始向量
- * \param len 长度
- * \param cipher 密文
- * \param plain 明文
- */
- void sm4_ofb_decrypt(const uint8_t key[16], const uint8_t iv[16], size_t len, const uint8_t *cipher, uint8_t *plain) {
- sm4_ofb_encrypt(key, iv, len, cipher, plain);
- }
-
-
- #define SM4_ENCRYPT 0x10
- #define SM4_DECRYPT 0x20
-
- void sm4_close(sm4_ctx_t *ctx) {
- memset(ctx, 0, sizeof(sm4_ctx_t));
- }
- /**
- * .SM4 初始化
- * \param ctx
- * \param mode 模式选择参数
- * \param key 初始密钥
- * \param iv 初始向量
- * \return
- */
- int sm4_init(sm4_ctx_t *ctx, uint8_t mode, const uint8_t key[16], const uint8_t iv[16]) {
- if (mode < SM4_ECB_MODE || mode > SM4_OFB_MODE) {
- return -1;
- }
- if (mode == SM4_ECB_MODE && iv != NULL) {
- return -1;
- }
- if (mode != SM4_ECB_MODE && iv == NULL) {
- return -1;
- }
- ctx->mode = mode;
- sm4_calc_key(key, ctx->rkey);
- if (iv != NULL) {
- memcpy(ctx->iv, iv, 16);
- } else {
- memset(ctx->iv, 0, 16);
- }
- return 0;
- }
-
- /**
- * SM4加密 可选择四种方式.
- * \param ctx
- * \param len 长度
- * \param plain 明文
- * \param cipher 密文
- * \return
- */
- int sm4_encrypt(sm4_ctx_t *ctx, size_t len, const uint8_t *plain, uint8_t *cipher) {
- if ((ctx->mode & 0xf0) == 0) {
- ctx->mode |= SM4_ENCRYPT;
- }
- if ((ctx->mode & 0xf0) != SM4_ENCRYPT) {
- return -1;
- }
-
- uint8_t m = ctx->mode & 0x0f;
- if (m == SM4_ECB_MODE) {
- _ecb(ctx->rkey, len, plain, cipher);
- } else if (m == SM4_CBC_MODE) {
- _cbc_encrypt(ctx->rkey, ctx->iv, len, plain, cipher);
- } else if (m == SM4_CFB_MODE) {
- _cfb_encrypt(ctx->rkey, ctx->iv, len, plain, cipher);
- } else if (m == SM4_OFB_MODE) {
- _ofb(ctx->rkey, ctx->iv, len, plain, cipher);
- } else {
- return -1;
- }
- return 0;
- }
-
- /**
- * SM4解密函数. 可选择四种工作模式
- * \param ctx 模式选择等函数
- * \param len 长度
- * \param cipher 密文
- * \param plain 明文
- * \return
- */
- int sm4_decrypt(sm4_ctx_t *ctx, size_t len, const uint8_t *cipher, uint8_t *plain) {
- uint8_t m = ctx->mode & 0x0f;
- if ((ctx->mode & 0xf0) == 0) {
- ctx->mode |= SM4_DECRYPT;
- if (m != SM4_CFB_MODE && m != SM4_OFB_MODE) {
- sm4_rev_key(ctx->rkey);
- }
- }
- if ((ctx->mode & 0xf0) != SM4_DECRYPT) {
- return -1;
- }
-
- if (m == SM4_ECB_MODE) {
- _ecb(ctx->rkey, len, cipher, plain);
- } else if (m == SM4_CBC_MODE) {
- _cbc_decrypt(ctx->rkey, ctx->iv, len, cipher, plain);
- } else if (m == SM4_CFB_MODE) {
- _cfb_decrypt(ctx->rkey, ctx->iv, len, cipher, plain);
- } else if (m == SM4_OFB_MODE) {
- _ofb(ctx->rkey, ctx->iv, len, cipher, plain);
- } else {
- return -1;
- }
- return 0;
- }
-
- test_sm4.cpp文件
- #include <stdio.h>
- #include<iostream>
- #include "sm4.h"
- #include <fstream>
- #include <string>
- #include <cstring>
- #pragma warning (disable : 4996)
- using namespace std;
- #include<stdlib.h>
-
-
-
- class SM4Test {
-
- public:
- //将密文/明文最后一组 长度 填充为16位
- static char* PKCS5Padding(string strParams)
- {
- int nRaw_size = strParams.size();
- int i = 0, j = nRaw_size / 16 + 1, k = nRaw_size % 16;
- int nPidding_size = 16 - k;
- char* szArray;
- szArray = (char*)malloc(nRaw_size + nPidding_size);
- memcpy(szArray, strParams.c_str(), nRaw_size);
- for (int i1 = nRaw_size; i1 < (nRaw_size + nPidding_size); i1++)
- {
- // PKCS5Padding 算法:
- szArray[i1] = nPidding_size;
- }
- return szArray;
- }
-
-
- static void menu0() {
- cout<<"|※欢迎使用SM4加解密系统,请选择您的操作: |"<<endl;
- cout<<("| 1.对文本加密 |")<<endl;
- cout<<"| 2.对文本解密 |"<<endl;
- cout<<"| 3.对文件加密 |"<<endl;
- cout<<"| 4.对文件解密 |"<<endl;
- }
-
- static void expect_equal(const char* name, const uint8_t* a, const uint8_t* b, size_t len) {
- if (memcmp(a, b, len) == 0) {
- printf("%s OK!\n", name);
- }
- else {
- printf("%s FAIL!\n", name);
- }
- }
- static uint8_t getuint8(string s) {
- const int l0 = s.length();
- uint8_t val = std::atoi(s.c_str());
- return val;
- }
-
- /**
- * 选择工作模式(ECB/CBC/CFB/OFB) 字符串加密显示.
- * \param s 输入字符串
- */
- static void ECBencrypt(string s, uint8_t* key, uint8_t* iv, int mode) {
- uint8_t cipher0[16];
- string plain4 = s;
- const int l = plain4.length();
- const char* mm = plain4.c_str();//明文的uint8_t 类型 // string 转换为 char*
- const uint8_t* M = (uint8_t*)mm;
- int i = l / 16 + 1;//输入明文长度大于16位 则循环i轮,进行i轮加密
- if (mode = SM4_ECB_MODE) {
- cout << "ECB加密:"<<endl;
- }
- else if (mode = SM4_CBC_MODE) {
- cout << "CBC加密:" << endl;
- }
- else if (mode = SM4_CFB_MODE) {
- cout << "CFB加密:" << endl;
- }
- else if (mode = SM4_OFB_MODE) {
- cout << "OFB加密:" << endl;
- }
- cout << "明 文: ";
- cout << plain4 << endl;
- cout << "密 文: ";
- for (int c = 0; c < i; c++) {
- string Str = "";
- if (c != i - 1) Str = plain4.substr(c * 16, 16); //不是最后一组明文,截取16位
- else Str = plain4.substr(c * 16);//最后一组明文,截取至末尾
- const char* str = Str.c_str();
- if (c == i - 1) str = PKCS5Padding(Str); //最后一组明文 长度可能小于16位 先进行字节填充
- const uint8_t* MM = (uint8_t*)str;//类型转换
- if (mode = SM4_ECB_MODE) sm4_ecb_encrypt(key, 16, MM, cipher0);
- else if (mode = SM4_CBC_MODE) sm4_cbc_encrypt(key, iv, 16, MM, cipher0);
- else if (mode = SM4_CFB_MODE) sm4_cfb_encrypt(key, iv, 16, MM, cipher0);
- else if (mode = SM4_OFB_MODE) sm4_ofb_encrypt(key, iv, 16, MM, cipher0);
- for (int m = 0; m < 16; ++m) {
- //printf("%02x ", cipher[m]);
- cout << cipher0[m];
- }
- }
- cout << endl;
- }
-
- /**
- * ECB解密显示
- * \param c 密文
- * \param key 密钥
- * \param iv 初始向量
- */
- static void ECBdecrypt(uint8_t* cipher0, uint8_t* key, uint8_t* iv,int mode) {
- uint8_t plain2[16];
- string tis((char*)cipher0);//密文转string 便于提取子串
- if (mode = SM4_ECB_MODE) {
- cout << "ECB解密:" << endl;
- }
- else if (mode = SM4_CBC_MODE) {
- cout << "CBC解密:" << endl;
- }
- else if (mode = SM4_CFB_MODE) {
- cout << "CFB解密:" << endl;
- }
- else if (mode = SM4_OFB_MODE) {
- cout << "OFB解密:" << endl;
- }
- cout << "密 文: " << cipher0 << endl;
- int l0 = tis.length();
- int r = l0 / 16;//密文长度大于16位 则循环r+1轮,进行r轮解密
- cout << "明 文: ";
- for (int i = 0; i < r; i++) {
- string Tis = "";
- if (i != r - 1) Tis = tis.substr(i * 16, 16);//非最后一组密文提取密文中的16位
- if (i == r - 1) {
- Tis = tis.substr(i * 16); //最后一组 可能不足16位,截取至末尾
-
- }
- const char* str = Tis.c_str();
- string strr0((char*)str);
- if (i == r - 1) str = PKCS5Padding(Tis);//最后一组密文 长度可能小于16位 先进行字节填充
- const uint8_t* CC = (uint8_t*)str;
- //sm4_ecb_decrypt(key, 16, CC, plain2);
- if (mode = SM4_ECB_MODE) sm4_ecb_decrypt(key, 16, CC, plain2);
- else if (mode = SM4_CBC_MODE) sm4_cbc_decrypt(key, iv, 16, CC, plain2);
- else if (mode = SM4_CFB_MODE) sm4_cfb_decrypt(key, iv, 16, CC, plain2);
- else if (mode = SM4_OFB_MODE) sm4_ofb_decrypt(key, iv, 16, CC, plain2);
- for (int m = 0; m < 16; ++m) {
- cout << plain2[m];
- }
- }
- }
-
- static void sm4_test(void) {
- uint8_t plain[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 };
- uint8_t plain3[] = { 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 };
- uint8_t cipher[16*128];
- uint8_t plain2[16*128];
- uint8_t key[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 };
- uint8_t iv[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 };
- uint8_t cipher00[] = { 0x68, 0x1e, 0xdf ,0x34 ,0xd2 ,0x06 ,0x96 ,0x5e ,0x86 ,0xb3 ,0xe9 ,0x4f ,0x53 ,0x6e ,0x42 ,0x46 };
-
-
- //构造可分为128个明文分组的明文 plain_128
- uint8_t* plain128[128];
- for (int i = 0; i < 128; i++) {
- plain128[i] = plain;
- }
- uint8_t plain_128[16*128];
- for (int i = 0; i < 128; i++) {
- for (int j = 0; j < 16; j++)
- plain_128[i * 16 + j] = plain128[i][j];
- }
- //构造可分为128个密文分组的密文 cipher_128
- uint8_t* cipher128[128];
- for (int i = 0; i < 128; i++) {
- cipher128[i] = cipher00;
- }
- uint8_t cipher_128[16 * 128];
- for (int i = 0; i < 128; i++) {
- for (int j = 0; j < 16; j++)
- cipher_128[i * 16 + j] = cipher128[i][j];
- }
-
- /*
- cout <<endl<< "|------------------------ ECB加密 Test01--------------------------|" << endl;
- string s = "好好学习天天向上";
- ECBencrypt(s,key, iv, SM4_ECB_MODE); //ECB加密 Test01
- cout << "|-------------------------ECB解密 Test01--------------------------|" << endl;
- uint8_t cipher0[] = "r%8Yk€T舗h創*奛鷨<市$ 籃";
- ECBdecrypt(cipher0, key, iv, SM4_ECB_MODE);//ECB解密 Test01
- */
-
- cout << endl <<endl << "|------------------------ ECB加密 Test02--------------------------|" << endl;
- sm4_ecb_encrypt(key, 16, plain, cipher);
- cout << "明 文: ";
- for (int i = 0; i < 16; ++i) {
- printf("%02x ", plain[i]);
- }
- cout<<endl << "密 文: " ;
- for (int i = 0; i < 16; ++i) {
- printf("%02x ", cipher[i]);
- }
- /*
- //测试128个明文分组
- cout <<endl<< endl << "128个明文分组 加密测试:" << endl;
- sm4_ecb_encrypt(key, 16*128, plain_128, cipher);
- cout << "明 文: "<<endl;
- for (int i = 0; i < 16*128; ++i) {
- printf("%02x ", plain_128[i]);
- }
- cout << endl << "密 文: "<<endl;
- for (int i = 0; i < 16*128; ++i) {
- printf("%02x ", cipher[i]);
- }
- */
-
-
- cout<<endl << "|------------------------ ECB解密 Test02--------------------------|" << endl;
- sm4_ecb_decrypt(key, 16, cipher, plain2);
- cout << "密 文: ";
- for (int i = 0; i < 16; ++i) {
- printf("%02x ", cipher[i]);
- }
- cout<<endl << "明 文: "<<endl;
- for (int i = 0; i < 16; ++i) {
- printf("%02x ", plain2[i]);
- }
- cout << endl;
- /*
- //测试128位密文还原
- for (int i = 0; i < 16; i++)
- cipher_128[i] = 0x01;//修改第一个密文分组为全0x01
- cout << endl << endl << "128个密文分组 解密测试:" << endl;
- sm4_ecb_decrypt(key, 16 * 128, cipher_128, plain2);
- cout << "密 文: "<<endl;
- for (int i = 0; i < 16 * 128; ++i) {
- printf("%02x ", cipher_128[i]);
- }
- cout << endl << "明 文: "<<endl;
- for (int i = 0; i < 16 * 128; ++i) {
- printf("%02x ", plain2[i]);
- }*/
-
- uint8_t p1[32];
- uint8_t p2[32];
- uint8_t c1[32];
- //p1[0] = 0x01;
- uint8_t p3[] = { 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
- 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 };
- memset(p2, 0, 32);
- cout << endl <<endl<< "|------------------------ CBC加密 Test----------------------------|" << endl;
- cout << "明 文: ";
- sm4_cbc_encrypt(key, key, 32, iv, c1);
- for (int i = 0; i < 32; ++i) {
- printf("%02x ", iv[i]);
- }
- cout << endl << "密 文: " ;
- for (int i = 0; i < 32; ++i) {
- printf("%02x ", c1[i]);
- }
- /*
- //测试128个明文分组
- cout << endl << endl << "128个明文分组 加密测试:" << endl;
- sm4_cbc_encrypt(key, iv, 16 * 128, plain_128, cipher);
- cout << "明 文: " << endl;
- for (int i = 0; i < 16 * 128; ++i) {
- printf("%02x ", plain_128[i]);
- }
- cout << endl << "密 文: " << endl;
- for (int i = 0; i < 16 * 128; ++i) {
- printf("%02x ", cipher[i]);
- }*/
-
-
- cout <<endl<< "|-------------------------CBC解密 Test----------------------------|" << endl;
- cout << "密 文: ";
- sm4_cbc_decrypt(key, key, 32, c1, p2);
- for (int i = 0; i < 32; ++i) {
- printf("%02x ", c1[i]);
- }
- printf("\n");
- printf("明 文: ");
- for (int i = 0; i < 32; ++i) {
- printf("%02x ", p2[i]);
- }
-
- cout << endl<<endl << "|-------------------------CFB加密 Test----------------------------|" << endl;
- cout << "明 文: ";
- sm4_cfb_encrypt(key, key, 32, p3, c1);
- for (int i = 0; i < 16; ++i) {
- printf("%02x ", p3[i]);
- }
- printf("\n");
- printf("密 文: ");
- for (int i = 0; i < 16; ++i) {
- printf("%02x ", c1[i]);
- }
-
- cout << endl << "|-------------------------CFB解密 Test----------------------------|" << endl;
- cout << "密 文: ";
- sm4_cfb_decrypt(key, key, 32, c1, p2);
- for (int i = 0; i < 16; ++i) {
- printf("%02x ", c1[i]);
- }
- printf("\n");
- printf("明 文: ");
- for (int i = 0; i < 16; ++i) {
- printf("%02x ", p2[i]);
- }
- cout << endl << endl << "|-------------------------OFB加密 Test----------------------------|" << endl;
- cout << "明 文: ";
- sm4_ofb_encrypt(key, key, 32, iv, c1);
- for (int i = 0; i < 16; ++i) {
- printf("%02x ", iv[i]);
- }
- printf("\n");
- printf("密 文: ");
- for (int i = 0; i < 16; ++i) {
- printf("%02x ", c1[i]);
- }
- cout << endl << "|-------------------------OFB解密 Test----------------------------|" << endl;
- cout << "密 文: ";
- sm4_ofb_decrypt(key, key, 32, c1, p2);
- //expect_equal("sm4_ofb", p1, p2, 32);
- for (int i = 0; i < 16; ++i) {
- printf("%02x ", c1[i]);
- }
- printf("\n");
- printf("明 文: ");
- for (int i = 0; i < 16; ++i) {
- printf("%02x ", p2[i]);
- }
- }
-
- static void sm4_ctx_test(int mode, const char* name) {
- uint8_t key[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 };
-
- uint8_t p1[32];
- uint8_t p2[32];
- uint8_t c1[32];
- for (int i = 0; i < 32; ++i) {
- p1[i] = (i * i) & 0xff;
- }
- memset(p2, 0, 32);
- memset(c1, 0, 32);
-
- const uint8_t* iv = NULL;
- if (mode != SM4_ECB_MODE) {
- iv = key;
- }
-
- sm4_ctx_t ctx_en;
- sm4_ctx_t ctx_de;
- int r = sm4_init(&ctx_en, mode, key, iv);
- if (r != 0) {
- printf("sm4_init(%s | SM4_ENCRYPT) FAIL!\n", name);
- return;
- }
- r = sm4_init(&ctx_de, mode, key, iv);
- if (r != 0) {
- printf("sm4_init(%s | SM4_DECRYPT) FAIL!\n", name);
- return;
- }
-
- r = sm4_encrypt(&ctx_en, 16, p1, c1);
- r = sm4_encrypt(&ctx_en, 16, p1 + 16, c1 + 16);
- if (r != 0) {
- printf("sm4_encrypt(%s) FAIL!\n", name);
- return;
- }
- r = sm4_decrypt(&ctx_de, 32, c1, p2);
- if (r != 0) {
- printf("sm4_decrypt(%s) FAIL!\n", name);
- return;
- }
-
- expect_equal(name, p1, p2, 32);
- }
- };
-
-
-
- int main() {
-
- SM4Test::sm4_test();
-
- while (1) { }
-
- }
-
- /**
- * (主函数替换)
- * .利用该主函数中可对文件进行加解密
- * \param argc 控制台参数个数
- * \param argv (本程序)文件路径 +/-
- * \return
- *//*
- int main(int argc, char* argv[])
- {
- cout << "argc=" << argc << endl;
- cout << "argv[0]=" << argv[0] << endl;
- cout << "argv[1]=" << argv[1] << endl;
- cout << "argv[2]=" << argv[2] << endl;
- FILE* fpr, * fpw;//注意 FILE 为全大写
- char ch;// key = 0xfa;//初始密钥
- uint8_t key[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 };
- //命令行参数必须是3个,且第3个参数必须是+/-
- if (argc != 3 || *argv[2] != '+' && *argv[2] != '-')
- {
- printf("usage: 可执行文件名 +/-");
- return 0;
- }
- //以读二进制文件的方式打开指定文件 argv[1] 为文件路径
- if ((fpr = fopen(argv[1], "rb")) == NULL)
- {
- printf("cannot open this file");
- return 0;
- }
- //以读写二进制文件的方式打开指定文件
- //因为会不断对fpw进行写操作【逐字符写】,
- //为避免后一次写操作覆盖了前一次内容,不可使用"w+"
- if ((fpw = fopen(argv[1], "rb+")) == NULL)
- {
- printf("cannot open file");
- return 0;
- }
- //逐字符读取文件fpr中,直至到达文件尾(EOF表示文件尾,值为-1)
- //设置 定长数组 装二进制数16位
- uint8_t chs[16];
- uint8_t cipher[16];
- int nn = 0;//计数器 记录chs数组目前长度
- cout << "now nn = " << nn << endl;
- while ((ch = fgetc(fpr)) != EOF)
- {
- cout << "读到第" << nn << "个字符"<<endl ;
- if (nn == 16) { //若数组内长度为16 (满一组) 数组从下标0开始填充
- nn = 0;
- cout << "读到的组为" << endl;
- for (int i = 0; i < 16; ++i) {
- printf("%02x ", chs[i]);
- }
- for (int i = 0; i <= 15; i++)
- chs[i] = 0;
- }
- else if(nn != 16){
- chs[nn] = ch;
- nn++;
- }
- if(nn == 16){//chs内为一组 //将读取到的字符加密/解密后写到文件fpw中
- if (*argv[2] == '+') //加密chs 返回char char* 再写入文件
- sm4_ecb_encrypt(key, 16, chs, cipher); //此时chs为明文 cipher为密文
- else if (*argv[2] == '-')
- sm4_ecb_decrypt(key, 16, chs, cipher);//此时 chs为密文 cipher为明文
- for (int i = 0; i < 15; i++)
- fputc(cipher[i], fpw);
- // fputc(ch ^ key, fpw);
- }
- }
- cout << "now nn = " << nn << endl;
- if (nn != 17) {//最后一组还没写入文件 再写一次
- cout << "最后一组为" << endl;
- for (int i = 0; i < 16; ++i) {
- printf("%02x ", chs[i]);
- }
- if (*argv[2] == '+') //加密chs 返回char char* 再写入文件
- sm4_ecb_encrypt(key, 16, chs, cipher); //此时chs为明文 cipher为密文
- else if (*argv[2] == '-')
- sm4_ecb_decrypt(key, 16, chs, cipher);//此时 chs为密文 cipher为明文
- for (int i = 0; i < 15; i++)
- fputc(cipher[i], fpw);
- }
- if (*argv[2] == '+') cout << "文件加密成功!" << endl;
- if (*argv[2] == '-') cout << "文件解密成功!" << endl;
- fclose(fpr);
- fclose(fpw);
- return 0;
- }*/
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。