c/c++实现SM4加密解密算法

  • 代码实现
    • sm4.h
    • sm4.cpp
    • main.cpp

代码实现

sm4.h

/** @Author: Jinzhuo-li* @Date: 2021-10-14 16:27:19* @LastEditTime: 2021-10-25 15:28:41* @LastEditors: Please set LastEditors* @Description: In User Settings Edit* @FilePath: \文档*/
/**   * \file sm4.h   **/
#ifndef _BASE_SM4_H
#define _BASE_SM4_H#define SM4_ENCRYPT 1
#define SM4_DECRYPT 0#define SM4_PADDING_PKCS7 1
#define SM4_PADDING_ZERO 0#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <memory.h>
#include <stdint.h>/**   * \brief          SM4 context structure   */
typedef struct
{int mode;             /*!<  encrypt/decrypt   */unsigned long sk[32]; /*!<  SM4 subkeys       */int padding_type;     /*!<  none/pkcs7/0   */
} 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   */void sm4_crypt_ecb(sm4_context *ctx,int mode,int length,unsigned char *input,unsigned char *output);void sm4_crypt_ecb_pkcs7(sm4_context *ctx,int mode,int length,unsigned char *input,unsigned char *output);#ifdef __cplusplus
}
#endif#endif /* sm4.h */

sm4.cpp


#include "sm4.h"
#include <string.h>
#include <stdio.h>/*   * 32-bit integer manipulation macros (big endian)   */
#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#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   /* 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 */
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"   */
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)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)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.   */
static unsigned long sm4F(unsigned long x0, unsigned long x1, unsigned long x2, unsigned long x3, unsigned long rk)
{return (x0 ^ sm4Lt(x1 ^ x2 ^ x3 ^ rk));
}/* private function:   * Calculating round encryption key.   * args:    [in] a: a is a 32 bits unsigned value;   * return: sk[i]: i{0,1,2,3,...31}.   */
static unsigned long sm4CalciRK(unsigned long ka)
{unsigned long bb = 0;unsigned long rk = 0;unsigned char a[4];unsigned char b[4];PUT_ULONG_BE(ka, a, 0)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)rk = bb ^ (ROTL(bb, 13)) ^ (ROTL(bb, 23));return rk;
}static void sm4_setkey(unsigned long SK[32], unsigned char key[16])
{unsigned long MK[4];unsigned long k[36];unsigned long i = 0;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);k[0] = MK[0] ^ FK[0];k[1] = MK[1] ^ FK[1];k[2] = MK[2] ^ FK[2];k[3] = MK[3] ^ FK[3];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   *   */
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];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)while (i < 32){ulbuf[i + 4] = sm4F(ulbuf[i], ulbuf[i + 1], ulbuf[i + 2], ulbuf[i + 3], sk[i]);// #ifdef _DEBUG//        printf("rk(%02d) = 0x%08x,  X(%02d) = 0x%08x \n",i,sk[i], i, ulbuf[i+4] );// #endifi++;}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_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_DECRYPT;// SM4_ENCRYPT;sm4_setkey(ctx->sk, key);for (i = 0; i < 16; i++){SWAP(ctx->sk[i], ctx->sk[31 - i]);}
}/*********************************************************************************************** @brief sm4算法的块加密,使用ECB的pkcs7填充模式,默认长度为128位* @param ctx (传入) sm4算法内部的数据结构体* @param mode (传入) 使用模式,表示加密还是解密,格式:1(加密),0(解密)* @param length (传入) 待加密字符串的HEX数组的长度* @param input (传出) 待加密字符串的HEX数组* @param output (传入) 加密后的HEX数组**********************************************************************************************/
void sm4_crypt_ecb(sm4_context *ctx,int mode,int length,unsigned char *input,unsigned char *output)
{while (length > 0){sm4_one_round(ctx->sk, input, output);input += 16;output += 16;length -= 16;}
}/*********************************************************************************************** @brief sm4算法的块加密,使用ECB的pkcs7填充模式,默认长度为128位* @param ctx (传入) sm4算法内部的数据结构体* @param mode (传入) 使用模式,表示加密还是解密,格式:1(加密),0(解密)* @param length (传入) 待加密字符串的HEX数组的长度* @param input (传出) 待加密字符串的HEX数组* @param output (传入) 加密后的HEX数组**********************************************************************************************/
void sm4_crypt_ecb_pkcs7(sm4_context *ctx,int mode,int length,unsigned char *input,unsigned char *output)
{if (ctx->padding_type != SM4_PADDING_PKCS7){printf(" SM4 Not Set PKCS7 padding mode,padding type:%d \r\n",ctx->padding_type);return;}int out_len = length;unsigned char *pOut = output;unsigned char *input_new = NULL;unsigned char *p = NULL;int input_new_len = length + 16;int diff = 16 - length % 16;if (mode == SM4_ENCRYPT){if (diff > 0){input_new = (unsigned char *)malloc(input_new_len);if (input_new == NULL){free(input_new);input_new = NULL;p = NULL;return;}p = input_new;memset(input_new, 0, input_new_len);memcpy(input_new, input, length);int i = 0;for (; i < diff; i++){p[length + i] = diff;}length = length + i;}}if (input_new != NULL){while (length > 0){sm4_one_round(ctx->sk, p, output);p += 16;output += 16;length -= 16;}free(input_new);input_new = NULL;p = NULL;}else{while (length > 0){sm4_one_round(ctx->sk, input, output);input += 16;output += 16;length -= 16;}}if (mode == SM4_DECRYPT){int p = pOut[out_len - 1];memset(pOut + out_len - p, 0, p);out_len -= p;}
}

