SM4算法软件实现

合集下载

sm4算法原理

sm4算法原理

sm4算法原理
SM4 算法是国家密码管理局和暨南大学根据国家密码管理办法制
定的块密码算法,是国家信息安全标准GB/T 32905-2016中规定的高
级加密标准(AES)的替代产品。

它使用128位长的分组,使用128位
长的和256位长的密钥加密和解密数据,进行32轮迭代运算。

SM4 算法采用管控混合运算机制,采用32轮迭代和变换来确保
大量的运算运算量,采用分组变换,以其中的 S-网状结构来加强的运
算安全性。

此外,SM4 算法还采用了“一致性检查”,以保证数据的
有效性。

SM4 算法的安全特性主要体现在以下几点:首先,SM4 算法的运
算量足够大,使其更难以被暴力破解;其次,SM4 算法运算安全性更强,内在逻辑复杂,抗攻击性好;最后,SM4 算法运算效率高,可用
于数据加密和解密。

总之,SM4 算法是安全、高效的加解密算法,可实现安全性强、
运算量大,数据有效性和安全性的高度保密,并具有良好的实施性能,被广泛应用于无线通信,网络安全等领域。

nist抗量子密码算法

nist抗量子密码算法

nist抗量子密码算法一、引言随着量子计算技术的发展,传统的密码算法面临着被破解的风险。

为了应对这一挑战,美国国家标准和技术研究院(NIST)组织了一系列抗量子密码算法的评选,最终确定了几个具有代表性的抗量子密码算法,其中包括SM4分组密码算法。

本文将介绍SM4分组密码算法的基本原理、安全性分析、实现方法以及在网络安全中的应用。

二、基本原理SM4分组密码算法是一种分组密码,它将明文数据按照一定长度进行分组加密,每个分组称为一个块。

SM4分组密码采用32轮非线性迭代结构,每轮包括乘法预处理、S盒替换、置换等操作,最终输出密文块。

S盒是SM4分组密码算法中的关键部分,采用多项式代替方式,对输入比特进行替换,提高了密码的安全性。

三、安全性分析SM4分组密码算法采用了一系列抗量子攻击的技术,如S盒的选择、密钥调度器的设计等,使得该算法在面对量子计算攻击时具有较高的安全性。

首先,SM4分组密码算法的S盒采用了高强度的多项式,避免了常见的量子态破解方法。

其次,密钥调度器的设计也考虑了量子计算攻击的特点,通过复杂的乘积和移位操作,使得密钥空间更加复杂和难以破解。

此外,SM4分组密码算法还采用了分组密码特有的扩散和混淆机制,使得攻击者难以找到明文和密文之间的规律,进一步提高了安全性。

四、实现方法SM4分组密码算法的实现需要使用相应的加密软件和硬件设备。

在软件实现方面,可以采用C语言等高级语言进行编程实现。

在硬件实现方面,可以采用专门的芯片或处理器来实现SM4分组密码算法的硬件加速。

无论是在软件还是硬件实现中,都需要对算法的细节和参数进行仔细的选择和调整,以确保实现的安全性和性能。

五、应用场景SM4分组密码算法在网络安全中具有广泛的应用场景。

首先,它可以应用于数据加密、数字签名等领域,保护数据的机密性和完整性。

其次,它可以应用于网络通信中,确保通信的安全性。

此外,SM4分组密码算法还可以与其他密码算法结合使用,形成更加安全的加密体系。

商密算法SM2、SM3、SM4的用途和原理

商密算法SM2、SM3、SM4的用途和原理

商密算法SM2、SM3、SM4的⽤途和原理SM1对称密码SM1 算法是分组密码算法,分组长度为128位,密钥长度都为 128 ⽐特,算法安全保密强度及相关软硬件实现性能与 AES 相当,算法不公开,仅以IP核的形式存在于芯⽚中。

采⽤该算法已经研制了系列芯⽚、智能IC卡、智能密码钥匙、加密卡、加密机等安全产品,⼴泛应⽤于电⼦政务、电⼦商务及国民经济的各个应⽤领域(包括国家政务通、警务通等重要领域)。

SM2椭圆曲线公钥密码算法SM2算法就是ECC椭圆曲线密码机制,但在签名、密钥交换⽅⾯不同于ECDSA、ECDH等国际标准,⽽是采取了更为安全的机制。

另外,SM2推荐了⼀条256位的曲线作为标准曲线。

SM2标准包括总则,数字签名算法,密钥交换协议,公钥加密算法四个部分,并在每个部分的附录详细说明了实现的相关细节及⽰例。

SM2算法主要考虑素域Fp和F2m上的椭圆曲线,分别介绍了这两类域的表⽰,运算,以及域上的椭圆曲线的点的表⽰,运算和多倍点计算算法。

然后介绍了编程语⾔中的数据转换,包括整数和字节串,字节串和⽐特串,域元素和⽐特串,域元素和整数,点和字节串之间的数据转换规则。

详细说明了有限域上椭圆曲线的参数⽣成以及验证,椭圆曲线的参数包括有限域的选取、椭圆曲线⽅程参数、椭圆曲线群基点的选取等,并给出了选取的标准以便于验证。

最后给椭圆曲线上密钥对的⽣成以及公钥的验证,⽤户的密钥对为(s,sP),其中s为⽤户的私钥,sP为⽤户的公钥,由于离散对数问题从sP难以得到s,并针对素域和⼆元扩域给出了密钥对⽣成细节和验证⽅式。

总则中的知识也适⽤于SM9算法。

在总则的基础上给出了数字签名算法(包括数字签名⽣成算法和验证算法),密钥交换协议以及公钥加密算法(包括加密算法和解密算法),并在每个部分给出了算法描述,算法流程和相关⽰例。

数字签名算法、密钥交换协议以及公钥加密算法都使⽤了国家密管理局批准的SM3密码杂凑算法和随机数发⽣器。

基于秘密共享的SM4算法S盒实现方案

基于秘密共享的SM4算法S盒实现方案

基于秘密共享的SM4算法S盒实现方案李新超;钟卫东;刘明明;李栋【摘要】针对现有的SM4算法掩码方案不能完全抵抗差分功耗分析(DPA)攻击的现状,提出一种基于秘密共享抵抗DPA攻击的方案.通过将输入变换到复合域中求逆,结合秘密共享、门限方案构造一个新型S盒.S盒利用秘密共享函数代替仿射变换,在乘法器分组中采用虚拟值法,并在反相器中引入分解法,使得实现方案具有较少的运算次数和较低的空间占比.安全性分析与实验结果表明,该方案所构造的S盒可有效抵御高阶DPA攻击及glitch攻击,且具有较低的功率消耗.【期刊名称】《计算机工程》【年(卷),期】2018(044)011【总页数】6页(P148-153)【关键词】SM4算法;差分功耗分析;S盒;秘密共享;虚拟值;复合域【作者】李新超;钟卫东;刘明明;李栋【作者单位】武警工程大学网络与信息安全武警部队重点实验室,西安710086;武警工程大学密码工程学院,西安710086;武警工程大学网络与信息安全武警部队重点实验室,西安710086;武警工程大学密码工程学院,西安710086;武警工程大学网络与信息安全武警部队重点实验室,西安710086;武警工程大学密码工程学院,西安710086;武警工程大学网络与信息安全武警部队重点实验室,西安710086;武警工程大学密码工程学院,西安710086【正文语种】中文【中图分类】TP3090 概述SM4是我国自行设计的分组密码标准,2012年由国家密码管理局发布,采用非平衡Feistel结构,加密算法与密钥扩展算法均采用32轮非线性迭代结构,具有较高的安全性[1]。

自1999年Kocher利用差分功耗分析(Differential Power Analysis,DPA)攻击成功破解DES算法之后,各种已知的密码算法包括SM4都面临着巨大的威胁,如何抵御DPA攻击成为密码学研究的一大热点。

2007年,文献[2]通过对SM4算法进行分析,成功得到了S盒的代数表达式,为SM4算法的进一步研究奠定了基础。

GMSSL SM4测试过程及源码(ECB、CBC、CTR)

GMSSL SM4测试过程及源码(ECB、CBC、CTR)

基于GMSSL的SM4测试过程及源码1.SM4介绍SM4算法,是由国家密码管理局于2012年发布,又名GMS4.0 。

相关标准为GM/T 0002-2012《SM4分组密码算法》。

关于sm4的源码在github上有很多,但好多都不全,只有SM4的ECB模式,目前找到的比较全的SM4源码就是GMSSL中所实现的。

2.GMSSL介绍GmSSL是一个开源的密码工具箱,支持SM2/SM3/SM4/SM9/ZUC等国密(国家商用密码)算法。

项目由北京大学关志副研究员的密码学研究组开发维护,项目源码托管于github。

GMSSL不仅实现了所有的国密算法,还实现了国密的ssl版本---GMTLS。

