SM4:无线局域网标准的分组数据算法。对称加密,密钥长度和分组长度均为128位。
此算法是一个分组算法,用于无线局域网产品。该算法的分组长度为128比特,密钥长度为128比特。加密算法与密钥扩展算法都采用32轮非线性迭代结构。解密算法与加密算法的结构相同,只是轮密钥的使用顺序相反,解密轮密钥是加密轮密钥的逆序。
此算法采用非线性迭代结构,每次迭代由一个轮函数给出,其中轮函数由一个非线性变换和线性变换复合而成,非线性变换由S盒所给出。其中rki为轮密钥,合成置换T组成轮函数。轮密钥的产生与上图流程类似,由加密密钥作为输入生成,轮函数中的线性变换不同,还有些参数的区别。
过程:
基本运算:SM4密码算法使用模2加和循环移位作为基本运算。
基本密码部件:SM4密码算法使用了S盒、非线性变换τ、线性变换部件L、合成变换T基本密码部件。
轮函数:SM4密码算法采用对基本轮函数进行迭代的结构。利用上述基本密码部件,便可构成轮函数。SM4密码算法的轮函数是一种以字为处理单位的密码函数。
加密算法:SM4密码算法是一个分组算法。数据分组长度为128比特,密钥长度为128比特。加密算法采用32轮迭代结构,每轮使用一个轮密钥。
解密算法:SM4密码算法是对合运算,因此解密算法与加密算法的结构相同,只是轮密铝的使用顺序相反,解密轮密钥是加密轮密钥的逆序。
密钥扩展算法:SM4密码算法使用128位的加密密钥,并采用32轮法代加密结构,每一轮加密使用一个32位的轮密钥,共使用32个轮密钥。因此需要使用密钥扩展算法,从加密密钥产生出32个轮密钥。
SM4的安全性:SM4密码算法经过我国专业密码机构的充分分析测试,可以抵抗差分攻击、线性攻击等现有攻击,因此是安全的。
用法上基本一样,只不过密钥变成16字节,加密数据16字节,结果也是16字节。
public class Sm4Utils {
// 编码
private static final String ENCODING = "UTF-8";
// 加密名称
public static final String ALGORIGTHM_NAME = "SM4";
// 加密分组方式
public static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/PKCS7Padding";
//KEY长度
public static final int DEFAULT_KEY_SIZE = 128;
public Sm4Utils() {
}
static {
Security.addProvider(new BouncyCastleProvider());
}
// 生成ecb暗号
private static Cipher generateEcbCipher(String algorithmName, int mode, byte[] key) throws Exception {
Cipher cipher = Cipher.getInstance(algorithmName,BouncyCastleProvider.PROVIDER_NAME);
Key sm4Key = new SecretKeySpec(key, ALGORIGTHM_NAME);
cipher.init(mode, sm4Key);
return cipher;
}
// 生成密钥
public static byte[] generateKey() throws Exception {
return generateKey(DEFAULT_KEY_SIZE);
}
public static byte[] generateKey(int keySize) throws Exception {
KeyGenerator kg = KeyGenerator.getInstance(ALGORIGTHM_NAME, BouncyCastleProvider.PROVIDER_NAME);
kg.init(keySize, new SecureRandom());
return kg.generateKey().getEncoded();
}
// 加密
public static String encryptEcb(String hexKey, String paramStr, String charset) throws Exception {
String cipherText = "";
if (null != paramStr && !"".equals(paramStr)) {
byte[] keyData = ByteUtils.fromHexString(hexKey);
charset = charset.trim();
if (charset.length() <= 0) {
charset = ENCODING;
}
byte[] srcData = paramStr.getBytes(charset);
byte[] cipherArray = encrypt_Ecb_Padding(keyData, srcData);
cipherText = ByteUtils.toHexString(cipherArray);
}
return cipherText;
}
// 加密模式之ecb
public static byte[] encrypt_Ecb_Padding(byte[] key, byte[] data) throws Exception {
Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.ENCRYPT_MODE, key);
byte[] bs = cipher.doFinal(data);
return bs;
}
// Sm4解密
public static String decryptEcb(String hexKey, String cipherText, String charset) throws Exception {
String decryptStr = "";
byte[] keyData = ByteUtils.fromHexString(hexKey);
byte[] cipherData = ByteUtils.fromHexString(cipherText);
byte[] srcData = decrypt_Ecb_Padding(keyData, cipherData);
charset = charset.trim();
if (charset.length() <= 0) {
charset = ENCODING;
}
decryptStr = new String(srcData, charset);
return decryptStr;
}
// 解密
public static byte[] decrypt_Ecb_Padding(byte[] key, byte[] cipherText) throws Exception {
Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.DECRYPT_MODE, key);
return cipher.doFinal(cipherText);
}
// 密码校验
public static boolean verifyEcb(String hexKey,String cipherText,String paramStr) throws Exception {
boolean flag = false;
byte[] keyData = ByteUtils.fromHexString(hexKey);
byte[] cipherData = ByteUtils.fromHexString(cipherText);
byte[] decryptData = decrypt_Ecb_Padding(keyData,cipherData);
byte[] srcData = paramStr.getBytes(ENCODING);
flag = Arrays.equals(decryptData,srcData);
return flag;
}
public static void main(String[] args) {
try {
String json = "{\"name\":\"Devil\"}";
System.out.println("json: " + json);
String key = ByteUtils.toHexString(Sm4Utils.generateKey());
System.out.println("key: " + key);
String encryptJson= Sm4Utils.encryptEcb(key, json,ENCODING);
System.out.println("encryptJson: " + encryptJson);
System.out.println(Sm4Utils.verifyEcb(key, encryptJson, json));
String decryptJson = Sm4Utils.decryptEcb(key, encryptJson,ENCODING);
System.out.println("decryptJson: " + decryptJson);
} catch (Exception e) {
e.printStackTrace();
}
}
}
基础篇:解决”网上邻居”的访问故障Win7和XP的“网上邻居”无法访问对方时(局域网内互访和双机互联互访),可以参考以下解决方式(本贴以win7截图,XP设置与win7雷同…PS:由于本人使用是英文版系统,所以截图将会是英文配图,具体的中文将在步骤中说明,不再赘述).1.关闭防火墙.关闭win7和XP的防火墙,如果有第三方防火墙也请自行关闭. 下载 (81.97 KB)2010-10-9 21:5..._xp找不到win7的共享
大家好,我是雄雄,欢迎关注微信公众号【雄雄的小课堂】。最近这段时间一直在看开源框架,自己慢慢的琢磨,终于将jeecgboot环境搭建起来,并且成功的跑起来了demo,在此过程中,很明显的能..._springboot不能点击
Base64目前主要用于HTML5、移动开发等不考虑IE6的场景中。Base64格式data:[][;charset=][;base64],Base64 在CSS中的使用.demoImg{ background-image: url("data:image/jpg;base64,/9j/4QMZRXhpZgAASUkqAAgAAAAL...."); }Base64 在HTML中的使用
首先,捋一下安装jdk的思路。1.下载jdk2.将jdk解压缩到目标目录下3.配置环境变量接下来一步一步的来。下载jdk1.8网址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html我选择的是 jdk-8u144-linux-x64.tar.gz。
生产上踩过ArrayList的contains方法性能的坑背景在项目中,需要集合ArrayList存储大量数据时,有时候可能需要对新增数据去重判断时,我们会用到集合的contains方法,判断当前元素是否存在,存在则不存储,不存在则进行存储,本人在生产开发中就遇到contains方法带来的严重性能问题,今天我们将通过下面的contains方法源码分析,以及测试性能的方式,来告诉你ArrayLi..._contains坑
背景介绍现在世界上主要有三种温度单位, 开尔文(kelvin),摄氏度(celsius) 和 华氏度(fahrenheit)。程序代码-- coding: utf-8 --“”"Created on Wed Jan 8 14:30:46 2020@author: James“”"‘’’ Conversion between differenttemperature scales..._三种温度单位的换算
如果用户按下JList组件超过3秒,有没有办法捕获事件?我找到的困难部分是即使在用户松开鼠标左键之前也需要触发事件. (可以通过几个mousePressed和mouseReleased轻松完成)解决方法:以下是我用于类似情况的内容:public class Player implements Runnable, MouseListener{public void mousePressed(Mous..._java检测鼠标长按
字典 字典(dict)是python中唯一一个映射类型,在python中key是唯一的,在保存的时候,根据key计算出一个内存地址,然后将key-value保存在这个地址中,这种算法被称为hash算法.所以,在dict中存储的键值对中的key必须是可哈希的.(可以改变的都是不可哈希的,那么可哈希的就意味着不可变.)这是为了能准确地计算内存地址而规定的.还有,dict保存的数据不是按照..._dict.create().set 整数
跟Gradle有关系,在报错里我注意到了gradletool一词,于是我去到安卓工程项目级别下的build.gradle中修改了tools.build:gradle的版本,原本是4.0.0+的现改为:dependencies { classpath 'com.android.tools.build:gradle:3.5.0' }最后重新build运行安卓flutter就Ok了...
存储过程和函数类似于Java中的方法。⒈存储过程 一组预先编译好的sql语句的集合,理解成批处理语句。 好处: ①提高代码的重用性 ②简化操作 ③减少了编译次数并且减少了和数据库服务器的连接次数,提高了效率 1.创建语法 1 create procedure 存储过程名称(参数列表)2 begin3 存储过程...
#配置→主机→需要添加端口监控的ip→监控项#创建监控项#按照图内填入对应端口信息#端口监控项创建完成端口的监控不仅仅是要端口的数据的数据,更需要的是一个触发的机制,当端口不在时,触发告警,通知对应的业务人员及时处理,接下来是触发器的设置#配置→主机→触发器→创建触发器#输入名称(名称就是当你服务出现问题所展现的告警信息)#级别 (选择严重或是灾难,端口是监测一个业务是否存在的比较一个重要且有效的途径,对业务的监测起着至关重要的作用)#监控项 (找到刚新增的端口监控项)#功_zabbix 错误率