【c++算法】《c/c++实现SM4加密解密算法》
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加密解密算法》相关推荐
- 国密SM9算法C++实现之七:加密解密算法
SM9算法C++实现系列目录: 基于JPBC的SM9算法的java实现与测试 国密SM9算法C++实现之0:源码下载地址 国密SM9算法C++实现之一:算法简介 国密SM9算法C++实现之二:测试工具 ...
- rsa加解密算法报告c语言,RSA加密解密算法c语言程序Word版
<RSA加密解密算法c语言程序Word版>由会员分享,可在线阅读,更多相关<RSA加密解密算法c语言程序Word版(5页珍藏版)>请在人人文库网上搜索. 1.传播优秀Word版 ...
- 使用Bouncy Castle(pom版本:bcprov-jdk15on 1.59)中SM4 加密解密算法 ECB
SM4 加密算法 加密 SM4算法是一种分组密码算法.其分组长度为128bit,密钥长度也为128bit. 加密算法与密钥扩展算法均采用32轮非线性迭代结构,以字(32位)为单位进行加密运算,每一次迭 ...
- c++/c SM4加密解密算法代码实现
#include <openssl/sms4.h>int main(void) {//加密参数初始化sms4_key_t sms4_key_enc;unsigned char *plain ...
- 加密解密算法|使用C语言实现加密解密算法XTEA
一.前言 数据通信时我们经常用到加密,尤其在单片机开发中计算能力有限,因此找到一个适合单片机加密的方式格外的重要,今天介绍一下XTEA加密算法. 在数据的加解密领域,算法分为对称密钥与非对称密 ...
- 【Android 安全】DEX 加密 ( Java 工具开发 | 加密解密算法 API | 编译代理 Application 依赖库 | 解压依赖库 aar 文件 )
文章目录 一.加密解密算法 API 二.编译代理 Application 依赖库 三.解压代理 Application 依赖库 aar 文件 参考博客 : [Android 安全]DEX 加密 ( 常 ...
- 简单的加密/解密算法_/c++
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/qq_36557960/article/details/79299093 关于加密和解密问题,有的加密 ...
- sm4加密 解密(oc)
前几天项目用到sm4加密解密,加密为十六进制字符串,再将十六进制字符串解密.网上百度了下,sm4是密钥长度和加密明文加密密文都为16个字节十六进制数据,网上的sm4 c语言算法很容易搜到,笔者刚开始没 ...
- java 加密_Java版SMS4加密解密算法
特别说明:该专栏文章均来源自微信公众号<大数据实战演练>,欢迎关注! 前言 最近工作中需要实现HBase自定义扩展sms4加密,今天就先来说一下Java版的SMS4加密解密算法的具体实现. ...
- 提供一个基于.NET的加密/解密算法
提供一个基于.NET SymmetricAlgorithm 类的.带私钥的加密/解密算法的包装类.使用方法: symmcrypto de = new SymmCrypto(SymmCrypto.Sym ...
最新文章
- 如何在ubuntu下安装合适的翻译词典
- 使用mysql++写入BLOB数据
- 互联网高可用架构技术实践
- 《软技能:代码之外的生存指南》一一35.2 找出你的短板
- python3GUI--磁力搜索工具(附tk源码)
- Win7局域网内找不到其他电脑怎么解决
- threejs 绘制星空
- C++ Qt实现WPS、浏览器tab页面
- Flash:形变动画的制作
- DA转换器原理及应用(报告)
- MAC通过ZOC远程访问Linux
- Linux 内核中RAID5源码详解之守护进程raid5d
- Figma#1: 图形绘制
- 视频格式转换器如何截取视频片段
- 中国腹肌刺激器行业发展动态与投资前景预测报告(2022-2027)
- yolov 论文发表在什么期刊上_基于红外热成像与 YOLOv
- HTML中Table标签的属性及应用
- DB2 错误解决方案:A system temporary table space with sufficient page size does not exist.. SQLCODE=-1585,
- 前端三大框架Vue框架详解
- 高通骁龙820A芯片,众多品牌为其站台
热门文章
- 注册OCX控件并在VS2013的mfc程序中使用及常见问题总结
- Conficker蠕虫作者可随时引爆“网络核武”
- java模拟器野人岛2,生存战争野人岛2最终版
- Android布局详解之一:FrameLayout
- 91位图和bigemap大地图的区别
- 华为交换机冗余链路(VRRP)和vlan负载均衡
- (原创)骑士人才系统(74CMS) 阿里短信接口 不影响后续升级
- linux 下载hbase源码,linux上安装hbase(示例代码)
- Vmlogin防关联超级浏览器Selenium浏览器自动化详细教程
- windows系统腾讯qq自带截图工具自动滚动截长图方法