main.cpp

#include <cstdio>
#include <string.h>
#include "sm4.h"/*********************************************************************************************** @brief 使用sm4算法的ECB模式,使用pkg7填充方式进行解密,将HEX字符串转为ASCII字符串* @param key (传入) sm4算法的密钥,格式:ASCII,如123456abcd* @param in (传入) 待解密的HEX字符串,格式:HEX* @param out (传出) 解密后的明文字符串,格式:ASCII,支持中文* sm4_setkey_dec和sm4_crypt_ecb_pkcs7是sm.h原始接口,加解密都一样,区别是加密SM4_ENCRYPT,解密SM4_DECRYPT**********************************************************************************************/
int GetSM4Decrypto(const unsigned char* key, const unsigned char* in, unsigned char* out)
{unsigned char arrKey[32] = { 0 };unsigned char arrOutHex[1024] = { 0 };int len = -1;sm4_context ctx;ctx.padding_type = SM4_PADDING_PKCS7;len = ascii2HexArray(key, strlen(key), arrKey);//printf_ArrHex(arrKey, strlen(arrKey));sm4_setkey_dec(&ctx, arrKey);sm4_crypt_ecb_pkcs7(&ctx, SM4_DECRYPT, 224, in, arrOutHex);//SM4_ENCRYPTsprintf(out, "%s", arrOutHex);return len;
}int main(void)
{char key[32];              //加解密KEYchar data2[512] = { 0 };//加密数据char result[1024] = { 0 };//解密结果//这是解密伪代码,加密只需要在里更改SM4_ENCRYPTint len = GetSM4Decrypto(key, data2, result);system("pause");return 0;
}

版权声明:拷贝、转载请附上本文连接

