前端加密的常见几种方式

1,025 阅读6分钟

前端加密的分类

  • md5 基于 单向加密算法
  • AES 基于 对称加密算法
  • RSA 基于 非对称加密算法
  • DSA
  • ......

md5

基本概念

单向加密,人如其名,就是只能单向对明文进行加密,而不能逆向通过密文得到明文。该算法在加密过程中,在得到明文后,经过加密算法得到密文,不需要使用密钥。因为没有密钥,所以就无法通过密文得到明文。

MD5,全称Message Digest Algorithm 5,翻译过来就是消息摘要算法第5版,是计算机安全领域广泛使用的一种散列函数,用于确保信息传输的完整性。MD5算法是由MD2、MD3、MD4演变而来,是一种单向加密算法一种不可逆的加密方式

特点
  1. 长度固定

无论多长的数据,经过MD5加密后其MD5值长度都是固定的。MD5值长度固定为128位,而最后的值一般都用16进制数字表示,一个16进制数字占4位,所以最后的MD5值都是用32个16进制数字表示。

  1. 计算简单

MD5算法说到底还是散列算法,或者叫做哈希算法,所以计算一个数据的MD5值是比较容易的,同时加密速度也是很快的。

  1. 抗修改性

对原数据进行任何改动,哪怕只是修改1个字节,所得到的MD5值都有很大的区别。

  1. 强抗碰撞性

已知原数据和其MD5值,很难找到具有相同MD5值的数据,即很难伪造数据。

安全性

MD5加密本身来讲这个过程是不可逆的, 一般通过撞库破解,首先建立一个大型的数据库,然后把最常见的,有可能出现的密码,通过MD5加密成密文,并且以这些MD5值为主键加索引,将常见的密码为单列存入数据库中,并通过不断的积累,形成一个巨大的密码MD5数据库,这样当你截取到网络上密码的MD5值时,通过查询这个巨大的数据库来直接匹配MD5值,这就是所谓的撞库,

撞库破解的概率是很低的

加盐算法,会使得破解更加困难

使用
index.html 
倒入md5 即可
<script src="./resources/UtilMd5.js"></script>
​
// 或者使用cdn
<script src="https://cdn.bootcdn.net/ajax/libs/blueimp-md5/2.18.0/js/md5.js"></script><script src="https://cdn.bootcdn.net/ajax/libs/blueimp-md5/2.18.0/js/md5.min.js"></script>

使用实例

普通加密
md5(pwd)
加盐加密
//盐值
var salt = "";
md5(pwd + salt);

AES

基本概念

对称加密,美国国家标准技术研究所在2001年发布了高级加密标准(AES)。 AES是基于数据块的加密方式, 即,每次处理的数据是一块(16字节),当数据不是16字节的倍数时填充, 这就是所谓的分组密码(区别于基于比特位的流密码),16字节是分组长度。

特点
  • 安全性(Security) 算法足够强,抗攻击
  • 经济性(Efficiency) 算法运算效率高
  • 密钥捷变(Key Agility) 更改密钥所引入的损失尽量小,即最小消耗的密钥扩展算法
  • 适应性 (Versatility) 适用于不同的CPU架构,软件或硬件平台的实现
  • 设计简单(Simplicity) 轮函数的设计精简,只是多轮迭代
安全性

注意到AES有很多不同的算法,如aes192,aes-128-ecb,aes-256-cbc等,AES除了密钥外还可以指定IV(Initial Vector),不同的系统只要IV不同,用相同的密钥加密相同的数据得到的加密结果也是不同的。加密结果通常有两种表示方法:hex和base64,这些功能Nodejs全部都支持,但是在应用中要注意,如果加解密双方一方用Nodejs,另一方用Java、PHP等其它语言,需要仔细测试。如果无法正确解密,要确认双方是否遵循同样的AES算法,字符串密钥和IV是否相同,加密后的数据是否统一为hex或base64格式。

