本文介绍SM4软加密算法算法C/C++代码实现,可用于本地文件的加密使用。 两种模式 1、对整个文件进行加密解密 2、对字符串加密解密,本人使用的场景是将字符串先加密,然后将密文写入到文件保存,读取时,先读取再解密使用。 由于sm4加密时一次为128bit即16个字节,分组加密时可能会补字节,所以文件保存时宜记录加密前后数据长度。 以下为源码,亲测可用,vs2015,Linux下编译报错可将<string>换<string.h> Sm4.h头文件如下: - //sm4.h
- #pragma once
- /**
- * \file sm4.h
- */
- #define SM4_ENCRYPT 1
- #define SM4_DECRYPT 0
-
- /**
- * \brief SM4 context structure 上下文结构
- */
- typedef struct
- {
- int mode; /*!< encrypt/decrypt 控制加密还是解密 */
- unsigned long sk[32]; /*!< SM4 subkeys 存放每次迭代的轮密钥 */
- }sm4_context;
-
-
- #ifdef __cplusplus
- extern "C" {
- #endif
- //
- /**
- * \brief SM4 key schedule (128-bit, encryption)设置加密秘钥
- *
- * \param ctx SM4 context to be initialized
- * \param key 16-byte secret key
- */
- void sm4_setkey_enc(sm4_context *ctx, unsigned char key[16]);
-
- /**
- * \brief SM4 key schedule (128-bit, decryption)
- *
- * \param ctx SM4 context to be initialized
- * \param key 16-byte secret key
- */
- void sm4_setkey_dec(sm4_context *ctx, unsigned char key[16]);
-
- /**
- * \brief SM4-ECB block encryption/decryption
- * \param ctx SM4 context
- * \param mode SM4_ENCRYPT or SM4_DECRYPT
- * \param length length of the input data
- * \param input input block
- * \param output output block
- */
- int sm4_crypt_ecb(sm4_context *ctx,
- int mode,
- int length,
- unsigned char *input,
- unsigned char *output);
-
- /**
- * \brief SM4-CBC buffer encryption/decryption
- * \param ctx SM4 context
- * \param mode SM4_ENCRYPT or SM4_DECRYPT
- * \param length length of the input data
- * \param iv initialization vector (updated after use)
- * \param input buffer holding the input data
- * \param output buffer holding the output data
- */
- void sm4_crypt_cbc(sm4_context *ctx,
- int mode,
- int length,
- unsigned char iv[16],
- unsigned char *input,
- unsigned char *output);
-
- #ifdef __cplusplus
- }
- #endif
- #include <iostream>
- class Sm4EncDec
- {
- public:
- /**********************************************************************************************
- * @brief 构造函数 密钥赋值
- **********************************************************************************************/
- Sm4EncDec();
-
- /**********************************************************************************************
- * @brief 构造函数 密钥赋值
- * @param SrcPath (传入) 需要赋值的密钥
- **********************************************************************************************/
- Sm4EncDec(unsigned char key[]);
-
- /**********************************************************************************************
- * @brief 加密文件
- * @param SrcPath (传入) 加密源文件名
- * @param DestPath (传出) 加密后的密文文件名
- **********************************************************************************************/
- void Encrypt(std::string DestPath, std::string SrcPath);
-
- /**********************************************************************************************
- * @brief 解密文件
- * @param SrcPath (传入) 解密源文件名
- * @param DestPath (传出) 解密后的明文文件名
- **********************************************************************************************/
- void Decrypt(std::string DestPath, std::string SrcPath);
-
-
- /**********************************************************************************************
- * @brief 加密文件
- * @param SrcPath (传入传出) 加密源文件名
- **********************************************************************************************/
- void Encrypt(std::string SrcPath);
-
- /**********************************************************************************************
- * @brief 解密文件
- * @param SrcPath (传入传出) 解密源文件名
- **********************************************************************************************/
- void Decrypt(std::string SrcPath);
-
-
- /**********************************************************************************************
- * @brief 加密字符串
- * @param SrcPath (传入) 需要加密的字符串
- * @param DestPath (传出) 加密后的密文字符串
- **********************************************************************************************/
- int Encrypt(unsigned char *destBuf, unsigned char *srcStr, int srcLen);
-
- /**********************************************************************************************
- * @brief 解密字符串
- * @param SrcPath (传入) 需要解密的字符串
- * @param DestPath (传出) 解密后的明文字符串
- **********************************************************************************************/
- int Decrypt(unsigned char *destBuf, unsigned char *srcStr, int srcLen);
-
- private:
- //密钥
- unsigned char key[16];
- };
复制代码Sm4.cpp - //sm4.cpp
- #pragma pack(4)
- #include "sm4.h"
- #include <string.h>
- #include <stdio.h>
- #include <iostream>
- #include <algorithm>
-
- /*
- * 32-bit integer manipulation macros (big endian)
- * //将字符型数组b的第i到第i+3位的二进制拼接成一个4*8=32bit的整数,存入n中
- */
- #ifndef GET_ULONG_BE
- #define GET_ULONG_BE(n,b,i) \
- { \
- (n) = ( (unsigned long) (b)[(i) ] << 24 ) \
- | ( (unsigned long) (b)[(i) + 1] << 16 ) \
- | ( (unsigned long) (b)[(i) + 2] << 8 ) \
- | ( (unsigned long) (b)[(i) + 3] ); \
- }
- #endif
-
- //将整数n的32位的二进制表示转换为4个char的数组,存入数组b的第i到第i+3位
- #ifndef PUT_ULONG_BE
- #define PUT_ULONG_BE(n,b,i) \
- { \
- (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
- (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
- (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
- (b)[(i) + 3] = (unsigned char) ( (n) ); \
- }
- #endif
-
- /*
- *rotate shift left marco definition
- * 循环移位
- */
- #define SHL(x,n) (((x) & 0xFFFFFFFF) << n)
- #define ROTL(x,n) (SHL((x),n) | ((x) >> (32 - n)))
-
- #define SWAP(a,b) { unsigned long t = a; a = b; b = t; t = 0; }
-
- /*
- * Expanded SM4 S-boxes S盒
- /* Sbox table: 8bits input convert to 8 bits output*/
-
- static const unsigned char SboxTable[16][16] =
- {
- { 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 }
- };
-
- /* System parameter 系统参数FK */
- static const unsigned long FK[4] = { 0xa3b1bac6,0x56aa3350,0x677d9197,0xb27022dc };
-
- /* fixed parameter 固定参数 */
- static const unsigned long 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
- };
-
-
- /*
- * private function:
- * look up in SboxTable and get the related value.
- * args: [in] inch: 0x00~0xFF (8 bits unsigned value).
- */
- static unsigned char sm4Sbox(unsigned char inch)
- {
- unsigned char *pTable = (unsigned char *)SboxTable;
- unsigned char retVal = (unsigned char)(pTable[inch]);
- return retVal;
- }
-
- /*
- * private F(Lt) function:
- * "T algorithm" == "L algorithm" + "t algorithm".
- * args: [in] a: a is a 32 bits unsigned value;
- * return: c: c is calculated with line algorithm "L" and nonline algorithm "t"
- */
- /*
- 合成置换T ,由非线性变换t和线性变换L复合而成
- 将输入的整数ka转换为8比特一个的字符PUT_ULONG_BE(ka,a,0),
- 然后使用S盒进行非线性变换,再将变换结果转换为32比特的整数
- GET_ULONG_BE(bb,b,0),最后对得到的32位整数bb进行线性变换:
- c = bb异或(bb << <2)异或(bb << <10)异或(bb << <18)异或(bb << <24)。
- 从而得到复合变换的结果c。
- */
-
- static unsigned long sm4Lt(unsigned long ka)
- {
- unsigned long bb = 0;
- unsigned long c = 0;
- unsigned char a[4];
- unsigned char b[4];
-
- PUT_ULONG_BE(ka, a, 0);
-
- //函数T与密钥扩展中的函数T相同
- b[0] = sm4Sbox(a[0]);
- b[1] = sm4Sbox(a[1]);
- b[2] = sm4Sbox(a[2]);
- b[3] = sm4Sbox(a[3]);
-
- GET_ULONG_BE(bb, b, 0);
-
- //L处理变为B与左移2位及左移10位及左移18位及左移24位的B进行异或处理
- c = bb ^ (ROTL(bb, 2)) ^ (ROTL(bb, 10)) ^ (ROTL(bb, 18)) ^ (ROTL(bb, 24));
- return c;
- }
-
- /*
- * private F function:
- * Calculating and getting encryption/decryption contents.
- * args: [in] x0: original contents;
- * args: [in] x1: original contents;
- * args: [in] x2: original contents;
- * args: [in] x3: original contents;
- * args: [in] rk: encryption/decryption key;
- * return the contents of encryption/decryption contents.
- */
- /*
- 轮函数F 每一轮加密中,输入为(x0, x1, x2, x3),xi为32位比特,
- 共计128比特。通过x0^sm4Lt(x1^x2^x3^rk)得到该轮加密的结果。
- */
- static unsigned long sm4F(unsigned long x0, unsigned long x1, unsigned long x2, unsigned long x3, unsigned long rk)
- {
- //明文拆分后的4个字的后3个字与该轮的子密钥进行异或处理
- //经过一个函数T得到C,之后再将明文拆分后的第一个字与C进行异或。
- return (x0^sm4Lt(x1^x2^x3^rk));
- }
-
-
- /*
- * 变换T’ 先进行Sbox的非线性替换,然后进行线性变换,
- * 线性变换L改为了: rk = bb ^ (ROTL(bb, 13)) ^ (ROTL(bb, 23));
- */
-
- static unsigned long sm4CalciRK(unsigned long ka)
- {
- unsigned long bb = 0;
- unsigned long rk = 0;
- unsigned char a[4];
- unsigned char b[4];
- //将A拆分为4个8bit的字节
- PUT_ULONG_BE(ka, a, 0)
- //S盒变换
- b[0] = sm4Sbox(a[0]);
- b[1] = sm4Sbox(a[1]);
- b[2] = sm4Sbox(a[2]);
- b[3] = sm4Sbox(a[3]);
-
- //4个S盒的输出组成32位的值B
- GET_ULONG_BE(bb, b, 0)
-
- //B与左移13位及左移23位的B进行异或处理作为函数T的输出C
- rk = bb ^ (ROTL(bb, 13)) ^ (ROTL(bb, 23));
- return rk;
- }
-
- /*
- * 密钥扩展算法,对当前传入的主密钥进行32轮的迭代,
- * 每次迭代的轮密钥都被存放到ctx结构中的sk数组中
- * 类似于加密中的操作,首先通过宏将初始的密钥拆分为4个32位bit的字,
- * MK0,MK1,MK2,MK3,并为计算各轮密钥预先准备好初始值
- */
- static void sm4_setkey(unsigned long SK[32], unsigned char key[16])
- {
- unsigned long MK[4]; //拆分后的4个32bit秘钥
- unsigned long k[36]; //存放MK与系统参数FK异或运算得到的K
- unsigned long i = 0;
-
- //将密钥拆分为4字
- GET_ULONG_BE(MK[0], key, 0);
- GET_ULONG_BE(MK[1], key, 4);
- GET_ULONG_BE(MK[2], key, 8);
- GET_ULONG_BE(MK[3], key, 12);
-
- //线性变换 L 位移异或,与系统参数的每个字做异或运算得到(K0, K1, K2, K3)
- k[0] = MK[0] ^ FK[0];
- k[1] = MK[1] ^ FK[1];
- k[2] = MK[2] ^ FK[2];
- k[3] = MK[3] ^ FK[3];
-
- //对于第i轮的密钥SK[i] ,其是由k[i]
- //和对k[i+1]^k[i+2]^k[i+3]^CK[i]的复合变换T’异或得到的:
- for (; i < 32; i++)
- {
- k[i + 4] = k[i] ^ (sm4CalciRK(k[i + 1] ^ k[i + 2] ^ k[i + 3] ^ CK[i]));
- SK[i] = k[i + 4];
- }
- }
-
- /*
- * SM4 standard one round processing
- *
- */
-
- /*
- * 轮加密
- * 先将明文输入input的整数,放入ulbuf[4]中,
- * 然后迭代地调用函数static unsigned long sm4F() 进行32轮加密
- * 每一轮加密都需要使用之前的结果 ulbuf[i], ulbuf[i+1], ulbuf[i+2], ulbuf[i+3]
- * 和该轮的密钥 sk[i],产生出该轮的密文 ulbuf[i+4],
- * 最后的密文存储在ulbuf[35]~ulbuf[32]中,转换为字符数组的形式放入output中。
- */
- static void sm4_one_round(unsigned long sk[32],
- unsigned char input[16],
- unsigned char output[16])
- {
- unsigned long i = 0;
- unsigned long ulbuf[36];
-
- //将128bit的明文分成4个32bit的字X1,X2,X3,X4
- memset(ulbuf, 0, sizeof(ulbuf));
- GET_ULONG_BE(ulbuf[0], input, 0);
- GET_ULONG_BE(ulbuf[1], input, 4);
- GET_ULONG_BE(ulbuf[2], input, 8);
- GET_ULONG_BE(ulbuf[3], input, 12);
-
- //进行32轮的轮操作
- while (i < 32)
- {
- ulbuf[i + 4] = sm4F(ulbuf[i], ulbuf[i + 1], ulbuf[i + 2], ulbuf[i + 3], sk[i]);
- i++;
- }
-
- PUT_ULONG_BE(ulbuf[35], output, 0);
- PUT_ULONG_BE(ulbuf[34], output, 4);
- PUT_ULONG_BE(ulbuf[33], output, 8);
- PUT_ULONG_BE(ulbuf[32], output, 12);
- }
-
- /*
- * SM4 key schedule (128-bit, encryption) 设置加密秘钥
- */
- void sm4_setkey_enc(sm4_context *ctx, unsigned char key[16])
- {
- ctx->mode = SM4_ENCRYPT; /*!< SM4_ENCRYPT 加密 SM4_DECRYPT解密 */
- sm4_setkey(ctx->sk, key);
- }
-
- /*
- * SM4 key schedule (128-bit, decryption)
- */
- 设置解密秘钥 轮密钥的使用顺序相反
- void sm4_setkey_dec(sm4_context *ctx, unsigned char key[16])
- {
- int i;
- ctx->mode = SM4_ENCRYPT;
- sm4_setkey(ctx->sk, key);
- for (i = 0; i < 16; i++)
- {
- SWAP(ctx->sk[i], ctx->sk[31 - i]);
- }
- }
-
-
- /*
- * SM4-ECB block encryption/decryption
- * ECB模式密文被分割成分组长度相等的块(不足补齐),
- * 然后单独一个个加密,一个个输出组成密文。
- */
- int sm4_crypt_ecb(sm4_context *ctx,
- int mode,
- int length,
- unsigned char *input,
- unsigned char *output)
- {
- int retlen = 0;
- while (length > 0 )
- {
- sm4_one_round(ctx->sk, input, output);
- input += 16;
- output += 16;
- length -= 16;
- retlen += 16;
- }
- return retlen;
- }
-
- /*
- * SM4-CBC buffer encryption/decryption
- * 循环模式(链式),前一个分组的密文和当前分组的明文操作后再加密,
- * 增强破解难度。(不容易主动攻击,安全性好于ECB,是SSL、IPSec的标准)
- */
- void sm4_crypt_cbc(sm4_context *ctx,
- int mode,
- int length,
- unsigned char iv[16],
- unsigned char *input,
- unsigned char *output)
- {
- int i;
- unsigned char temp[16];
-
- if (mode == SM4_ENCRYPT)
- {
- while (length > 0)
- {
- for (i = 0; i < 16; i++)
- output[i] = (unsigned char)(input[i] ^ iv[i]);
-
- sm4_one_round(ctx->sk, output, output);
- memcpy(iv, output, 16);
-
- input += 16;
- output += 16;
- length -= 16;
- }
- }
- else /* SM4_DECRYPT */
- {
- while (length > 0)
- {
- memcpy(temp, input, 16);
- sm4_one_round(ctx->sk, input, output);
-
- for (i = 0; i < 16; i++)
- output[i] = (unsigned char)(output[i] ^ iv[i]);
-
- memcpy(iv, temp, 16);
-
- input += 16;
- output += 16;
- length -= 16;
- }
- }
- }
-
-
- //初始化密钥赋值 默认unsigned char key1[16] = { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10 };
- Sm4EncDec::Sm4EncDec()
- {
- memset(key, 0, 16);
- unsigned char key1[16] = { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10 };
- memcpy(key, key1,16);
- }
-
- Sm4EncDec::Sm4EncDec(unsigned char _key[])
- {
- memset(key,0,16);
- if (_key == NULL)
- Sm4EncDec();
- memcpy(key, _key, 16);
- }
-
- //加密
- void Sm4EncDec::Encrypt(std::string DestPath,std::string SrcPath)
- {
- if (SrcPath.empty())
- return;
-
- FILE* InFile = fopen(SrcPath.c_str(), "rb");
- if (InFile == NULL)
- {
- return;
- }
-
- FILE* OutFile = fopen(DestPath.c_str(), "wb");
- if (OutFile == NULL)
- {
- fclose(InFile);
- return;
- }
-
- fseek(InFile, 0, SEEK_END);
- long filelen = ftell(InFile);
- fseek(InFile, 0, SEEK_SET);
-
- long last = filelen;
- long offset = 1024;
-
- unsigned char* SrcBuffer = new unsigned char[offset];
- unsigned char* DestBuffer = new unsigned char[offset];
- sm4_context ctx;
-
- while (last > 0)
- {
- memset(SrcBuffer, 0, offset);
- memset(DestBuffer, 0, offset);
- offset = std::min(offset, last);
-
- fread(SrcBuffer, offset, 1, InFile);
- last -= offset;
-
- //设置秘钥
- sm4_setkey_enc(&ctx, key);
- //加密
- int elen = sm4_crypt_ecb(&ctx, SM4_ENCRYPT, offset, SrcBuffer, DestBuffer); //SM4_ENCRYPT为加密 SM4_DECRYPT为解密
-
- fwrite(DestBuffer, elen, 1, OutFile);
- }
- delete[]SrcBuffer;
- delete[]DestBuffer;
- fclose(InFile);
- fclose(OutFile);
-
- return;
- }
-
- //解密
- void Sm4EncDec::Decrypt(std::string DestPath, std::string SrcPath)
- {
- if (SrcPath.empty())
- return;
-
- FILE* InFile = fopen(SrcPath.c_str(), "rb");
- if (InFile == NULL)
- {
- return;
- }
-
- FILE* OutFile = fopen(DestPath.c_str(), "wb");
- if (OutFile == NULL)
- {
- fclose(InFile);
- return;
- }
-
- fseek(InFile, 0, SEEK_END);
- long filelen = ftell(InFile);
- fseek(InFile, 0, SEEK_SET);
-
- long last = filelen;
- long offset = 1024;
- sm4_context ctx;
- unsigned char* SrcBuffer = new unsigned char[offset];
- unsigned char* DestBuffer = new unsigned char[offset];
- while (last > 0)
- {
- memset(SrcBuffer, 0, offset);
- memset(DestBuffer, 0, offset);
-
- offset = std::min(offset, last);
-
- fread(SrcBuffer, offset, 1, InFile);
-
- sm4_setkey_dec(&ctx, key);
- int dlen = sm4_crypt_ecb(&ctx, SM4_DECRYPT, offset, SrcBuffer, DestBuffer); //SM4_ENCRYPT为加密 SM4_DECRYPT为解密
-
- fwrite(DestBuffer, dlen, 1, OutFile);
- last -= offset;
- }
- delete[]SrcBuffer;
- delete[]DestBuffer;
- fclose(InFile);
- fclose(OutFile);
- return;
- }
-
- //加密
- void Sm4EncDec::Encrypt(std::string SrcPath)
- {
- FILE* InFile = fopen(SrcPath.c_str(), "rb+");
- if (InFile == NULL)
- {
- return;
- }
- fseek(InFile, 0, SEEK_END);
- int filelen = ftell(InFile);
- fseek(InFile, 0, SEEK_SET);
-
- int last = filelen;
- int offset = 1024;
-
- unsigned char* SrcBuffer = new unsigned char[offset];
- unsigned char* DestBuffer = new unsigned char[offset];
-
- sm4_context ctx;
-
- int fileindex = 0;
-
- while (last > 0)
- {
- memset(SrcBuffer, 0, offset);
- memset(DestBuffer, 0, offset);
-
- offset = std::min(offset, last);
-
- fseek(InFile, fileindex,SEEK_SET);
-
- int rn = fread(SrcBuffer,offset,1, InFile);
-
- fileindex = ftell(InFile); //读位置
-
- //设置秘钥
- sm4_setkey_enc(&ctx, key);
- //加密
- int retlen = sm4_crypt_ecb(&ctx, SM4_ENCRYPT, offset, SrcBuffer, DestBuffer); //SM4_ENCRYPT为加密 SM4_DECRYPT为解密
-
- fseek(InFile, fileindex - offset, SEEK_SET);
-
- int wn = fwrite(DestBuffer, retlen,1, InFile);
- fseek(InFile, fileindex, SEEK_SET);
-
- last -= offset;
- }
- fclose(InFile);
- return;
- }
-
- //解密
- void Sm4EncDec::Decrypt( std::string SrcPath)
- {
- FILE* InFile = fopen(SrcPath.c_str(), "rb+");
-
- if (InFile == NULL)
- {
- return;
- }
- sm4_context ctx;
-
- fseek(InFile, 0, SEEK_END);
- int filelen = ftell(InFile);
- fseek(InFile, 0, SEEK_SET);
-
- int last = filelen;
- int offset = 1024;
-
- unsigned char* SrcBuffer = new unsigned char[offset];
- unsigned char* DestBuffer = new unsigned char[offset];
-
- int fileindex =0;
-
- while (last > 0)
- {
- memset(SrcBuffer, 0, offset);
- memset(DestBuffer, 0, offset);
-
- offset = std::min(offset, last);
-
- fseek(InFile, fileindex, SEEK_SET);
- int tn = fread(SrcBuffer,offset,1, InFile);
- fileindex = ftell(InFile); //记录读的位置
-
- sm4_setkey_dec(&ctx, key);
- int retlen = sm4_crypt_ecb(&ctx, SM4_DECRYPT, offset, SrcBuffer, DestBuffer); //SM4_ENCRYPT为加密 SM4_DECRYPT为解密
-
- fseek(InFile, fileindex - offset,SEEK_SET);
- int wn = fwrite(DestBuffer, retlen,1, InFile);
- fseek(InFile, fileindex, SEEK_SET);
-
- last -= offset;
- }
-
- fclose(InFile);
- return;
- }
-
-
- //加密字符串
- int Sm4EncDec::Encrypt(unsigned char *destBuf, unsigned char *srcStr, int srcLen)
- {
- if (srcStr == NULL)
- return 0;
- int last = srcLen;
- int offset = 128;
- unsigned char* dest = destBuf;
- unsigned char* src = srcStr;
- sm4_context ctx;
- int retlen = 0;
- while (last > 0)
- {
- offset = std::min(offset, last);
-
- last -= offset;
- //设置秘钥
- sm4_setkey_enc(&ctx, key);
- //加密
- int elen = sm4_crypt_ecb(&ctx, SM4_ENCRYPT, offset, src, dest); //SM4_ENCRYPT为加密 SM4_DECRYPT为解密
-
- src += offset;
- dest += offset;
- retlen += elen;
- }
- return retlen;
- }
-
- //解密字符串
- int Sm4EncDec::Decrypt(unsigned char *destBuf, unsigned char *srcStr, int srcLen)
- {
- if (srcStr == NULL)
- return 0;
- int last = srcLen;
- int offset = 128;
- int retlen = 0;
-
- unsigned char* dest = destBuf;
- unsigned char* src = srcStr;
- sm4_context ctx;
-
- while (last > 0)
- {
- offset = std::min(offset, last);
-
- last -= offset;
- sm4_setkey_dec(&ctx, key);
- int dlen = sm4_crypt_ecb(&ctx, SM4_DECRYPT, offset, src, dest); //SM4_ENCRYPT为加密 SM4_DECRYPT为解密
-
- src += offset;
- dest += offset;
- retlen += dlen;
- }
- return retlen;
- }
-
- #pragma pack()
复制代码key为16字节,支持特殊字符,自测中文可用,加密文件或字符串支持中文特殊字符。 调用Sm4EncDec类成员Encrypt和Decrypt可实现加密解密。
|