【c++算法】《c/c++实现SM4加密解密算法》相关推荐

  1. 国密SM9算法C++实现之七:加密解密算法

    SM9算法C++实现系列目录: 基于JPBC的SM9算法的java实现与测试 国密SM9算法C++实现之0:源码下载地址 国密SM9算法C++实现之一:算法简介 国密SM9算法C++实现之二:测试工具 ...

  2. rsa加解密算法报告c语言,RSA加密解密算法c语言程序Word版

    <RSA加密解密算法c语言程序Word版>由会员分享,可在线阅读,更多相关<RSA加密解密算法c语言程序Word版(5页珍藏版)>请在人人文库网上搜索. 1.传播优秀Word版 ...

  3. 使用Bouncy Castle(pom版本:bcprov-jdk15on 1.59)中SM4 加密解密算法 ECB

    SM4 加密算法 加密 SM4算法是一种分组密码算法.其分组长度为128bit,密钥长度也为128bit. 加密算法与密钥扩展算法均采用32轮非线性迭代结构,以字(32位)为单位进行加密运算,每一次迭 ...

  4. c++/c SM4加密解密算法代码实现

    #include <openssl/sms4.h>int main(void) {//加密参数初始化sms4_key_t sms4_key_enc;unsigned char *plain ...

  5. 加密解密算法|使用C语言实现加密解密算法XTEA

    一.前言     数据通信时我们经常用到加密,尤其在单片机开发中计算能力有限,因此找到一个适合单片机加密的方式格外的重要,今天介绍一下XTEA加密算法. 在数据的加解密领域,算法分为对称密钥与非对称密 ...

  6. 【Android 安全】DEX 加密 ( Java 工具开发 | 加密解密算法 API | 编译代理 Application 依赖库 | 解压依赖库 aar 文件 )

    文章目录 一.加密解密算法 API 二.编译代理 Application 依赖库 三.解压代理 Application 依赖库 aar 文件 参考博客 : [Android 安全]DEX 加密 ( 常 ...

  7. 简单的加密/解密算法_/c++

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/qq_36557960/article/details/79299093 关于加密和解密问题,有的加密 ...

  8. sm4加密 解密(oc)

    前几天项目用到sm4加密解密,加密为十六进制字符串,再将十六进制字符串解密.网上百度了下,sm4是密钥长度和加密明文加密密文都为16个字节十六进制数据,网上的sm4 c语言算法很容易搜到,笔者刚开始没 ...

  9. java 加密_Java版SMS4加密解密算法

    特别说明:该专栏文章均来源自微信公众号<大数据实战演练>,欢迎关注! 前言 最近工作中需要实现HBase自定义扩展sms4加密,今天就先来说一下Java版的SMS4加密解密算法的具体实现. ...

  10. 提供一个基于.NET的加密/解密算法

    提供一个基于.NET SymmetricAlgorithm 类的.带私钥的加密/解密算法的包装类.使用方法: symmcrypto de = new SymmCrypto(SymmCrypto.Sym ...

最新文章

  1. 如何在ubuntu下安装合适的翻译词典
  2. 使用mysql++写入BLOB数据
  3. 互联网高可用架构技术实践
  4. 《软技能:代码之外的生存指南》一一35.2 找出你的短板
  5. python3GUI--磁力搜索工具(附tk源码)
  6. Win7局域网内找不到其他电脑怎么解决
  7. threejs 绘制星空
  8. C++ Qt实现WPS、浏览器tab页面
  9. Flash:形变动画的制作
  10. DA转换器原理及应用(报告)
  11. MAC通过ZOC远程访问Linux
  12. Linux 内核中RAID5源码详解之守护进程raid5d
  13. Figma#1: 图形绘制
  14. 视频格式转换器如何截取视频片段
  15. 中国腹肌刺激器行业发展动态与投资前景预测报告(2022-2027)
  16. yolov 论文发表在什么期刊上_基于红外热成像与 YOLOv
  17. HTML中Table标签的属性及应用
  18. DB2 错误解决方案:A system temporary table space with sufficient page size does not exist.. SQLCODE=-1585,
  19. 前端三大框架Vue框架详解
  20. 高通骁龙820A芯片,众多品牌为其站台

热门文章

  1. 注册OCX控件并在VS2013的mfc程序中使用及常见问题总结
  2. Conficker蠕虫作者可随时引爆“网络核武”
  3. java模拟器野人岛2,生存战争野人岛2最终版
  4. Android布局详解之一:FrameLayout
  5. 91位图和bigemap大地图的区别
  6. 华为交换机冗余链路(VRRP)和vlan负载均衡
  7. (原创)骑士人才系统(74CMS) 阿里短信接口 不影响后续升级
  8. linux 下载hbase源码,linux上安装hbase(示例代码)
  9. Vmlogin防关联超级浏览器Selenium浏览器自动化详细教程
  10. windows系统腾讯qq自带截图工具自动滚动截长图方法