查看: 463|回复: 5

用javascript实现字符串的sm4加密

[复制链接]
论坛徽章:
403
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
发表于 2020-5-19 14:10 | 显示全部楼层 |阅读模式
本帖最后由 〇〇 于 2020-5-19 14:13 编辑

https://www.npmjs.com/package/sm-crypto

https://github.com/wechat-miniprogram/sm-crypto
测试

  1. function test_sm4(ss)
  2. {
  3. //长度填充为16的倍数
  4. len=ss.length
  5. n=len%16
  6. ss+=new Array(n+1).join("\0")
  7. //字符串转16位无符号整数数组
  8. u16 = new Uint16Array(ss.split('').map(function(x){return x.charCodeAt(0);}));
  9. console.log(u16)
  10. //16位无符号整数数组转为8位无符号整数数组
  11. u8 = new Uint8Array(u16.buffer, u16.byteOffset, u16.byteLength);
  12. console.log(u8)
  13. //对8位无符号整数数组sm4加密
  14. s8 = sm4.encrypt(u8,key)
  15. console.log(s8)
  16. //对8位无符号整数数组sm4解密
  17. d8 = sm4.decrypt(s8,key)
  18. console.log(d8)
  19. //将8位无符号整数数组转为16位无符号整数数组,或恢复原文
  20. a16 = new Uint16Array(d8.length/2)
  21. s = ""
  22. for (i=0;i<d8.length/2;i++)
  23. {
  24. a16[i]=d8[2*i]+d8[2*i+1]*256
  25. s+=String.fromCharCode(a16[i])
  26. }
  27. console.log(a16)
  28. return s.substr(0,len)
  29. }
复制代码
论坛徽章:
403
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
 楼主| 发表于 2020-5-19 19:22 | 显示全部楼层
再加入压缩

  1. pako=require('../pako.min.js')
  2. function test_sm4(ss)
  3. {
  4. //长度填充为16的倍数
  5. len=ss.length
  6. n=16-len%16
  7. ss+=new Array(n+1).join("\0")
  8. //字符串转16位无符号整数数组
  9. u16 = new Uint16Array(ss.split('').map(function(x){return x.charCodeAt(0);}));
  10. //console.log(u16)
  11. //16位无符号整数数组转为8位无符号整数数组
  12. u8 = new Uint8Array(u16.buffer, u16.byteOffset, u16.byteLength);
  13. //console.log(u8)
  14. console.log("source "+u8.length)
  15. //压缩gz
  16. var c8    = pako.deflate(u8);
  17. console.log("compressed "+c8.length)
  18. //console.log(u8)
  19. //长度填充为16的倍数
  20. len2=c8.length
  21. n2=16-len2%16
  22. //c8.concat(Array(n2).fill(0))
  23. c82= new Uint8Array(len2+n2)
  24. for (i=0;i<len2;i++)
  25. c82[i]=c8[i]
  26. console.log(c82)
  27. //对8位无符号整数数组sm4加密
  28. s8 = sm4.encrypt(c82,key)
  29. console.log("compressed & encode "+s8.length)
  30. //console.log(s8)
  31. //对8位无符号整数数组sm4解密
  32. d8 = sm4.decrypt(s8,key)
  33. //console.log(d8)
  34. console.log("compressed & decode "+d8.length)
  35. d8 = d8.slice(0,len2)
  36. console.log("sliced "+d8.length)
  37. //解压gz
  38. var e8    = pako.inflate(d8);
  39. console.log("decompressed "+e8.length)
  40. console.log(e8)
  41. //将8位无符号整数数组转为16位无符号整数数组,或恢复原文
  42. a16 = new Uint16Array(e8.length/2)
  43. s = ""
  44. for (i=0;i<e8.length/2;i++)
  45. {
  46. a16[i]=e8[2*i]+e8[2*i+1]*256
  47. s+=String.fromCharCode(a16[i])
  48. }
  49. //console.log(a16)
  50. return s.substr(0,len)
  51. }
  52. x2='将8位无符号整数数组转为16位无符号整数数组,或恢复原文'
  53. test_sm4(x2)
复制代码

使用道具 举报

回复
论坛徽章:
403
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
 楼主| 发表于 2020-5-19 22:18 | 显示全部楼层
又加入了Base64编码和解码

  1. function test_sm4(ss)
  2. {
  3. //长度填充为16的倍数
  4. len=ss.length
  5. n=16-len%16
  6. ss+=new Array(n+1).join("\0")
  7. //字符串转16位无符号整数数组
  8. u16 = new Uint16Array(ss.split('').map(function(x){return x.charCodeAt(0);}));
  9. //console.log(u16)
  10. //16位无符号整数数组转为8位无符号整数数组
  11. u8 = new Uint8Array(u16.buffer, u16.byteOffset, u16.byteLength);
  12. //console.log(u8)
  13. console.log("source "+u8.length)
  14. //压缩gz
  15. var c8    = pako.deflate(u8);
  16. console.log("compressed "+c8.length)
  17. //console.log(u8)
  18. //长度填充为16的倍数
  19. len2=c8.length
  20. n2=16-len2%16
  21. //c8.concat(Array(n2).fill(0))
  22. c82= new Uint8Array(len2+n2)
  23. for (i=0;i<len2;i++)
  24. c82[i]=c8[i]
  25. //console.log(c82)
  26. //对8位无符号整数数组sm4加密
  27. s8 = sm4.encrypt(c82,key)
  28. console.log("compressed & encode "+s8.length)
  29. //console.log(s8)
  30. //把Uint8Array转为base64字符串
  31. b64=base64js.fromByteArray(s8)
  32. //console.log('base64 '+b64)
  33. console.log('base64 '+b64.length)

  34. //把base64字符串转为Uint8Array
  35. s81=base64js.toByteArray(b64)
  36. console.log(s81.length)
  37. //对8位无符号整数数组sm4解密
  38. d8 = sm4.decrypt(s81,key)
  39. //console.log(d8)
  40. console.log("compressed & decode "+d8.length)
  41. d8 = d8.slice(0,len2)
  42. console.log("sliced "+d8.length)
  43. //解压gz
  44. var e8    = pako.inflate(d8);
  45. console.log("decompressed "+e8.length)
  46. //console.log(e8)
  47. //将8位无符号整数数组转为16位无符号整数数组,或恢复原文
  48. a16 = new Uint16Array(e8.length/2)
  49. s = ""
  50. for (i=0;i<e8.length/2;i++)
  51. {
  52. a16[i]=e8[2*i]+e8[2*i+1]*256
  53. s+=String.fromCharCode(a16[i])
  54. }
  55. //console.log(a16)
  56. return s.substr(0,len)
  57. }