同时由于GMSSL是基于openssl的,还保持了openssl的基本功能,包括各种国际算法和ssl/TLS版本。

3.GMSSL裁剪使用GMSSL的话就涉及到了裁剪,需要如下操作:(1)在在config中添加no-选项,有编译不过的,就添加,直到编译完成。

例如:./config --prefix=/usr/local/openssl no-pic no-poly1305 no-rsa no-aes no-rfc3779(2)同时修改Configure 中307 $config{sdirs} = [317 ];把没用到的删掉,在config ,make 可以编译出加密库libcrypto.so (3)其实如果使用静态库编译我们的程序的话,就没必要裁剪了,因为使用静态库在编译的过程中只会把用到的接口链接到我们的程序中,不会额外增加我们程序的大小。

4.GMSSL SM4 接口使用GMSSL中实现了SM4的所有模式下的源码,包括ECB、CBC、CFB、OFB和CTR。

这篇文章主要讲解ECB、CBC和CTR这三种常用模式的接口测试。

4.1 ECB模式。

对称分组加密算法ECB模式的原理如下:在GMSSL源码中SM4-ECB模式的源码实现是:crypto/sms4/sms4_ecb.c主要涉及的接口为:加解密接口测试如下:int sm4_ecb_enc_128bit(unsigned char *key, unsigned char *in_data, unsigned char *out_data){sms4_key_t enc_key;sms4_set_encrypt_key(&enc_key, key);sms4_encrypt(in_data, out_data, &enc_key);return 0;}int sm4_ecb_dec_128bit(unsigned char *key, unsigned char *in_data, unsigned char *out_data){sms4_key_t dec_key;sms4_set_decrypt_key(&dec_key, key);sms4_encrypt(in_data, out_data, &dec_key);return 0;}测试结果:4.2 CBC 模式分组加密算法CBC模式原理:在GMSSL源码中SM4-CBC模式的源码实现是:crypto/sms4/sms4_cbc.c主要涉及的接口为:加解密接口测试如下://sm4 cbc encryptmemcpy(user_key, key, 16);memcpy(user_iv, iv, 16);sms4_key_t enc_key;sms4_set_encrypt_key(&enc_key, user_key);sms4_cbc_encrypt(plain_text, enc_text, 16, &enc_key, user_iv, 1);sms4_cbc_encrypt(plain_text+16, enc_text+16, 16, &enc_key, user_iv, 1);//sm4 cbc decryptmemcpy(user_key, key, 16);memcpy(user_iv, iv, 16);sms4_key_t dec_key;sms4_set_decrypt_key(&dec_key, user_key);sms4_cbc_encrypt(enc_text, dec_text, 16, &dec_key, user_iv, 0);sms4_cbc_encrypt(enc_text+16, dec_text+16, 16, &dec_key, user_iv, 0);测试结果:4.3 CTR 模式对称分组加密算法CTR模式原理:在GMSSL源码中SM4-CBC模式的源码实现是:crypto/sms4/sms4_ctr.c主要涉及的接口为:接口测试程序:测试结果:。

分组密码算法SM4的低复杂度实现

分组密码算法SM4的低复杂度实现
h a r d wa r e o f e n c r y pt i o n/ d e c r y p t i o n a nd ke y e x p a n s i o n mod u l e be c a us e t h e e n c r y p t i o n / d e c r yp t i o n a l g o r i t h m i s v e r y s i mi l a r wi h t he t k e y e xp a n s i o n a l g o r i t h m .Opt i mu m t r a d e — o f a mo ng c o n t r o l — l o g i c c ompl e xi t y ,r e us e d — mo du l e c o mp l e xi t y a n d t h r o u g hp u t i s r e a l i z e d t h r o ug h c a r e f u l a n a l ys i s a nd c ho o s e o f s p e c i ic f r e a l i z a t i on . A SM 4 c i ph e r I P i s d e s i gn e d b a s e d o n t hi s a r c hi t e c t u r e .Th e d e s i g ne d I P’ S c os t i s o nl y
L o w Co mp l e x i t y I mp l e me n t a t i o n 0 f B l o c k Ci p h e r S M4 A l g o r i t h m
WANG Ch e n - g u a n g , QI AO S h u - s h a n , HEI Y o n g

国密算法Java代码的标准实现

国密算法Java代码的标准实现

国密算法Java代码的标准实现 前⼀阵⼦做的项⽬,越来越多的⾦融类应⽤使⽤国密算法进⾏加解密的运算。

国密即国家密码局认定的国产密码算法。

主要有SM1,SM2,SM3,SM4。

密钥长度和分组长度均为128位。

SM1 为对称加密。

其加密强度与AES相当。

该算法不公开,调⽤该算法时,需要通过加密芯⽚的接⼝进⾏调⽤。

SM2为⾮对称加密,基于ECC。

该算法已公开。

由于该算法基于ECC,故其签名速度与秘钥⽣成速度都快于RSA。

ECC 256位(SM2采⽤的就是ECC 256位的⼀种)安全强度⽐RSA 2048位⾼,但运算速度快于RSA。

SM3 消息摘要。

可以⽤MD5作为对⽐理解。

该算法已公开。

校验结果为256位。

SM4 ⽆线局域⽹标准的分组数据算法。

对称加密,密钥长度和分组长度均为128位。

由于SM1、SM4加解密的分组⼤⼩为128bit,故对消息进⾏加解密时,若消息长度过长,需要进⾏分组,要消息长度不⾜,则要进⾏填充。

