GeekShare推出TodoList的本地加密代码
2019-10-02 17:06
2899 查看
下面的代码是GeekShare推出的TodoList的加密模块代码,采用AES加密,当然还有辅助的MD5加密和Base64编码,这些都是公开的加密算法和编码方式,直接利用已有的NPM包
1、核心加密算法,封装成js模块 encrypt.js
encode加密,传入要加密的文本text和加密密钥key
decode解密,传入密文和加密密钥key
import {Base64} from 'js-base64' var aesjs = require('aes-js'); var pbkdf2 = require('pbkdf2'); var md5 = require('md5'); var encrypt = { encode: function (text, key, salt='geekshare', base64Encode = true) { var blockLen = 16; key = pbkdf2.pbkdf2Sync(key, salt, 1, blockLen, 'sha512'); var iv = [] var ivString = '' for (var i = 0; i < blockLen; i++) { var temp = Math.floor(Math.random()*128) iv.push(temp); ivString += String.fromCharCode(temp); } var padLen = blockLen - aesjs.utils.utf8.toBytes(text).length % blockLen; text = text + (String.fromCharCode(padLen).repeat(padLen)); var textBytes = aesjs.utils.utf8.toBytes(text); var aesCbc = new aesjs.ModeOfOperation.cbc(key, iv); var encryptedBytes = aesCbc.encrypt(textBytes); var encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes); encryptedHex = ivString + encryptedHex; if (base64Encode) { encryptedHex = Base64.encode(encryptedHex); } return encryptedHex; }, decode: function (text, key, salt='geekshare', base64Encode = true) { var blockLen = 16; key = pbkdf2.pbkdf2Sync(key, salt, 1, blockLen, 'sha512'); if ( base64Encode ) { text = Base64.decode(text); } var ivString = text.substr(0, blockLen); var iv = []; for ( var i = 0; i < ivString.length; i++) { iv.push(ivString.charCodeAt(i)); } text = text.substr(blockLen); var encryptedBytes = aesjs.utils.hex.toBytes(text); var aesCbc = new aesjs.ModeOfOperation.cbc(key, iv); var decryptedBytes = aesCbc.decrypt(encryptedBytes); var decryptedText = aesjs.utils.utf8.fromBytes(decryptedBytes); var padLen = decryptedText.charCodeAt( decryptedText.length - 1); decryptedText = decryptedText.substr(0, decryptedText.length - padLen); return decryptedText }, md5: function (text) { return md5(text); } } export default encrypt;
2、业务调用接口,todolist.js
encodeText接口,传入要加密的文本和用户的seqToken,自动读取本地存储的密钥,密钥也是seqToken加密后的,需要先解密拿到密钥,然后再用密钥加密
decodeText接口,和加密流程类似,先解密密钥,再用密钥解密密文
考虑到同一设备可能登陆多个账号,因此针对数据存储的key用uid的hash前缀做区分,另外考虑到用户更新加密密码或者加密模式,客户端会并存多个加密密码,这个也按照密钥的hash指纹作为key来区分
import encrypt from './js/encrypt' var todolist = { todolistKey: 'todolistkey', todolistevent: 'todolistevent', setUid: function (uid) { let suffix = encrypt.md5(uid).substr(0, 6) this.todolistKey = suffix + 'todolistkey' this.todolistevent = suffix + 'todolistevent' }, getTodolistKey: function (keyName=null) { let data = localStorage.getItem(this.todolistKey) if (data) { data = JSON.parse(data) } if (!data) { data = {} } if (keyName) { return data ? data[keyName] : undefined } return data }, getLastTodolistKey: function () { let listKey = this.getTodolistKey() var lastKey = null for (lastKey in listKey) { } return lastKey }, addTodolistKey: function (password, passwordKey) { let data = this.getTodolistKey() data[passwordKey] = password localStorage.setItem(this.todolistKey, JSON.stringify(data)) return true; }, clearTodolistKey: function (lastKey) { // 清除其它key,只保留lastKey let data = this.getTodolistKey() let newData = {} for (let key in data) { if (key == lastKey) { newData[key] = data[key] } } localStorage.setItem(this.todolistKey, JSON.stringify(newData)) }, removeTodolistKey: function (key) { let data = this.getTodolistKey() if (data[key]) { delete data[key] localStorage.setItem(this.todolistKey, JSON.stringify(data)) } }, getTodolistEvent: function () { let data = localStorage.getItem(this.todolistevent); if (data) { data = JSON.parse(data) } return data }, addTodolistEvent: function (eventData) { if (eventData.fromType == eventData.toType == 'server') { return true } localStorage.setItem(this.todolistevent, JSON.stringify(eventData)) return true }, clearTodolistEvent: function () { localStorage.removeItem(this.todolistevent) }, isEncodeText: function (text) { return /^[a-z0-9]{32}\|/.test(text) }, decodeText: function (text, seqToken) { let key = text.substr(0, text.indexOf('|')) text = text.substr(text.indexOf('|') + 1) let realKey = this.getTodolistKey(key) if (realKey) { realKey = encrypt.decode(realKey, seqToken, seqToken) } if (!realKey) { console && console.warn('invalid local key and quit decode') return false } let md5 = false if (/\|[a-z0-9]{32}$/.test(text)) { md5 = text.substr(text.lastIndexOf('|') + 1) text = text.substr(0, text.lastIndexOf('|')) } let realText = encrypt.decode(text, realKey, seqToken) if (md5 !== false) { if (encrypt.md5(realText + realKey + seqToken) !== md5) { console && console.warn('decode text not match '+md5) return false } } return realText }, encodeText: function (text, key, seqToken) { var realKey = this.getTodolistKey(key) if (realKey) { realKey = encrypt.decode(realKey, seqToken, seqToken) } if (!realKey) { console && console.warn('invalid local key and quit encode') return false } let enText = encrypt.encode(text, realKey, seqToken) enText = `${key}|${enText}` let md5 = encrypt.md5(text + realKey + seqToken) return `${enText}|${md5}` } } export default todolist;
相关文章推荐
- 英美澳施压,要求 Facebook 停止端到端加密计划
- Mac 终端效率神技
- GeekShare推出本地加密的免费TodoList工具
- react用Redux中央仓库实现一个todolist
- React-redux实现小案例(todolist)的过程
- React+Redux实现简单的待办事项列表ToDoList
- 关于工作流引擎ccflow待办分类 研究与技术实现
- python文字和unicode/ascll相互转换函数及简单加密解密实现代码
- C#中RSA加密与解密的实例详解
- python暴力解压rar加密文件过程详解
- Flask框架实现的前端RSA加密与后端Python解密功能详解
- Laravel 数据库加密及数据库表前缀配置方法
- django fernet fields字段加密实践详解
- 使用VueCli3+TypeScript+Vuex一步步构建todoList的方法