您的位置:首页 > 理论基础 > 数据结构算法

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;


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  TodoList 加密