JAVA代码:Util:import javax.crypto.SecretKey;2 import javax.crypto.SecretKeyFactory;3 import javax.crypto.spec.PBEKeySpec;4 import javax.crypto.spec.SecretKeySpec;5 import java.math.BigInteger;6 import java.security.NoSuchAlgorithmException;7 import java.security.SecureRandom;8 import java.security.spec.InvalidKeySpecException;9 import java.security.spec.KeySpec;1011 public class Util {12 public static final byte MAX_VALUE = -1;13 public static byte[] hexToByte(String arg8) {14 if(arg8.length() % 2 == 0) {15 char[] v0 = arg8.toCharArray();16 byte[] v1 = new byte[arg8.length() / 2];17 int v2 = 0;18 int v3 = 0;19 int v4 = arg8.length();20 while(v2 < v4) {21 StringBuilder v5 = new StringBuilder();22 v5.append("");23 int v6 = v2 + 1;24 v5.append(v0[v2]);25 v5.append(v0[v6]);26 v1[v3] = new Integer(Integer.parseInt(v5.toString(), 16) & 255).byteValue();27 v2 = v6 + 1;28 ++v3;29 }3031 return v1;32 }33 throw new IllegalArgumentException();34 }35 public static String byteToHex(byte[] arg5) {36 if(arg5 != null) {37 String v0 = "";38 int v2;39 for(v2 = 0; v2 < arg5.length; ++v2) {40 String v1 = Integer.toHexString(arg5[v2] & 255);41 v0 = v1.length() == 1 ? v0 + "0" + v1 : v0 + v1;42 }4344 return v0.toUpperCase();45 }46 throw new IllegalArgumentException("Argument b ( byte array ) is null! ");47 }4849 public static byte[] byteConvert32Bytes(BigInteger arg5) {50 byte[] v0 = null;51 if(arg5 == null) {52 return v0;53 }5455 int v4 = 32;56 if(arg5.toByteArray().length == 33) {57 v0 = new byte[v4];58 System.arraycopy(arg5.toByteArray(), 1, v0, 0, v4);59 }60 else if(arg5.toByteArray().length == v4) {61 v0 = arg5.toByteArray();62 }63 else {64 v0 = new byte[v4];65 int v1;66 for(v1 = 0; v1 < 32 - arg5.toByteArray().length; ++v1) {67 v0[v1] = 0;68 }6970 System.arraycopy(arg5.toByteArray(), 0, v0, v4 - arg5.toByteArray().length, arg5.toByteArray().length);71 }7273 return v0;74 }7576 public static byte[] hexStringToBytes(String arg7) {77 if(arg7 != null) {78 if(arg7.equals("")) {79 }80 else {81 arg7 = arg7.toUpperCase();82 int v0 = arg7.length() / 2;83 char[] v1 = arg7.toCharArray();84 byte[] v2 = new byte[v0];85 int v3;86 for(v3 = 0; v3 < v0; ++v3) {87 int v4 = v3 * 2;88 v2[v3] = ((byte)(Util.charToByte(v1[v4]) << 4 | Util.charToByte(v1[v4 + 1])));89 }9091 return v2;92 }93 }9495 return null;96 }9798 public static byte charToByte(char arg1) {99 return ((byte)"0123456789ABCDEF".indexOf(arg1));100 }101102 }1 import javax.crypto.SecretKey;2 import javax.crypto.SecretKeyFactory;3 import javax.crypto.spec.PBEKeySpec;4 import javax.crypto.spec.SecretKeySpec;5 import java.math.BigInteger;6 import java.security.NoSuchAlgorithmException;7 import java.security.SecureRandom;8 import java.security.spec.InvalidKeySpecException;9 import java.security.spec.KeySpec;1011 public class Util {12 public static final byte MAX_VALUE = -1;13 public static byte[] hexToByte(String arg8) {14 if(arg8.length() % 2 == 0) {15 char[] v0 = arg8.toCharArray();16 byte[] v1 = new byte[arg8.length() / 2];17 int v2 = 0;18 int v3 = 0;19 int v4 = arg8.length();20 while(v2 < v4) {21 StringBuilder v5 = new StringBuilder();22 v5.append("");23 int v6 = v2 + 1;24 v5.append(v0[v2]);25 v5.append(v0[v6]);26 v1[v3] = new Integer(Integer.parseInt(v5.toString(), 16) & 255).byteValue();27 v2 = v6 + 1;28 ++v3;29 }3031 return v1;32 }33 throw new IllegalArgumentException();34 }35 public static String byteToHex(byte[] arg5) {36 if(arg5 != null) {37 String v0 = "";38 int v2;39 for(v2 = 0; v2 < arg5.length; ++v2) {40 String v1 = Integer.toHexString(arg5[v2] & 255);41 v0 = v1.length() == 1 ? v0 + "0" + v1 : v0 + v1;42 }4344 return v0.toUpperCase();45 }46 throw new IllegalArgumentException("Argument b ( byte array ) is null! ");47 }4849 public static byte[] byteConvert32Bytes(BigInteger arg5) {50 byte[] v0 = null;51 if(arg5 == null) {52 return v0;53 }5455 int v4 = 32;56 if(arg5.toByteArray().length == 33) {57 v0 = new byte[v4];58 System.arraycopy(arg5.toByteArray(), 1, v0, 0, v4);59 }60 else if(arg5.toByteArray().length == v4) {61 v0 = arg5.toByteArray();62 }63 else {64 v0 = new byte[v4];65 int v1;66 for(v1 = 0; v1 < 32 - arg5.toByteArray().length; ++v1) {67 v0[v1] = 0;68 }6970 System.arraycopy(arg5.toByteArray(), 0, v0, v4 - arg5.toByteArray().length, arg5.toByteArray().length);71 }7273 return v0;74 }7576 public static byte[] hexStringToBytes(String arg7) {77 if(arg7 != null) {78 if(arg7.equals("")) {79 }80 else {81 arg7 = arg7.toUpperCase();82 int v0 = arg7.length() / 2;83 char[] v1 = arg7.toCharArray();84 byte[] v2 = new byte[v0];85 int v3;86 for(v3 = 0; v3 < v0; ++v3) {87 int v4 = v3 * 2;88 v2[v3] = ((byte)(Util.charToByte(v1[v4]) << 4 | Util.charToByte(v1[v4 + 1])));89 }9091 return v2;92 }93 }9495 return null;96 }9798 public static byte charToByte(char arg1) {99 return ((byte)"0123456789ABCDEF".indexOf(arg1));100 }101102 } SM2:import org.bouncycastle.crypto.generators.ECKeyPairGenerator;2 import org.bouncycastle.crypto.params.ECDomainParameters;3 import org.bouncycastle.crypto.params.ECKeyGenerationParameters;4 import org.bouncycastle.math.ec.ECCurve;5 import org.bouncycastle.math.ec.ECFieldElement;6 import org.bouncycastle.math.ec.ECPoint;78 import java.math.BigInteger;9 import java.security.SecureRandom;1011 public class SM2 {12 public static String[] ecc_param = {"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC", "28E9FA9E9D9F5E3413 public final BigInteger ecc_p = new BigInteger(ecc_param[0], 16);14 public final BigInteger ecc_a = new BigInteger(ecc_param[1], 16);15 public final BigInteger ecc_b = new BigInteger(ecc_param[2], 16);16 public final BigInteger ecc_n = new BigInteger(ecc_param[3], 16);17 public final BigInteger ecc_gx = new BigInteger(ecc_param[4], 16);18 public final BigInteger ecc_gy = new BigInteger(ecc_param[5], 16);19 public final ECFieldElement ecc_gx_fieldelement = new ECFieldElement.Fp(this.ecc_p, this.ecc_gx);20 public final ECFieldElement ecc_gy_fieldelement = new ECFieldElement.Fp(this.ecc_p, this.ecc_gy);21 public final ECCurve ecc_curve = new ECCurve.Fp(this.ecc_p, this.ecc_a, this.ecc_b);22 public final ECPoint ecc_point_g = new ECPoint.Fp(this.ecc_curve, this.ecc_gx_fieldelement, this.ecc_gy_fieldelement);23 public final ECDomainParameters ecc_bc_spec = new ECDomainParameters(this.ecc_curve, this.ecc_point_g, this.ecc_n);24 public final ECKeyPairGenerator ecc_key_pair_generator;2526 public static SM2 Instance() {27 return new SM2();28 }2930 public SM2() {31 ECKeyGenerationParameters ecc_ecgenparam = new ECKeyGenerationParameters(this.ecc_bc_spec, new SecureRandom());32 this.ecc_key_pair_generator = new ECKeyPairGenerator();33 this.ecc_key_pair_generator.init(ecc_ecgenparam);34 }35 } SM2Util:import org.bouncycastle.crypto.AsymmetricCipherKeyPair;2 import org.bouncycastle.crypto.params.AsymmetricKeyParameter;3 import org.bouncycastle.crypto.params.ECPrivateKeyParameters;4 import org.bouncycastle.crypto.params.ECPublicKeyParameters;5 import org.bouncycastle.math.ec.ECPoint;67 import java.io.IOException;8 import java.math.BigInteger;910 public class SM2Util {11 public static final String PUBLIC_KEY = "你的公钥1";12 public static final String PUBLIC_KEY_2 = "你的公钥2";13 public static String encrypt(String key, String mes) {14 byte[] arg9 = mes.getBytes();15 byte[] arg8 = Util.hexToByte(key);16 String v0 = null;17 if(arg8 != null) {18 if(arg8.length == 0) {19 }20 else {21 if(arg9 != null) {22 if(arg9.length == 0) {23 }24 else {25 byte[] v0_1 = new byte[arg9.length];26 System.arraycopy(arg9, 0, v0_1, 0, arg9.length);27 Cipher v1 = new Cipher();28 SM2 v2 = SM2.Instance();29 ECPoint v4 = v1.Init_enc(v2, v2.ecc_curve.decodePoint(arg8));30 v1.Encrypt(v0_1);31 byte[] v5 = new byte[32];32 v1.Dofinal(v5);33 return Util.byteToHex(v4.getEncoded()) + Util.byteToHex(v5) + Util.byteToHex(v0_1);34 }35 }36 return v0;37 }38 }39 return v0;40 }4142 public static String decrypt(String key, String mes) throws IOException {43 byte[] arg9 = Util.hexToByte(key);44 byte[] arg10 = Util.hexToByte(mes);45 byte[] v0 = null;46 if(arg9 != null) {47 if(arg9.length == 0) {48 }49 else {50 if(arg10 != null) {51 if(arg10.length == 0) {52 }53 else {54 String v0_1 = Util.byteToHex(arg10);55 byte[] v1 = Util.hexToByte(v0_1.substring(0, 130));56 int v3 = arg10.length - 97;57 byte[] v2 = Util.hexToByte(v0_1.substring(130, 194));58 byte[] v4 = Util.hexToByte(v0_1.substring(194, v3 * 2 + 194));59 SM2 v5 = SM2.Instance();60 BigInteger v6 = new BigInteger(1, arg9);61 ECPoint v7 = v5.ecc_curve.decodePoint(v1);62 Cipher v8 = new Cipher();63 v8.Init_dec(v6, v7);64 v8.Decrypt(v4);65 v8.Dofinal(v2);66 return new String(v4);67 }68 }6970 return new String(v0);71 }72 }73 return new String(v0);74 }7576 // public static SM2KeyVO generateKeyPair() {77 // AsymmetricCipherKeyPair v1;78 // SM2 v0 = SM2.Instance();79 // while(true) {80 // v1 = v0.ecc_key_pair_generator.generateKeyPair();81 // if(v1.getPrivate().getD().toByteArray().length == 32) {82 // break;83 // }84 // }85 //86 // AsymmetricKeyParameter v2 = v1.getPrivate();87 // AsymmetricKeyParameter v3 = v1.getPublic();88 // BigInteger v4 = ((ECPrivateKeyParameters)v2).getD();89 // ECPoint v5 = ((ECPublicKeyParameters)v3).getQ();90 // SM2KeyVO v6 = new SM2KeyVO();91 // v6.setPublicKey(v5);92 // v6.setPrivateKey(v4);93 // return v6;94 // }9596 } SM2KeyVO:import org.bouncycastle.math.ec.ECPoint;23 import java.math.BigInteger;45 public class SM2KeyVO {6 BigInteger privateKey;7 ECPoint publicKey;89 public String getPriHexInSoft() {10 return Util.byteToHex(this.privateKey.toByteArray());11 }1213 public BigInteger getPrivateKey() {14 return this.privateKey;15 }1617 public String getPubHexInSoft() {18 return Util.byteToHex(this.publicKey.getEncoded());19 }2021 public ECPoint getPublicKey() {22 return this.publicKey;23 }2425 public void setPrivateKey(BigInteger arg1) {26 this.privateKey = arg1;27 }2829 public void setPublicKey(ECPoint arg1) {30 this.publicKey = arg1;31 }32 } SM3Util:import org.bouncycastle.crypto.digests.SM3Digest;2 import org.bouncycastle.util.encoders.Hex;34 public class SM3Util {5 public static String sm3(String arg5) {6 byte[] v0 = new byte[32];7 byte[] v1 = arg5.getBytes();8 SM3Digest v2 = new SM3Digest();9 v2.update(v1, 0, v1.length);10 v2.doFinal(v0, 0);11 return new String(Hex.encode(v0)).toUpperCase();12 }13 } SM4:import java.io.ByteArrayInputStream;2 import java.io.ByteArrayOutputStream;34 public class SM4 {5 public static final int[] CK = new int[]{462357, 472066609, 943670861, 1415275113, 1886879365, -1936483679, -1464879427, -993275175, -521670923, -66909679, 404694573, 876298825, 1347903077, 1819507329, -2003855715, -153225146 public static final int[] FK = new int[]{-1548633402, 1453994832, 1736282519, -1301273892};7 public static final int SM4_DECRYPT = 0;8 public static final int SM4_ENCRYPT = 1;9 public static final byte[] SboxTable = new byte[]{-42, -112, -23, -2, -52, -31, 61, -73, 22, -74, 20, -62, 40, -5, 44, 5, 43, 103, -102, 118, 42, -66, 4, -61, -86, 68, 19, 38, 73, -122, 6, -103, -100, 66, 80, -12, -111, -17, -104, 122, 51, 84, 11, 67, -11011 public SM4() {12 super();13 }1415 private long GET_ULONG_BE(byte[] arg7, int arg8) {16 return (((long)(arg7[arg8] & 255))) << 24 | (((long)((arg7[arg8 + 1] & 255) << 16))) | (((long)((arg7[arg8 + 2] & 255) << 8))) | (((long)(arg7[arg8 + 3] & 255))) & 4294967295L;17 }1819 private void PUT_ULONG_BE(long arg7, byte[] arg9, int arg10) {20 arg9[arg10] = ((byte)(((int)(arg7 >> 24 & 255))));21 arg9[arg10 + 1] = ((byte)(((int)(arg7 >> 16 & 255))));22 arg9[arg10 + 2] = ((byte)(((int)(arg7 >> 8 & 255))));23 arg9[arg10 + 3] = ((byte)(((int)(arg7 & 255))));24 }2526 private long ROTL(long arg5, int arg7) {27 return this.SHL(arg5, arg7) | arg5 >> 32 - arg7;28 }2930 private long SHL(long arg3, int arg5) {31 return (-1 & arg3) << arg5;32 }3334 private void SWAP(long[] arg5, int arg6) {35 long v0 = arg5[arg6];36 arg5[arg6] = arg5[31 - arg6];37 arg5[31 - arg6] = v0;38 }3940 private byte[] padding(byte[] arg6, int arg7) {41 int v1;42 byte[] v0 = null;43 if(arg6 == null) {44 return v0;45 }4647 if(arg7 == 1) {48 v1 = 16 - arg6.length % 16;49 v0 = new byte[arg6.length + v1];50 System.arraycopy(arg6, 0, v0, 0, arg6.length);51 int v2;52 for(v2 = 0; v2 < v1; ++v2) {53 v0[arg6.length + v2] = ((byte)v1);54 }55 }56 else {57 v1 = arg6[arg6.length - 1];58 v0 = new byte[arg6.length - v1];59 System.arraycopy(arg6, 0, v0, 0, arg6.length - v1);60 }6162 return v0;63 }6465 private long sm4CalciRK(long arg11) {66 byte[] v5 = new byte[4];67 byte[] v4 = new byte[4];68 this.PUT_ULONG_BE(arg11, v5, 0);69 v4[0] = this.sm4Sbox(v5[0]);70 v4[1] = this.sm4Sbox(v5[1]);71 v4[2] = this.sm4Sbox(v5[2]);72 v4[3] = this.sm4Sbox(v5[3]);73 long v0 = this.GET_ULONG_BE(v4, 0);74 return this.ROTL(v0, 13) ^ v0 ^ this.ROTL(v0, 23);75 }7677 private long sm4F(long arg3, long arg5, long arg7, long arg9, long arg11) {78 return this.sm4Lt(arg5 ^ arg7 ^ arg9 ^ arg11) ^ arg3;79 }8081 private long sm4Lt(long arg11) {82 byte[] v5 = new byte[4];83 byte[] v4 = new byte[4];84 this.PUT_ULONG_BE(arg11, v5, 0);85 v4[0] = this.sm4Sbox(v5[0]);86 v4[1] = this.sm4Sbox(v5[1]);87 v4[2] = this.sm4Sbox(v5[2]);88 v4[3] = this.sm4Sbox(v5[3]);89 long v0 = this.GET_ULONG_BE(v4, 0);90 return this.ROTL(v0, 2) ^ v0 ^ this.ROTL(v0, 10) ^ this.ROTL(v0, 18) ^ this.ROTL(v0, 24);91 }9293 private byte sm4Sbox(byte arg3) {94 return SM4.SboxTable[arg3 & 255];95 }9697 public byte[] sm4_crypt_cbc(SM4_Context arg13, byte[] arg14, byte[] arg15) throws Exception {98 byte[] v8;99 byte[] v6;100 byte[] v2;101 if(arg14 != null) {102 int v1 = 16;103 if(arg14.length == v1) {104 if(arg15 != null) {105 if((arg13.isPadding) && arg13.mode == 1) {106 arg15 = this.padding(arg15, 1);107 }108109 int v3 = arg15.length;110 ByteArrayInputStream v4 = new ByteArrayInputStream(arg15);111 ByteArrayOutputStream v5 = new ByteArrayOutputStream();112 if(arg13.mode == 1) {113 while(v3 > 0) {114 v2 = new byte[v1];115 v6 = new byte[v1];116 v8 = new byte[v1];117 v4.read(v2);118 int v0;119 for(v0 = 0; v0 < v1; ++v0) {120 v6[v0] = ((byte)(v2[v0] ^ arg14[v0]));121 }122123 this.sm4_one_round(arg13.sk, v6, v8);124 System.arraycopy(v8, 0, arg14, 0, v1);125 v5.write(v8);126 v3 += -16;127 }128 }129 else {130 v2 = new byte[v1];131 while(v3 > 0) {132 v6 = new byte[v1];133 v8 = new byte[v1];134 byte[] v9 = new byte[v1];135 v4.read(v6);136 System.arraycopy(v6, 0, v2, 0, v1);137 this.sm4_one_round(arg13.sk, v6, v8);138 int v0;139 for(v0 = 0; v0 < v1; ++v0) {140 v9[v0] = ((byte)(v8[v0] ^ arg14[v0]));141 }142143 System.arraycopy(v2, 0, arg14, 0, v1);144 v5.write(v9);145 v3 += -16;146 }147 }148149 byte[] v1_1 = v5.toByteArray();150 if((arg13.isPadding) && arg13.mode == 0) {151 v1_1 = this.padding(v1_1, 0);152 }153154 v4.close();155 v5.close();156 return v1_1;157 }158 else {159 throw new Exception("input is null!");160 }161 }162 }163164 throw new Exception("iv error!");165 }166167 public byte[] sm4_crypt_ecb(SM4_Context arg7, byte[] arg8) throws Exception {168 byte[] v3;169 if(arg8 != null) {170 if((arg7.isPadding) && arg7.mode == 1) {171 arg8 = this.padding(arg8, 1);172 }173174 int v0 = arg8.length;175 ByteArrayInputStream v1 = new ByteArrayInputStream(arg8);176 ByteArrayOutputStream v2 = new ByteArrayOutputStream();177 while(v0 > 0) {178 byte[] v4 = new byte[16];179 v3 = new byte[16];180 v1.read(v4);181 this.sm4_one_round(arg7.sk, v4, v3);182 v2.write(v3);183 v0 += -16;184 }185186 v3 = v2.toByteArray();187 if((arg7.isPadding) && arg7.mode == 0) {188 v3 = this.padding(v3, 0);189 }190191 v1.close();192 v2.close();193 return v3;194 }195196 throw new Exception("input is null!");197 }198199 private void sm4_one_round(long[] arg23, byte[] arg24, byte[] arg25) {200 int v0;201 SM4 v11 = this;202 byte[] v13 = arg25;203 long[] v14 = new long[36];204 v14[0] = v11.GET_ULONG_BE(arg24, 0);205 v14[1] = v11.GET_ULONG_BE(arg24, 4);206 v14[2] = v11.GET_ULONG_BE(arg24, 8);207 v14[3] = v11.GET_ULONG_BE(arg24, 12);208 int v8;209 for(v8 = 0; true; ++v8) {210 v0 = 32;211 if(v8 >= v0) {212 break;213 }214215 v14[v8 + 4] = this.sm4F(v14[v8], v14[v8 + 1], v14[v8 + 2], v14[v8 + 3], arg23[v8]);216 }217218 v11.PUT_ULONG_BE(v14[35], v13, 0);219 v11.PUT_ULONG_BE(v14[34], v13, 4);220 v11.PUT_ULONG_BE(v14[33], v13, 8);221 v11.PUT_ULONG_BE(v14[v0], v13, 12);222 }223224 private void sm4_setkey(long[] arg13, byte[] arg14) {225 long[] v1 = new long[4];226 long[] v2 = new long[36];227 int v3 = 0;228 v1[0] = this.GET_ULONG_BE(arg14, 0);229 v1[1] = this.GET_ULONG_BE(arg14, 4);230 v1[2] = this.GET_ULONG_BE(arg14, 8);231 v1[3] = this.GET_ULONG_BE(arg14, 12);232 long v5 = v1[0];233 int[] v9 = SM4.FK;234 v2[0] = v5 ^ (((long)v9[0]));235 v2[1] = v1[1] ^ (((long)v9[1]));236 v2[2] = v1[2] ^ (((long)v9[2]));237 v2[3] = v1[3] ^ (((long)v9[3]));238 while(v3 < 32) {239 v2[v3 + 4] = v2[v3] ^ this.sm4CalciRK(v2[v3 + 1] ^ v2[v3 + 2] ^ v2[v3 + 3] ^ (((long)SM4.CK[v3]))); 240 arg13[v3] = v2[v3 + 4];241 ++v3;242 }243 }244245 public void sm4_setkey_dec(SM4_Context arg4, byte[] arg5) throws Exception {246 if(arg4 != null) {247 if(arg5 != null) {248 int v1 = 16;249 if(arg5.length == v1) {250 arg4.mode = 0;251 this.sm4_setkey(arg4.sk, arg5);252 int v0;253 for(v0 = 0; v0 < v1; ++v0) {254 this.SWAP(arg4.sk, v0);255 }256257 return;258 }259 }260261 throw new Exception("key error!");262 }263264 throw new Exception("ctx is null!");265 }266267 public void sm4_setkey_enc(SM4_Context arg3, byte[] arg4) throws Exception {268 if(arg3 != null) {269 if(arg4 != null && arg4.length == 16) {270 arg3.mode = 1;271 this.sm4_setkey(arg3.sk, arg4);272 return;273 }274275 throw new Exception("key error!");276 }277278 throw new Exception("ctx is null!");279 }280 } SM4_Context:public class SM4_Context {2 public boolean isPadding;3 public int mode;4 public long[] sk;56 public SM4_Context() {7 super();8 this.mode = 1;9 this.isPadding = true;10 this.sk = new long[32];11 }12 } SM4Util:import mons.codec.binary.Base64;23 import java.io.IOException;4 import java.io.PrintStream;5 import java.util.regex.Pattern;67 public class SM4Utils {8 public static final String KEY = "你的key";9 public static final String IV = "你的IV";10 public boolean hexString;11 public String iv;12 public String secretKey;1314 public SM4Utils() {15 super();16 this.secretKey = "";17 this.iv = "";18 this.hexString = false;19 }2021 public static String sm4Decrypt(String mes) {22 SM4Utils v0 = new SM4Utils();23 v0.secretKey = KEY;24 v0.iv = IV;25 v0.hexString = true;26 return v0.decryptData_CBC(mes);27 }2829 public static String sm4Encrypt(String mes) {30 SM4Utils v0 = new SM4Utils();31 v0.secretKey = KEY;32 v0.iv = IV;33 v0.hexString = true;34 return v0.encryptData_CBC(mes);35 }3637 public String decryptData_CBC(String arg9) {38 byte[] v3;39 byte[] v2;40 try {41 arg9 = Base64.encodeBase64String(Util.hexToByte(arg9));42 if(arg9 != null && arg9.trim().length() > 0) {43 arg9 = pile("\\s*|\t|\r|\n").matcher(((CharSequence)arg9)).replaceAll("");44 }4546 SM4_Context v1 = new SM4_Context();47 v1.isPadding = true;48 v1.mode = 0;49 if(this.hexString) {50 v2 = Util.hexStringToBytes(this.secretKey);51 v3 = Util.hexStringToBytes(this.iv);52 }53 else {54 v2 = this.secretKey.getBytes();55 v3 = this.iv.getBytes();56 }5758 SM4 v4 = new SM4();59 v4.sm4_setkey_dec(v1, v2);60 return new String(v4.sm4_crypt_cbc(v1, v3, Base64.decodeBase64(arg9)), "UTF-8");61 }62 catch(Exception v0) {63 v0.printStackTrace();64 return null;65 }66 }6768 public String encryptData_CBC(String arg7) {69 byte[] v2;70 byte[] v1;71 try {72 SM4_Context v0_1 = new SM4_Context();73 v0_1.isPadding = true;74 v0_1.mode = 1;75 if(this.hexString) {76 v1 = Util.hexStringToBytes(this.secretKey);77 v2 = Util.hexStringToBytes(this.iv);78 }79 else {80 v1 = this.secretKey.getBytes();81 v2 = this.iv.getBytes();82 }8384 SM4 v3 = new SM4();85 v3.sm4_setkey_enc(v0_1, v1);86 return Util.byteToHex(v3.sm4_crypt_cbc(v0_1, v2, arg7.getBytes("UTF-8")));87 }88 catch(Exception v0) {89 v0.printStackTrace();90 return null;91 }92 }9394 public String decryptData_ECB(String arg8) {95 try {96 arg8 = Base64.encodeBase64String(Util.hexToByte(arg8));97 if(arg8 != null && arg8.trim().length() > 0) {98 arg8 = pile("\\s*|\t|\r|\n").matcher(((CharSequence)arg8)).replaceAll("");99 }100101 SM4_Context v1 = new SM4_Context();102 v1.isPadding = true;103 v1.mode = 0;104 byte[] v2 = this.hexString ? Util.hexStringToBytes(this.secretKey) : this.secretKey.getBytes(); 105 SM4 v3 = new SM4();106 v3.sm4_setkey_dec(v1, v2);107 return new String(v3.sm4_crypt_ecb(v1, Base64.decodeBase64(arg8)), "UTF-8");108 }109 catch(Exception v0) {110 v0.printStackTrace();111 return null;112 }113 }114115 public String encryptData_ECB(String arg6) {116 try {117 SM4_Context v0_1 = new SM4_Context();118 v0_1.isPadding = true;120 byte[] v1 = this.hexString ? Util.hexStringToBytes(this.secretKey) : Util.hexStringToBytes(this.secretKey); 121 SM4 v2 = new SM4();122 v2.sm4_setkey_enc(v0_1, v1);123 return Util.byteToHex(v2.sm4_crypt_ecb(v0_1, arg6.getBytes("UTF-8")));124 }125 catch(Exception v0) {126 v0.printStackTrace();127 return null;128 }129 }130131 }1 import mons.codec.binary.Base64;23 import java.io.IOException;4 import java.io.PrintStream;5 import java.util.regex.Pattern;67 public class SM4Utils {8 public static final String KEY = "你的key";9 public static final String IV = "你的IV";10 public boolean hexString;11 public String iv;12 public String secretKey;1314 public SM4Utils() {15 super();16 this.secretKey = "";17 this.iv = "";18 this.hexString = false;19 }2021 public static String sm4Decrypt(String mes) {22 SM4Utils v0 = new SM4Utils();23 v0.secretKey = KEY;24 v0.iv = IV;25 v0.hexString = true;26 return v0.decryptData_CBC(mes);27 }2829 public static String sm4Encrypt(String mes) {30 SM4Utils v0 = new SM4Utils();31 v0.secretKey = KEY;32 v0.iv = IV;33 v0.hexString = true;34 return v0.encryptData_CBC(mes);35 }3637 public String decryptData_CBC(String arg9) {38 byte[] v3;39 byte[] v2;40 try {41 arg9 = Base64.encodeBase64String(Util.hexToByte(arg9));42 if(arg9 != null && arg9.trim().length() > 0) {43 arg9 = pile("\\s*|\t|\r|\n").matcher(((CharSequence)arg9)).replaceAll("");44 }4546 SM4_Context v1 = new SM4_Context();47 v1.isPadding = true;48 v1.mode = 0;49 if(this.hexString) {50 v2 = Util.hexStringToBytes(this.secretKey);51 v3 = Util.hexStringToBytes(this.iv);52 }53 else {54 v2 = this.secretKey.getBytes();55 v3 = this.iv.getBytes();56 }5758 SM4 v4 = new SM4();59 v4.sm4_setkey_dec(v1, v2);60 return new String(v4.sm4_crypt_cbc(v1, v3, Base64.decodeBase64(arg9)), "UTF-8");61 }62 catch(Exception v0) {63 v0.printStackTrace();64 return null;65 }66 }6768 public String encryptData_CBC(String arg7) {69 byte[] v2;70 byte[] v1;71 try {72 SM4_Context v0_1 = new SM4_Context();73 v0_1.isPadding = true;74 v0_1.mode = 1;75 if(this.hexString) {76 v1 = Util.hexStringToBytes(this.secretKey);77 v2 = Util.hexStringToBytes(this.iv);78 }79 else {80 v1 = this.secretKey.getBytes();81 v2 = this.iv.getBytes();82 }8384 SM4 v3 = new SM4();85 v3.sm4_setkey_enc(v0_1, v1);86 return Util.byteToHex(v3.sm4_crypt_cbc(v0_1, v2, arg7.getBytes("UTF-8")));87 }88 catch(Exception v0) {89 v0.printStackTrace();90 return null;91 }92 }9394 public String decryptData_ECB(String arg8) {95 try {96 arg8 = Base64.encodeBase64String(Util.hexToByte(arg8));97 if(arg8 != null && arg8.trim().length() > 0) {98 arg8 = pile("\\s*|\t|\r|\n").matcher(((CharSequence)arg8)).replaceAll("");99 }100101 SM4_Context v1 = new SM4_Context();102 v1.isPadding = true;103 v1.mode = 0;104 byte[] v2 = this.hexString ? Util.hexStringToBytes(this.secretKey) : this.secretKey.getBytes();105 SM4 v3 = new SM4();106 v3.sm4_setkey_dec(v1, v2);107 return new String(v3.sm4_crypt_ecb(v1, Base64.decodeBase64(arg8)), "UTF-8");108 }109 catch(Exception v0) {。

SM4算法在无线通信中的硬件实现与应用

SM4算法在无线通信中的硬件实现与应用
LIU Junjie, SHI Jianjun, ZHANG Dajiang, et al. Realization and application of hardware for algorithm of SM4 in wireless communication. Computer Engineering and Applications, 2016, 52(17):118-122.
摘 要:随着无线通信的快速发展与普及,通信的安全问题成为研究的重点。针对数据吞吐量不高,但实时性要求 严格的无线通信问题,设计了一个 SM4 的硬件电路模块。在 Altera 的 Cyclone 系列 FPGA 上占用 1 875 个逻辑单元, 时钟频率 100 MHz,吞吐率为 266.5 Mb/s。将该模块应用于此通信链路中,并搭建了一个无线通信加密平台,实验结 果表明 SM4 加密算法在物理层上的应用对于信息传输的安全具有重要意义。 关键词:SM4;现场可编程门阵列(FPGA);无线通信;物理层加密 文献标志码:A 中图分类号:TP331 doi:10.3778/j.issn.1002-8331.1512-0361
Abstract:With the rapid expansion and spread of the wireless communication, the safety of communication has become focusing research. Aiming to the characteristics of short produce and strict real-time of the wireless communication, it designs a hardware circuit module of SM4. The result of synthesization shows that the project has occupied 1, 875 logic cells in FPGA of the Altera’s Cyclone series and realized the data’s velocity of 266.5 Mb/s. Then it applies the module to the link of communication to realize the encryption platform of wireless communication, the result of experiment declares that the SM4 encryption’s application in the physical layer has a great significance in the security of the information transmission. Key words:SM4; field programmable gate array; wireless communication; physical layer encryption
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

SM4算法实现说明:该SM4算法是8位单片机Keil C51纯软件实现目录SM4算法手册 (1)目录 (2)1.数据类型定义 (3)2.函数接口说明 (3)3.1 初始化SM4模块 (3)3.2 关闭SM4模块 (4)3.3 SM4加解密 (4)SM4算法的工作模式图解 (5)源码SM4算法例程 (7)1.数据类型定义typedef unsigned char U8;typedef singed char S8;typedef unsigned int U16;typedef signed int S16;typedef unsigned long U32;typedef signed long S32;2.函数接口说明SM4算法库包含的函数列表如下:表2-1 SM4算法库函数表3.1初始化SM4模块初始化SM4模块函数原型void SM4_Init( U8 *key)参数说明key 输入,指向密钥的指针注意事项SM4加解密前,先调用此函数,进行密钥扩展例程见附录一SM4算法库函数调用例程。

3.2关闭SM4模块关闭SM4模块函数原型void SM4_Close(void)参数说明注意事项SM4加解密后,调用此函数例程见附录一SM4算法库函数调用例程。

3.3S M4加解密SM4加解密函数原型void SM4_Crypto(U8*in, U32 inLen, U8 En_De, U8 mode, U8 *iv,U8*out)参数说明in 输入,指向输入数组的指针inLen 输入,输入的字节长度,必须为16的倍数,否则填充in使其长度为16的倍数En_De 输入,指加密或是解密0:加密1:解密mode 输入,0--ECB模式,1--CBC模式iv 输入,指向扰乱向量的指针out 输出,指向输出的指针注意事项:大量数据分多块进行CBC模式加密或解密时,需注意:(1) 若是加密,则第X块数据(X>1)调用本函数进行加密,使用的初始向量IV 一定要更新为第X-1块数据调用本函数进行加密得到的密文的最后一个分组(16字节)。

(2) 若是解密,则第X块数据(X>1)调用本函数进行解密,使用的初始向量IV 一定要更新为第X-1块数据的最后一个分组(16字节)。

图解分析详如下SM4算法的工作模式图解SM4算法的工作模式有以下两种:1.ECB(Electronic Code Book)图 1 ECB模式的运算流程图2.CBC(Cipher Block Chaining)图 2 CBC模式的运算流程图源码SM4算法例程(main.c, SM4.c, SM4.h)SM4.h// SMS4.h//#pragma once#ifndef SM4_H#define SM4_Htypedef unsigned char UINT8;typedef unsigned short UINT16;typedef unsigned long UINT32;#define SM4_BLOCK_SIZE 16#define SM4_MAX_LEN 512#define SM4_MODE_CBC 1#define SM4_MODE_ECB 0typedef struct {unsigned long rk[32];}SM4_KEY;void SM4_Init( UINT8 *key);void SM4_Crypto(UINT8*in, U32 inLen, UINT8 En_De, UINT8 mode, UINT8 *iv,UINT8*out);void SM4_Close(void);#endifMain.c#include <stdio.h>#include <string.h>#include "SM4.h"说明:print_buf函数需要根据所用单片机来实现,主要是观察数据使用,不影响算法,故注释掉。

//void print_buf(char *buf,int len, char *name)//{// int i;// printf("%s: \r\n", name);// for(i=0;i<len;i++)// if((i&0x0f)==0xf)// printf("0x%02bx,\r\n",buf[i]);// else// printf("0x%02bx,",buf[i]);// printf("\r\n");//}/***************** SM4 standard data ***********************plain: 0B0B2B4F5405FEF1E8A264FC89AB210A0B0B2B4F5405FEF1E8A264FC89AB210A key: B122AD0A7A362EC3ABA1DDEFB3AF4915iv: 11111111d1a16c2067708acbd1a16c20ECB cipher: 70DC8D6965DA2A367CDBA4631C39A38470DC8D6965DA2A367CDBA4631C39A384 CBC cipher: 33910DD4617BF43B17FC7C4C7C99719C6A85D9077F958793049EB0CDA97AA9AD*********************************************************/void main(){U32 xdata time1 = 0, time2 = 0, count = 0, k=0x12345678;U8 xdata sm4plain[32] ={0x0B,0x0B,0x2B,0x4F,0x54,0x05,0xFE,0xF1,0xE8,0xA2,0x64,0xFC,0x89,0xAB,0x21,0x0A,0x0B,0x0B,0x2B,0x4F,0x54,0x05,0xFE,0xF1,0xE8,0xA2,0x64,0xFC,0x89,0xAB,0x21,0x0A};U8 xdata sm4key[16] ={0xB1,0x22,0xAD,0x0A,0x7A,0x36,0x2E,0xC3,0xAB,0xA1,0xDD,0xEF,0xB3,0xAF,0x49,0x15};U8 xdata sm4iv[16] ={0x11,0x11,0x11,0x11,0xd1,0xa1,0x6c,0x20,0x67,0x70,0x8a,0xcb,0xd1,0xa1,0x6c,0x20};U8 xdata buffer1[32];U8 xdata buffer2[32];// UartInit();//SM4 ECB 正确性测试//Encrypt// printf("\r\n\r\nSM4 ECB MODE\r\n");// print_buf(sm4plain,32,"plain");// print_buf(sm4key,16,"key");SM4_Init(sm4key);SM4_Crypto(sm4plain, 32, 0, 0, NULL,buffer1);SM4_Close();// print_buf(buffer1,32,"cipher");//Decrypt//printbuf8(sm4key,16,"key");SM4_Init(sm4key);SM4_Crypto(buffer1, 32, 1, 0, NULL,buffer2);SM4_Close();// print_buf(buffer2,32,"re-plain");// if(memcmp(sm4plain, buffer2, 32))// {// printf("\r\n ECB mode error!\r\n");// time1++;// }//SM4 CBC 正确性测试//Encrypt// printf("SM4 CBC MODE\r\n");// print_buf(sm4plain,32,"plain");// print_buf(sm4key,16,"key");// print_buf(sm4iv,16,"iv");SM4_Init(sm4key);SM4_Crypto(sm4plain, 32, 0, 1, sm4iv, buffer1);SM4_Close();// print_buf(buffer1,32,"cipher");//Decrypt//printbuf8(sm4key,16,"key");SM4_Init(sm4key);SM4_Crypto(buffer1, 32, 1, 1, sm4iv, buffer2);SM4_Close();// print_buf(buffer2,32,"re-plain");// if(memcmp(sm4plain, buffer2, 32))// {// printf("\r\n CBC mode error!\r\n");// time2++;// }// count++;// printf("time1 = %d, time2=%d, count=%d\r\n",time1,time2,count);while(1);}SM4.c#include <stdio.h>#include <string.h>#include "stdlib.h"#include "SM4.h"U8 xdata S_M_S4_ke_y[16];U32 Unpack_32(U8 * src){return (((UINT32) src[3]) << 24| ((UINT32) src[2]) << 16| ((UINT32) src[1]) << 8| (UINT32) src[0]);}/* ROTATE_LEFT rotates x left n bits.*/#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))/* S box data */U8 code SBX[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};U8 SBox(U8 into){UINT8 xdata h = into>>4;return SBX[h][into^(h<<4)];}/* data convertion */U32 T(U32 A){UINT32 xdata b0,b1,b2,b3,B,B1,B2,B3,B4,C;b0 = SBox((U8)(A>>24));b1 = SBox((U8)(A>>16));b2 = SBox((U8)(A>>8));b3 = SBox((U8)A);B = (b3<<24) | (b2<<16) | (b1<<8) | b0; //UINT32 B = (b0<<24) | (b1<<16) | (b2<<8) | b3;B1 = ROTATE_LEFT(B,2);B2 = ROTATE_LEFT(B,10);B3 = ROTATE_LEFT(B,18);B4 = ROTATE_LEFT(B,24);C = B^B1^B2^B3^B4;return Unpack_32((U8 *)(&C)); //return C;}U32 code FK[4] = {0xC6BAB1A3,0x5033AA56,0x97917D67,0xDC2270B2};U32 code CK[32] = {0x150e0700, 0x312a231c, 0x4d463f38, 0x69625b54,0x857e7770, 0xa19a938c, 0xbdb6afa8, 0xd9d2cbc4,0xf5eee7e0, 0x110a03fc, 0x2d261f18, 0x49423b34,0x655e5750, 0x817a736c, 0x9d968f88, 0xb9b2aba4,0xd5cec7c0, 0xf1eae3dc, 0x0d06fff8, 0x29221b14,0x453e3730, 0x615a534c, 0x7d766f68, 0x99928b84,0xb5aea7a0, 0xd1cac3bc, 0xede6dfd8, 0x0902fbf4,0x251e1710, 0x413a332c, 0x5d564f48, 0x79726b64};/* key convertion */U32 KT(U32 A){U32 xdata b0,b1,b2,b3;U32 xdata B,B1,B2,C;b0 = SBox((U8)(A>>24));b1 = SBox((U8)(A>>16));b2 = SBox((U8)(A>>8));b3 = SBox((U8)A);B = (b3<<24) | (b2<<16) | (b1<<8) | b0; //B = (b0<<24) | (b1<<16) | (b2<<8) | b3;//print32(B);B1 = ROTATE_LEFT(B,13);B2 = ROTATE_LEFT(B,23);C = B^B1^B2;return Unpack_32((U8 *)(&C)); //return C;}/* Key expantions */void SMS4Key(U32 MK[4], SM4_KEY *pSmsKey){int xdata i;U32 xdata tmpMK[4];UINT32 xdata K[36];tmpMK[0] = Unpack_32((UINT8 *)&MK[0]);tmpMK[1] = Unpack_32((UINT8 *)&MK[1]);tmpMK[2] = Unpack_32((UINT8 *)&MK[2]);tmpMK[3] = Unpack_32((UINT8 *)&MK[3]);K[0] = tmpMK[0]^FK[0];K[1] = tmpMK[1]^FK[1];K[2] = tmpMK[2]^FK[2];K[3] = tmpMK[3]^FK[3];for(i=0;i<32;i++){pSmsKey->rk[i] = K[i]^KT(K[i+1]^K[i+2]^K[i+3]^CK[i]);K[i+4] = pSmsKey->rk[i];}return ;}/* SMS4 Encrypt data*//* Input : UINT32 PlainOutput: UINT32 Cipher */void SMS4Enc (UINT32 Plain[4],UINT32 Cipher[4], SM4_KEY *pSmsKey) {int xdata i;UINT32 xdata tmpPlain[4];UINT32 xdata X[36];tmpPlain[0] = Unpack_32((UINT8 *)&Plain[0]);tmpPlain[1] = Unpack_32((UINT8 *)&Plain[1]);tmpPlain[2] = Unpack_32((UINT8 *)&Plain[2]);tmpPlain[3] = Unpack_32((UINT8 *)&Plain[3]);X[0] = tmpPlain[0];X[1] = tmpPlain[1];X[2] = tmpPlain[2];X[3] = tmpPlain[3];for(i=0;i<32;i++){X[i] = X[i]^T(X[i+1]^X[i+2]^X[i+3]^pSmsKey->rk[i]);X[i+4] = X[i];}Cipher[0] = Unpack_32((UINT8 *)&X[35]);Cipher[1] = Unpack_32((UINT8 *)&X[34]);Cipher[2] = Unpack_32((UINT8 *)&X[33]);Cipher[3] = Unpack_32((UINT8 *)&X[32]);//Nosa- printf("Cipher[0] =%X \n",Cipher[0]);return;}/* SMS4 Decrypt data*/void SMS4Dec (UINT32 Cipher[4],UINT32 Plain[4], SM4_KEY *pSmsKey) {int xdata i;UINT32 xdata tmpCipher[4] ;UINT32 xdata X[36];tmpCipher[0] = Unpack_32((UINT8 *)&Cipher[0]);tmpCipher[1] = Unpack_32((UINT8 *)&Cipher[1]);tmpCipher[2] = Unpack_32((UINT8 *)&Cipher[2]);tmpCipher[3] = Unpack_32((UINT8 *)&Cipher[3]);X[0] = tmpCipher[0];X[1] = tmpCipher[1];X[2] = tmpCipher[2];X[3] = tmpCipher[3];for(i=0;i<32;i++){// X[i] = X[i]^T(X[i+1]^X[i+2]^X[i+3]^smsKey.rk[i]);X[i] = X[i]^T(X[i+1]^X[i+2]^X[i+3]^pSmsKey->rk[31-i]);X[i+4] = X[i];}Plain[0] = Unpack_32((UINT8 *)&X[35]);Plain[1] = Unpack_32((UINT8 *)&X[34]);Plain[2] = Unpack_32((UINT8 *)&X[33]);Plain[3] = Unpack_32((UINT8 *)&X[32]);return;}/** func : sms4CBC_xor()* Input :* UINT8 * str1 : 异或源地址1* UINT8 * str2 : 异或源地址2* UINT8 * outStr:异或输出地址* UINT32 len:异或长度* Output :* 0 : 异或失败* Len : 异或长度* Func Desp : CBC模式的异或运算*/UINT32 sms4CBC_xor(UINT8 * str1, UINT8 * str2, UINT8 * outStr, UINT32 len){UINT32 xdata i;for (i = 0; i < len; i++){outStr[i] = str1[i] ^ str2[i];// printf("outStr[%d] = %x\n",i,outStr[i]);}return len;}/** func : Sms4CBC_E()* Input :* UINT8 *IV : IV,和密钥长度一样,128bits* UINT8 *M : 明文地址* UINT32 mLen: 明文长度* UINT8 *S:密文地址* UINT8 *pucKey : 密钥* Output :* -1 : 加密失败* Len : 加密后长度* Func Desp : CBC模式的加密运算*/UINT32 Sms4CBC_E(UINT8 *IV, UINT8 *M, UINT32 mLen, UINT8 *S, UINT8 *pucKey) {SM4_KEY xdata smsKey = {0};UINT32 xdata i = 0;UINT8 xdata sms4Buff[SM4_BLOCK_SIZE];UINT8 xdata *tmpM, *tmpS;tmpM = M;tmpS = S;SMS4Key((UINT32 *)pucKey, &smsKey);memcpy(sms4Buff, IV, SM4_BLOCK_SIZE);while((mLen - i) > 0){sms4CBC_xor(tmpM, sms4Buff, sms4Buff, SM4_BLOCK_SIZE); //先异或SMS4Enc((UINT32 *)sms4Buff, (UINT32 *)tmpS, &smsKey); //再加密memcpy(sms4Buff, tmpS, SM4_BLOCK_SIZE); //保留上一轮的加密结果tmpS = tmpS + SM4_BLOCK_SIZE;tmpM = tmpM + SM4_BLOCK_SIZE;i = i + SM4_BLOCK_SIZE;}return i;}/** func : Sms4CBC_D()* Input :* UINT8 *IV : IV,和密钥长度一样,128bits* UINT8 *M : 明文地址* UINT32 mLen: 密文长度* UINT8 *S:密文地址* UINT8 *pucKey : 密钥* Output :* -1 : 解密失败* Len : 解密后长度* Func Desp : CBC模式的解密运算*/UINT32 Sms4CBC_D(UINT8 *IV, UINT8 *M, UINT32 mLen, UINT8 *S, UINT8 *pucKey){SM4_KEY xdata smsKey = {0};UINT32 xdata i = 0;UINT8 xdata sms4Buff[SM4_BLOCK_SIZE];UINT8 xdata *tmpM, *tmpS;tmpM = M;tmpS = S;SMS4Key((UINT32 *)pucKey, &smsKey);memcpy(sms4Buff, IV, SM4_BLOCK_SIZE);while((mLen - i) > 0){SMS4Dec((UINT32 *)tmpS, (UINT32 *)tmpM, &smsKey); //先解密sms4CBC_xor(tmpM, sms4Buff, tmpM, SM4_BLOCK_SIZE); //再异或memcpy(sms4Buff, tmpS, SM4_BLOCK_SIZE); //保留上一轮结果tmpS = tmpS + SM4_BLOCK_SIZE;tmpM = tmpM + SM4_BLOCK_SIZE;i = i + SM4_BLOCK_SIZE;}return i;}/** func : Sms4ECB_E()* Input :* UINT8 *M : 明文地址* UINT32 mLen: 明文长度* UINT8 *S:密文地址* UINT8 *pucKey : 密钥* Output :* -1 : 加密失败* Len : 加密后长度* Func Desp : CBC模式的加密运算*/UINT32 Sms4ECB_E(UINT8 *M, UINT32 mLen, UINT8 *S, UINT8 *pucKey){SM4_KEY xdata smsKey = {0};UINT32 xdata i = 0;UINT8 xdata *tmpM, *tmpS;tmpM = M;tmpS = S;SMS4Key((UINT32 *)pucKey, &smsKey);while((mLen - i) > 0){SMS4Enc((UINT32 *)tmpM, (UINT32 *)tmpS, &smsKey); //加密tmpS = tmpS + SM4_BLOCK_SIZE;tmpM = tmpM + SM4_BLOCK_SIZE;i = i + SM4_BLOCK_SIZE;}return i;}/** func : Sms4ECB_D()* Input :* UINT8 *M : 明文地址* UINT32 mLen: 密文长度* UINT8 *S:密文地址* UINT8 *pucKey : 密钥* Output :* -1 : 解密失败* Len : 解密后长度* Func Desp : CBC模式的解密运算*/UINT32 Sms4ECB_D(UINT8 *M, UINT32 mLen, UINT8 *S, UINT8 *pucKey){SM4_KEY xdata smsKey = {0};UINT32 xdata i = 0;UINT8 xdata *tmpM, *tmpS;tmpM = M;tmpS = S;SMS4Key((UINT32 *)pucKey, &smsKey);//printf("tempS = %X\n",*tmpS);while((mLen - i) > 0){SMS4Dec((UINT32 *)tmpS, (UINT32 *)tmpM, &smsKey); //解密tmpS = tmpS + SM4_BLOCK_SIZE;tmpM = tmpM + SM4_BLOCK_SIZE;i = i + SM4_BLOCK_SIZE;}return i;}#if 1/** func : SMS4_fill()* Input :* UINT8 *in : 源地址* UINT8 *len : 源长度* Output :* Func Desp : 填充函数*/void SMS4_fill(UINT8 *in, UINT32 *len){UINT32 xdata tmpLen = 0;UINT8 xdata fillByte = 0;UINT8 xdata *p = NULL;tmpLen = *len;p = in;if (tmpLen & 0x0f) //不是16的整数倍{fillByte = 16 - (tmpLen & 0x0f);memset(p + tmpLen, fillByte, fillByte);}else //16的整数倍{fillByte = 0;}*len = *len + fillByte;}#endif#if 0/** func : SMS4_fill()* Input :* UINT8 *in : 源地址* UINT8 *len : 源长度* Output :* Func Desp : 填充函数*/void SMS4_fill(UINT8 *in, INT32 *len){INT32 xdata tmpLen;UINT8 xdata *p,fillByte;tmpLen = *len;p = in;if (tmpLen & 0x0f) //不是16的整数倍{fillByte = 16 - (tmpLen & 0x0f);}else //16的整数倍{fillByte = 16;}memset(p + tmpLen, fillByte, fillByte);*len = *len + fillByte;}#endif/** func : SMS4_E()* Input :* UINT8 *IV : IV,和密钥长度一样,128bits,如果是ECB模式,可以填0* UINT8 *M : 明文地址* UINT32 mLen: 明文长度* UINT8 *S:密文地址* UINT8 *key : 密钥* UINT8 mode:SMS4模式选择0 ecb 1:cbc* Output :* -1 : 加密失败* Len : 加密后长度* Func Desp : SMS4的加密运算*/UINT32 SMS4_E(UINT8 *IV, UINT8 *M, UINT32 mLen, UINT8 *S, UINT8 *key, UINT8 mode) {UINT32 xdata tmpLen = mLen;if (!M || !S || !key || mLen <= 0 || mLen > SM4_MAX_LEN)return -1;SMS4_fill(M, &tmpLen);if (tmpLen & 0x0f || tmpLen > (SM4_MAX_LEN + SM4_BLOCK_SIZE))return -1;switch (mode){case SM4_MODE_ECB:return Sms4ECB_E(M, tmpLen, S, key);break;case SM4_MODE_CBC:if (!IV)return -1;return Sms4CBC_E(IV, M, tmpLen, S, key);break;default:return -1;}}/** func : SMS4_D()* Input :* UINT8 *IV : IV,和密钥长度一样,128bits,如果是ECB模式,可以填0* UINT8 *M : 明文地址* UINT32 mLen: 密文长度* UINT8 *S:密文地址* UINT8 *key : 密钥* UINT8 mode:SMS4模式选择* Output :* -1 : 加密失败* Len : 加密后长度* Func Desp : SMS4的解密运算*/UINT32 SMS4_D(UINT8 *IV, UINT8 *M, UINT32 mLen, UINT8 *S, UINT8 *key, UINT8 mode) {UINT32 xdata tmpLen = mLen;if (!M || !S || !key || mLen <= 0)return -1;if (mLen & 0x0f || mLen > (SM4_MAX_LEN + SM4_BLOCK_SIZE))return -1;switch (mode){case SM4_MODE_ECB:{tmpLen = Sms4ECB_D(M, mLen, S, key);break;}case SM4_MODE_CBC:{if (!IV)return -1;tmpLen = Sms4CBC_D(IV, M, mLen, S, key);break;}default:return -1;}return tmpLen;}void SM4_Init(UINT8 * key){memcpy(S_M_S4_ke_y, key, 16);//return 0;}void SM4_Crypto(UINT8*in, U32 inLen, UINT8 En_De, UINT8 mode, UINT8 *iv,UINT8*out) {if(En_De){SMS4_D(iv, out, inLen, in, S_M_S4_ke_y, mode);}else{SMS4_E(iv, in, inLen, out, S_M_S4_ke_y, mode);}//return 0;}void SM4_Close(){//return 0;}。

相关文档
最新文档