复制代码

> test_sm4(x2+x2)
source 128
compressed 54
compressed & encode 64
base64 88
64
compressed & decode 64
sliced 54
decompressed 128
'将8位无符号整数数组转为16位无符号整数数组,或恢复原文将8位无符号整数数组转为16位无符号整数数组,或恢复原文'

使用道具 举报

回复
论坛徽章:
403
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
 楼主| 发表于 2020-5-19 22:26 | 显示全部楼层
安装
npm install base64-js
var base64js = require('base64-js')

使用道具 举报

回复
论坛徽章:
403
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
 楼主| 发表于 2020-5-21 15:01 | 显示全部楼层
str转uf8的代码

  1. fs=function(str) {
  2.   // TODO(user): Use native implementations if/when available
  3.   var out = [], p = 0;
  4.   for (var i = 0; i < str.length; i++) {
  5.     var c = str.charCodeAt(i);
  6.     if (c < 128) {
  7.       out[p++] = c;
  8.     } else if (c < 2048) {
  9.       out[p++] = (c >> 6) | 192;
  10.       out[p++] = (c & 63) | 128;
  11.     } else if (
  12.         ((c & 0xFC00) == 0xD800) && (i + 1) < str.length &&
  13.         ((str.charCodeAt(i + 1) & 0xFC00) == 0xDC00)) {
  14.       // Surrogate Pair
  15.       c = 0x10000 + ((c & 0x03FF) << 10) + (str.charCodeAt(++i) & 0x03FF);
  16.       out[p++] = (c >> 18) | 240;
  17.       out[p++] = ((c >> 12) & 63) | 128;
  18.       out[p++] = ((c >> 6) & 63) | 128;
  19.       out[p++] = (c & 63) | 128;
  20.     } else {
  21.       out[p++] = (c >> 12) | 224;
  22.       out[p++] = ((c >> 6) & 63) | 128;
  23.       out[p++] = (c & 63) | 128;
  24.     }
  25.   }
  26.   return out;
  27. };
复制代码

转换后存储空间英文变小,中文变大
> x="// TODO(user): Use native implementations if/when available"
'// TODO(user): Use native implementations if/when available'
> x.length
59
> fs(x).length
59
> x2='UTF-8的特点是对不同范围的字符使用不同长度的编码。对于0x00-0x7F之间的字符,UTF-8编码与ASCII编码完全相同。'
'UTF-8的特点是对不同范围的字符使用不同长度的编码。对于0x00-0x7F之间的字符,UTF-8编码与ASCII编码完全相同。'
> x2.length
64
> fs(x2).length
144

使用道具 举报

回复
论坛徽章:
403
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
 楼主| 发表于 2020-5-21 20:08 | 显示全部楼层
本帖最后由 〇〇 于 2020-5-21 22:27 编辑

最后一步人工转8位整数数组为16位数组是不必要的

  1. function test_sm4(ss)
  2. {
  3. //长度填充为16的倍数
  4. len=ss.length
  5. n=8-len%8
  6. ss+=new Array(n+1).join("\0")
  7. //字符串转16位无符号整数数组
  8. u16 = new Uint16Array(ss.split('').map(function(x){return x.charCodeAt(0);}));
  9. console.log(u16)
  10. //16位无符号整数数组转为8位无符号整数数组
  11. u8 = new Uint8Array(u16.buffer, u16.byteOffset, u16.byteLength);
  12. console.log(u8)
  13. //对8位无符号整数数组sm4加密
  14. s8 = sm4.encrypt(u8,key)
  15. console.log(s8)
  16. //对8位无符号整数数组sm4解密
  17. d8 = sm4.decrypt(s8,key)
  18. console.log(d8)
  19. //将8位无符号整数数组转为16位无符号整数数组,或恢复原文

  20. tmp=new Uint8Array(d8)
  21. console.log(tmp)
  22. a_16 = new Uint16Array(tmp.buffer,0,tmp.length/2)

  23. console.log(a_16)
  24. return String.fromCharCode.apply(null,a_16).substr(0,len)
复制代码

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

DTCC2020中国数据库技术大会 限时8.5折

【架构革新 高效可控】2020年9月21日~23日第十一届中国数据库技术大会将在北京隆重召开。

大会设置2大主会场,20+技术专场,将邀请超百位行业专家,重点围绕数据架构、AI与大数据、传统企业数据库实践和国产开源数据库等内容展开分享和探讨,为广大数据领域从业人士提供一场年度盛会和交流平台。

http://dtcc.it168.com


大会官网>>
TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 
京ICP备09055130号-4  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表