-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontent.json
1 lines (1 loc) · 15 KB
/
content.json
1
{"meta":{"title":"ly随笔","subtitle":null,"description":"寻光者","author":"longye45","url":"https://longye45.github.io"},"pages":[{"title":"","date":"2018-03-09T10:19:16.171Z","updated":"2017-10-30T12:05:13.268Z","comments":false,"path":"categories/index.html","permalink":"https://longye45.github.io/categories/index.html","excerpt":"","text":""},{"title":"","date":"2018-03-09T10:19:16.173Z","updated":"2017-10-30T12:04:45.926Z","comments":false,"path":"tags/index.html","permalink":"https://longye45.github.io/tags/index.html","excerpt":"","text":""}],"posts":[{"title":"国密算法SM4的Java与JavaScript实现","slug":"SM4的加密实现","date":"2017-12-06T08:01:05.016Z","updated":"2018-03-22T03:23:15.153Z","comments":true,"path":"2017/12/06/SM4的加密实现/","link":"","permalink":"https://longye45.github.io/2017/12/06/SM4的加密实现/","excerpt":"","text":"SM4加密的实现前言最近项目中需要对数据进行加密处理,由于项目的特殊性要求,加密统一采用国密算法进行加密。网上对国密算法的资料有限,且没有找到对应的JavaScript加密代码,无奈之下只得自己实现。加密的算法文档在国家密码管理局官网上可以查找到,此次的算法实现仅限于SM3与SM4的代码实现,SM2由于项目未做特殊要求因此还未来得及实现。 SM4密码杂凑算法简介 SM4算法是一种对称分组加密算法。该算法的分组长度为 128 比特,密钥长度为 128 比特。加密算法与密钥扩展算法都采用 32 轮非线性迭代结构。解密算法与加密算法的结构相同,只是轮询密钥的使用顺序相反,解密轮密钥是加密轮密钥的逆序。 SM4算法加密过程 根据加密密钥生成轮询密钥根据密钥的不同,按照一定规律生成32个字(每个字四个字节)的轮询密钥,用于之后数据的加密; 将分组后的数据用轮询秘钥进行加密 加密的过程主要是用T方法和L方法,T方法转换过程中会用SBOX做一次非线性置换,经过这两个方法进行加密。 SM4算法的解密过程 根据加密密钥生成轮询密钥根据密钥的不同,按照一定规律生成32个字(每个字四个字节)的轮询密钥,用于之后数据的加密; 将分组后的数据逆向用轮询秘钥进行加密解密的过程主要是用T方法和L方法,T方法转换过程中会用SBOX做一次非线性置换,经过这两个方法进行加密。 SM4代码实现过程java中的SM4实现 代码中encrpt() 方法是供调用的Java的方法,方法的返回值是加密完成的数组,本方法有一个传入整型数据的重载方法,表示SM4加密次数; keyExtend()方法为扩展秘钥的方法; generateKey()方法为未指定密钥时自动生成随机密钥的方法,不需要再使用时调用,程序会在初始化时查找密钥,若未指定自动生成密钥; decrpt()方法为解密方法,同样提供传入整型的重写方法,用来解密经SM4加密多次后的数据,注意使用本方法时必须指定密钥(新建SM4对象时),或者直接在加密的对象中使用。 getKeyStr()方法用来获取加解密的密钥十六进制字符串格式 其他方法均为以上方法的子方法,由于设计较为底层的算法故不加赘述,具体请参照官方算法说明文档。 123456789101112131415161718192021222324252627/** * 加密 * * @return */ public byte[] encrpt() { this.bytes = addBytes(new byte[16 - (this.bytes.length % 16 == 0 ? 16 : this.bytes.length % 16)]); keyExtend();// 生成轮询密钥 int nowPo = 0;// 当前字开始位置 for (int i = 0; i < this.bytes.length / BLOCK; i++, nowPo += BLOCK) {// 分组 int[] rows = new int[4 + 32]; for (int j = 0; j < 4; j++) { rows[j] = byteArrayToInt(this.bytes, nowPo + j * 4); } for (int k = 0; k < 32; k++) { rows[k + 4] = rows[k] ^ TMethod(rows[k + 1] ^ rows[k + 2] ^ rows[k + 3] ^ this.rks[k]); } for (int k = 0; k < 4; k++) { System.arraycopy(intToByteArray(rows[35 - k]), 0, this.bytes, nowPo + 4 * k, 4); } } /* * 将未分组byte移到结果 */ System.arraycopy(this.bytes, this.bytes.length / BLOCK * BLOCK, this.bytes, this.bytes.length / BLOCK * BLOCK, this.bytes.length % BLOCK); return this.bytes; } 123456789101112/** * 密钥扩展算法 */ private void keyExtend() { int[] K = new int[36]; int[] keys = { this.key[0] ^ this.FKS[0], this.key[1] ^ this.FKS[1], this.key[2] ^ this.FKS[2], this.key[3] ^ this.FKS[3] }; System.arraycopy(keys, 0, K, 0, keys.length); for (int i = 0; i < 32; i++) { this.rks[i] = K[i] ^ TPMethod(K[i + 1] ^ K[i + 2] ^ K[i + 3] ^ CK[i]); K[i + 4] = this.rks[i]; } } 1234567891011/** * 随机生成密钥 */ private void generateKey() { byte[] var2 = new byte[32]; this.random.nextBytes(var2); for (int i = 0; i < KEYLENGTH; i++) { this.key[i] = byteArrayToInt(var2, 4 * i); } isKeyInit = true; } 123456789101112131415161718192021222324252627/** * 加密 * * @return */ public byte[] encrpt() { this.bytes = addBytes(new byte[16 - (this.bytes.length % 16 == 0 ? 16 : this.bytes.length % 16)]); keyExtend();// 生成轮询密钥 int nowPo = 0;// 当前字开始位置 for (int i = 0; i < this.bytes.length / BLOCK; i++, nowPo += BLOCK) {// 分组 int[] rows = new int[4 + 32]; for (int j = 0; j < 4; j++) { rows[j] = byteArrayToInt(this.bytes, nowPo + j * 4); } for (int k = 0; k < 32; k++) { rows[k + 4] = rows[k] ^ TMethod(rows[k + 1] ^ rows[k + 2] ^ rows[k + 3] ^ this.rks[k]); } for (int k = 0; k < 4; k++) { System.arraycopy(intToByteArray(rows[35 - k]), 0, this.bytes, nowPo + 4 * k, 4); } } /* * 将未分组byte移到结果 */ System.arraycopy(this.bytes, this.bytes.length / BLOCK * BLOCK, this.bytes, this.bytes.length / BLOCK * BLOCK, this.bytes.length % BLOCK); return this.bytes; } 1234567891011/** * 随机生成密钥 */ private void generateKey() { byte[] var2 = new byte[32]; this.random.nextBytes(var2); for (int i = 0; i < KEYLENGTH; i++) { this.key[i] = byteArrayToInt(var2, 4 * i); } isKeyInit = true; } JavaScript中的SM4实现由于Java代码的完成时间较早,JavaScript的实现代码是从Java代码移植过来的,方法命名大同小异,因此不加赘述。代码版面较长,本文就不贴了,请移步github查看。 SM3加密的使用方法SM4加密的Java使用最近事务繁多无法抽身用设计模式对本算法进行优化,为了稳定运行只能牺牲性能采用实例化后调用的方式进行。由于底层计算都是位运算实际使用情况尚可,以下是在Java中的使用方式: 123456public static void main(String args[]){ SM4Encrp sm4 = new SM4Encrp(new byte[]{0x43,0x35});//传入要加密的数据,使用内部生成随机密钥的方式进行,也可使用提供的其他构造方法 byte bt = sm4.encrpt();//加密 SM4Encrp sm4de = new SM4Encrp(bt,sm4.getKeyStr);//传入需要解密的数据和加密用的密钥 byte btSource = sm4de.decrpt();//解密获取原数据 } SM4加密的JavaScript使用由于前台多是处理字符串和二进制数据,故统一采用传递二进制的方式进行杂凑计算。如果有求字符串杂凑值的必要可以调用以下方法转换为二进制byte数组进行使用 123456789101112131415161718192021222324252627282930313233343536/** * 字符串转byte数组 * * @param {*字符串} * str */function stringToByte(str){ var bytes = new Array(); var len, c; len = str.length; for (var i = 0; i < len; i++) { c = str.charCodeAt(i); if (c >= 0x010000 && c <= 0x10FFFF) { bytes.push(((c >> 18) & 0x07) | 0xF0); bytes.push(((c >> 12) & 0x3F) | 0x80); bytes.push(((c >> 6) & 0x3F) | 0x80); bytes.push((c & 0x3F) | 0x80); } else if (c >= 0x000800 && c <= 0x00FFFF) { bytes.push(((c >> 12) & 0x0F) | 0xE0); bytes.push(((c >> 6) & 0x3F) | 0x80); bytes.push((c & 0x3F) | 0x80); } else if (c >= 0x000080 && c <= 0x0007FF) { bytes.push(((c >> 6) & 0x1F) | 0xC0); bytes.push((c & 0x3F) | 0x80); } else { bytes.push(c & 0xFF); } } return bytes;} 使用方式如下所示: 12345678var test = new SM4Encrpt({ //实例化解密类 (key/keyStr):***,//指定的数组加密/解密密钥数组/密钥字符串,此参数若是加密可以省略,加密密钥由本类自动生成;若是解密必须指定该密钥 bytes/enStr:*** //需要加密/解密的二进制/字符串 }); test.encrpt();//此为加密方法 test.encrpt(100);//此为加密100次 test.decrpt();//此为解密方法 test.decrpt(100);//此为解密100次 小结 热衷造轮子, 方便造车人。 愿别人的收获中也有属于自己的耕耘。","categories":[{"name":"算法编程","slug":"算法编程","permalink":"https://longye45.github.io/categories/算法编程/"}],"tags":[{"name":"加密","slug":"加密","permalink":"https://longye45.github.io/tags/加密/"},{"name":"Java","slug":"Java","permalink":"https://longye45.github.io/tags/Java/"},{"name":"JavaScript","slug":"JavaScript","permalink":"https://longye45.github.io/tags/JavaScript/"}]},{"title":"国密算法SM3的Java与JavaScript实现","slug":"国密加密算法的Java与JavaScript实现","date":"2017-12-04T01:29:37.428Z","updated":"2017-12-06T08:12:42.185Z","comments":true,"path":"2017/12/04/国密加密算法的Java与JavaScript实现/","link":"","permalink":"https://longye45.github.io/2017/12/04/国密加密算法的Java与JavaScript实现/","excerpt":"","text":"SM3加密的实现前言最近项目中需要对数据进行加密处理,由于项目的特殊性要求,加密统一采用国密算法进行加密。网上对国密算法的资料有限,且没有找到对应的JavaScript加密代码,无奈之下只得自己实现。加密的算法文档在国家密码管理局官网上可以查找到,此次的算法实现仅限于SM3与SM4的代码实现,SM2由于项目未做特殊要求因此还未来得及实现。 SM3密码杂凑算法简介 SM3算法是一种验证签名类算法,类似于MD5或SHA1等算法,适用于商用密码应用中的数字签名和验证、消息认证码的生成与验证以及随机数的生成, 可满足多种密码应用的安全需求。 SM3杂凑过程1.数据填充将原数据二进制进行填充,填充后的消息m′ 的比特长度为512的倍数。2.消息扩展将填充后的消息m′按512比特进行分组,将每组消息分组B(i)按一定方法扩展生成132个字,每个字为四个字节。3.迭代压缩按照一定规律进行64次迭代压缩,压缩后的值存入8个字节寄存器里面。4得到杂凑值最终计算出256位杂凑值 SM3代码实现过程java中的SM3实现代码中 getEncrpResult() 方法是获取杂凑值的方法,方法的返回值是一个整型数组,大部分的杂凑值为了便于查看与比较,通常采用十六进制的字符串进行表示,本类也同样提供实现方法,实现方法是 getStringEncrpResult() 。其他方法均为以上方法的子方法,由于设计较为底层的算法故不加赘述,具体请参照官方算法说明文档。 1234567public int[] getEncrpResult() { fillBinDatas();// 填充 ExtendedPacket();// 扩展 IterationMethod();// 迭代压缩 return result; } 12345678910public String getStringEncrpResult(){ int[] rs = getEncrpResult(); String string = \"\"; for (int i = 0; i < rs.length; i++) { string += Integer.toHexString(rs[i]) + \" \"; } return string;} JavaScript中的SM3实现由于Java代码的完成时间较早,JavaScript的实现代码是从Java代码移植过来的,方法命名大同小异,因此不加赘述。加密方法为 getEncrpResult() 和 getStringEncrpResult() 。 12345678me.getEncrpResult = function() { me.init(); fillBinDatas();// 填充 ExtendedPacket();// 扩展 IterationMethod();// 迭代压缩 return me.result; } 123456789101112me.getStringEncrpResult = function() { var rs = me.getEncrpResult(); var string = \"\"; var res = new Uint32Array(me.result.length); copyArray(rs, 0, res, 0, rs.length); for (var i = 0; i < rs.length; i++) { string += res[i].toString(16) + \" \"; } return string; } SM3加密的使用方法SM3加密的Java使用本人水平有限无法熟练处理线程安全问题,为了稳定运行只能牺牲性能采用实例化后调用的方式进行。由于底层计算都是位运算实际使用情况尚可,以下是在Java中的使用方式: 12SM3Encrp sm3 = new SM3Encrp(new byte[] { 0x61, 0x62, 0x63, (byte) 0xff });String sm3Code = s.getStringEncrpResult(); 除了以上构造方法,还提供输入流和字符串的构造方法重载,基本上满足了项目中的使用。 SM3加密的JavaScript使用由于前台多是处理字符串和二进制数据,故统一采用传递二进制的方式进行杂凑计算。如果有求字符串杂凑值的必要可以调用以下方法转换为二进制byte数组进行使用 123456789101112131415161718192021222324252627282930313233343536/** * 字符串转byte数组 * * @param {*字符串} * str */function stringToByte(str){ var bytes = new Array(); var len, c; len = str.length; for (var i = 0; i < len; i++) { c = str.charCodeAt(i); if (c >= 0x010000 && c <= 0x10FFFF) { bytes.push(((c >> 18) & 0x07) | 0xF0); bytes.push(((c >> 12) & 0x3F) | 0x80); bytes.push(((c >> 6) & 0x3F) | 0x80); bytes.push((c & 0x3F) | 0x80); } else if (c >= 0x000800 && c <= 0x00FFFF) { bytes.push(((c >> 12) & 0x0F) | 0xE0); bytes.push(((c >> 6) & 0x3F) | 0x80); bytes.push((c & 0x3F) | 0x80); } else if (c >= 0x000080 && c <= 0x0007FF) { bytes.push(((c >> 6) & 0x1F) | 0xC0); bytes.push((c & 0x3F) | 0x80); } else { bytes.push(c & 0xFF); } } return bytes;} 完整的使用过程如下: 12345678var sm = new SM3Entrpt([0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, 0x61,0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64]); var result = sm.getStringEncrpResult(); 如果要求字符串的杂凑值,使用方法如下: 123var str = \"测试代码\";var sm = new SM3Entrpt(stringToByte(str));var result = sm.getStringEncrpResult(); 小结 九层之台起于累土,千里之行始于足下。 愿别人的收获中也有属于自己的耕耘。","categories":[{"name":"算法编程","slug":"算法编程","permalink":"https://longye45.github.io/categories/算法编程/"}],"tags":[{"name":"加密","slug":"加密","permalink":"https://longye45.github.io/tags/加密/"},{"name":"Java","slug":"Java","permalink":"https://longye45.github.io/tags/Java/"},{"name":"JavaScript","slug":"JavaScript","permalink":"https://longye45.github.io/tags/JavaScript/"}]}]}