使用示例
新建crypto.js文件,构建crypto类
import CryptoJS from 'crypto-js';
​
class CryptoFile {
  constructor () {
    // 秘钥
    this.key = CryptoJS.enc.Utf8.parse('CRYPTOJSKEY00000'); // 16位
    this.iv = CryptoJS.enc.Utf8.parse('CRYPTOJSKEY00000');
  }
  // 加密
  encrypt(word) {
    let words = CryptoJS.enc.Utf8.parse(word);
    let encrypted = CryptoJS.AES.encrypt(words, this.key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 });
    return encrypted.toString();
  }
  
  // 解密
  decrypt(word) {
    let decrypt = CryptoJS.AES.decrypt(word, this.key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 });
    let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
    return decryptedStr.toString();
  }
}
export default new CryptoFile()
​
前端使用
import crypto from './crypto';
let data = '你加密的数据'
let encryptData = crypto.encrypt(JSON.stringify(data)); // 加密后的数据
let decryptData = crypto.decrypt(encryptData) // 解密后的数据
​
前端使用
import CryptoJS from 'crypto-js';
let data = '你加密的数据'
​
// 加密函数
function aesMinEncrypt(word){
  let _word = CryptoJS.enc.Utf8.parse(word);
  let _key = CryptoJS.enc.Utf8.parse("CRYPTOJSKEY00000"),// 16位
  let _iv = CryptoJS.enc.Utf8.parse("CRYPTOJSKEY00000");
 // _key 是密钥 ,_iv 是密钥偏移量 
 // 一般由后端返回,或者写死
  var encrypted = CryptoJS.AES.encrypt(_word, _key, {
            iv: _iv,
            mode: CryptoJS.mode.ECB, 
            padding: CryptoJS.pad.Pkcs7
    });
      return encrypted.toString();
}
// mode:     采用的加密算法,有aes192,aes-128-ecb,aes-256-cbc等
// padding : 数据填充 数据采用 PKCS#7 填充 , AES是基于数据块的加密方式,每次处理的数据是一块(16字节),当数据不是16字节的倍数时填充 因此这里的 key 需要为16位!
​
​
let encryptData = aesMinEncrypt(data); // 加密后的数据
​
// 解密函数
function aesMinDecrypt(word){
  let _word = CryptoJS.enc.Utf8.parse(word);
  let _key = CryptoJS.enc.Utf8.parse("CRYPTOJSKEY00000"),// 16位
  let _iv = CryptoJS.enc.Utf8.parse("CRYPTOJSKEY00000");
  var decryptedStr = CryptoJS.AES.decrypt(_word, _key, {
            iv: _iv,
            mode: CryptoJS.mode.ECB, 
            padding: CryptoJS.pad.Pkcs7
    });
      return decryptedStr.toString();
}
let decryptData = aesMinDecrypt(data) // 解密后的数据

RSA

基本概念

对称加密就是加密和解密使用同一个密钥。对称加密快而且方便,但是有个缺点,密钥容易被偷或被破解。非对称算法把密钥分成两个,一个自己持有叫私钥,另一个发给对方,还可以公开,叫公钥,用公钥加密的数据只能用私钥解开。

对称加密.png

特点

素数 又称质数,指在一个大于1的自然数中,除了1和此整数自身外,不能被其他自然数整除的数。

互质 又称互素。若N个整数的最大公因子是1,则称这N个整数互质。

模运算 即求余运算。“模”是“Mod”的音译。和模运算紧密相关的一个概念是“同余”。数学上,当两个整数除以同一个正整数,若得相同余数,则二整数同余。

欧拉函数 计算小于或等于n的正整数中与n互质的数的数目,以φ(n)表示。

安全性

RSA作为非对称加密技术的代表,加解密的速度其实相当慢只能对小块的数据进行加解密。但是其非对称的特点,满足公钥可以随处分发,只有公钥能解密私钥加密的数据,只有私钥能解密公钥加密的数据。所以很适合用来进行密钥分发和身份验证,这两个应用场景刚好相反。

使用示例
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>使用jsencrypt执行OpenSSL的RSA加密,解密</title>
</head>
<!--引入jsencrypt.js-->
<script src="https://cdn.bootcss.com/jsencrypt/3.0.0-beta.1/jsencrypt.js"></script>
</html>
function rsaMinEncrypt(word) {
  // 公钥
  const PUBLIC_KEY = `MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1qA+W/3WXYfOvzyoQyhgxIO+jscUrU8B
qMw0m5S1AkRu4Hocb8BOjlqsxgZwV4JTW6oZuBNbKaYaihcPpqX5NvaIQaFibIhDQAEV9+voUF2b
Zoo1yhloJ7SzYz4yw0ftZLhvoo4mmffK0Irj33q4TPAo3+8rGGjQW0dUFGAggX3sOeRMxsL4x6Vx
Ajfj9t+3en8mr02d5JLsC4XRfIgmkO6+JA7PsFJcqm4UVlQTNEoXgbuWwMyYkjZzNTx7MdJ4nTd0
ytP15n9A6Z81MN0o5IhoYhiUEUwQXkLWjVuveP7oJZqO+FIyxzHorRpaEkOosH2j3j53bPoLv9GZ
Dvbn/wIDAQAB`;
  const encrypt = new JSEncrypt();
  // encrypt.setPrivateKey('-----BEGIN RSA PRIVATE KEY-----'+PRIVATE_KEY+'-----END RSA PRIVATE KEY-----');
  encrypt.setPublicKey(`-----BEGIN PUBLIC KEY-----${PUBLIC_KEY}-----END PUBLIC KEY-----`);
  // var str = {
  // "uid":"1223334",
  // "pwd":"asd"
  // }
  const encrypted = encrypt.encrypt(word);
  //console.log('加密前数据:%o', word);
  //console.log('加密后数据:%o', encrypted);
  return encrypted;
}
let data = '你加密的数据'
rsaMinEncrypt(data)