目录
加密算法
主流分类方式
- 流密码&分组密码
- 对称密码&非对称密码
国产加密算法
SM4分组加密算法(对称密码)
简单使用
参考 国产SM4密码算法详解
文章中源码链接已失效
在SM4的源代码中存在如下几个函数:
void sm4_setkey_enc(sm4_context *ctx,unsigned char key[16])
void sm4_setkey_dec(sm4_context *ctx,unsigned char key[16])
void sm4_crypt_ecb( sm4_context *ctx,int mode,int length, unsigned char *input,unsigned char *output)
void sm4_crypt_cbc( sm4_context *ctx,int mode,int length,unsigned char iv[16],unsigned char *input,unsigned char output )
static void sm4_setkey( unsigned long SK[32], unsigned char key[16] )
还有一个非常重要的结构体:sm4_context
typedef struct
{
int mode; /!< encrypt/decrypt /
unsigned long sk[32]; /!< SM4 subkeys */
}sm4_context;
先说结构体:
sm4_context结构体中的Mode控制是加密还是解密,sk则表示子密钥,也称作轮密钥。
第一个函数: void sm4_setkey_enc(sm4_context *ctx,unsigned char key[16])
这个函数是用来设置加密密钥的,一个参数分别为sm4_context *ctx和一个key。
其内部会调用static void sm4_setkey( unsigned long SK[32], unsigned char key[16] )
函数
这个函数是用来设置密钥的,这个函数内部会对当前传入的主密钥进行32轮的迭代,每次迭代的轮密钥都被存放到ctx结构中的sk数组中。
void sm4_setkey_dec(sm4_context *ctx,unsigned char key[16])
函数就是解密函数,过程为上述过程的逆序过程。
第二个函数:void sm4_crypt_ecb( sm4_context *ctx,int mode,int length, unsigned char *input,unsigned char *output)
这个函数的作用是使用ecb模式(ECB(Electronic Codebook,电码本)模式是分组密码的一种最基本的工作模式。同样,sm4_crypt_cbc函数则是使用的CBC模式,也就是分组链接模式)来对内容进行加密,内部也是一个循环,根据length的长度来进行循环,每次循环都调用sm4_one_round进行加密或者解密,到底是加密还是解密,主要是根据第二个参数Mode来进行决定。
以上就是整个SM4算法的函数简介,运用这些函数接口,我们不需要知道内部的具体实现,就可以使用sm4加密算法来对我们的数据进行加解密,十分的方便。
分组加密回顾
运行模式
模式 | 描述 | 优点 | 缺点 | 用途 |
---|---|---|---|---|
电码本模式(ECB) | 每个明文组(64bit)以同一密钥加密 | 误差不传导 | 可能出现短块(自行填充);暴露明文数据模式 | 传送短数据 |
密码分组链接模式(CBC) | 加密算法的输入是当前明文组与前一密文组的异或 | 错误传播无界 :用于检测数据的完整性和真实性 | 错误传播无界 :一处错误—>一直错误 | 传送数据分组;认证 |
密码反馈模式(CFB) | 每次只处理输入的j比特,将上一次的密文用作加密算法的输入以产生伪随机输入,该输入再与当前明文异或以产生密文 | 无需填充; 比特错误传播 可用最后一位认证所有明文;自同步 | 比特错误传播 | 传送数据流;认证 |
输出反馈模式(OFB) | 与CFB类似,不同之处是本次加密算法的输入为前一次加密算法的输出 | 比特错误不会传播 | 有扰信道上(如卫星通讯)传送数据流 |
ECB: 一般意义理解
CBC: 需要初始向量IV (IV需要进行保护)
加密:
C1=Ek[IV⊕P1]
Ci=Ek[Ci-1⊕Pi]
解密:
P1=IV⊕Dk[C1]
Pi=Ci-1⊕Dk[Ci]
保护IV:如果敌方能欺骗接收方使用不同的IV,敌方就能在明文的第一分组中插入自己选择的比特值
P1(i)=IV(i)⊕Dk[C1] (i)
P1(i)’=IV(i)'⊕Dk[C1] (i)
CFB: 需要初始向量IV
可以将
分组密码
转化为流密码
故而无需填充
OFB模式
初始向量,无填充 ,流密码
CTR - CounTeR, 计数器模式(重点,推荐使用)
特点: 密文没有规律, 明文分组是和一个数据流进行的按位异或操作, 最终生成了密文
- 不需要初始化向量
- 不需要填充
这里我们有必要给出CTR模式的加密流程,因为CTR模式的解密和加密是一模一样的过程,在程序实现中也是可逆的.
CTR加密即解密,解密即加密,且各分组之间是独立的,可以并发完成,效率高。
数据填充
-
NoPadding
明文数据必须为8字节的整数倍,自动零比特填充 -
PKCS7Padding(PKCS5Padding)
为.NET和JAVA的默认填充方式,对加密数据字节长度对8取余为r,如r大于0,则补8-r个字节,字节为8-r的值;如果r等于0,则补8个字节8。比如:
加密字符串为为AA,则补位为AA666666;加密字符串为BBBBB,则补位为BBBBB333;加密字符串为CCCCCCCC,则补位为CCCCCCCC88888888。
JDK中AES算法中不支持PKCS7Padding,只支持PKCS5Padding 但是PKCS7Padding 和 PKCS5Padding 没有什么区别要实现在java端用PKCS7Padding填充,需要用到bouncycastle组件来实现
原理参考
原理参考:SM4 算法原理