珠宝首饰商城网站建设,html5网站开发趋势,腾讯营销平台,怎样注册一个自己的平台本文主要详细介绍了在前端开发中常用的加/解密算法#xff0c;以及前端如何实现。
总的来说#xff1a;前端加密无论使用哪个加密都一样是有可能性被他人获取到相关的公钥或密钥的#xff08;比如#xff1a;拦截请求、查看源代码等#xff09;#xff0c;然后进行加密与…本文主要详细介绍了在前端开发中常用的加/解密算法以及前端如何实现。
总的来说前端加密无论使用哪个加密都一样是有可能性被他人获取到相关的公钥或密钥的比如拦截请求、查看源代码等然后进行加密与后端通讯所以前端加密所谓的安全性是有限的最主要的还是在后端
一、加密算法
1、对称加密
含义 加密和解密使用的是相同的秘钥加密快而且方便但缺点是密钥容易被偷或被破解。
常见算法 AES、DES、3DES 、RC2、RC4、RC5、RC6 、 Blowfish、国密SM4。
常见应用场景
适用于需要高速加密/解密的场景如HTTP 传输的 SSL/TLS 部分。适用于加密大量数据如文件加密、网络通信加密、数据加密、电子邮件、Web 聊天等。
2、非对称加密
含义 加密和解密用的不是同一个秘钥一般是用公钥加密用私钥解密公钥和私钥成对存在公钥从私钥中提取产生公开给所有人。安全性要好于对称加密的但性能就比较差。
常见算法 RSA、DSA、Elgamal、DSS、Merkle-Hellman背包算法、D-H、ECC椭圆曲线加密算法、国家商用密码SM2算法。
常见应用场景
在实际应用中非对称加密通常用于需要确保数据完整性和安全性的场合如数字证书的颁发、SSL/TLS 协议的加密、数字签名、加密小文件、密钥交换、实现安全的远程通信等。
3、单向散列函数
含义 又称为消息摘要算法是不可逆的加密算法即对明文进行加密后无法通过得到的密文还原回去得到明文。
常见的单项散列函数 MD5、SHA1、SHA256、SHA512 以及它们之前加上 HmacKeyed-hash message authentication codes 后的 HmacMD5、HmacSHA1 等。
二、经典的加密算法
1、对称加密算法 —— AESAdvanced Encryption Standard
英文全称为 Advanced Encryption Standard即高级加密标准的意思。
AES的推出用于取代已经被证明不安全的 DES 算法。
AES 属于分组加密算法因为它会把传入的明文数据以 128 bit 为一组分别处理。
其秘钥长度则可以是 128、192 和 256 bit。
AES 或者说对称加密算法的优点是速度快缺点就是不安全因为网站上的代码和秘钥都是明文别人只要得到了加密结果再结合秘钥就能得到加密的数据了。
AES与DES
DES 优点DES算法具有极高安全性到目前为止除了用穷举搜索法对DES算法进行攻击外还没有发现更有效的办法。 缺点分组比较短、密钥太短、密码生命周期短、运算速度较慢。
AES 优点运算速度快对内存的需求非常低适合于受限环境。分组长度和密钥长度设计灵活 AES标准支持可变分组长度具有很好的抵抗差分密码分析及线性密码分析的能力。 缺点目前尚未存在对AES 算法完整版的成功攻击但已经提出对其简化算法的攻击。
AES与DES之间的主要区别 在于加密过程在DES中将明文分为两半然后再进行进一步处理而在AES中整个块不进行除法整个块一起处理以生成密文。 相对而言AES比DES快得多与DES相比AES能够在几秒钟内加密大型文件。
2、非对称加密—— RSA算法
RSA加密算法是一种非对称加密算法使用一对密钥分别是公钥和私钥这个公钥和私钥其实就是一组数字其二进制位长度可以是1024位或者2048位长度越长其加密强度越大。
目前为止公之于众的能破解的最大长度为795位密钥只要高于795位相对就比较安全所以目前为止这种加密算法一直被广泛使用。
由于RSA算法的原理都是大数计算使得RSA最快的情况也比对称加密算法慢上好几倍。
RSA的速度是对应同样安全级别的对称加密算法的1/1000左右。
常见场景 速度一直是RSA的缺陷一般来说RSA只用于小数据的加密比如对称加密算法的密钥又或者数字签名。例如在用户注册或登录的时候用公钥对密码进行加密再去传给后台后台用私钥对加密的内容进行解密然后进行密码校验或者保存到数据库。
3、单向散列函数 —— MD5Message Digest Algorithm 5
MD5 长度固定不论输入的内容有多少字节最终输出结果都为 128 bit即 16 字节。
这就是为什么 MD5 以及其它单向散列函数是不可逆的 —— 输出定长代表会有数据丢失。
通常我们可以用 16 进制字面值来表示它每 4 bit 以 16 进制字面值显示得到的是一个长度为 32 位的字符串。
注意MD5 等单向散列函数具有高度的离散性即只要输入的明文不一样得到的结果就完全不一样哪怕是仅仅多了一个空格。
使用场景
可以用来做密码的保护。比如可以不直接存储用户的密码而是存储密码的 MD5 结果。但是现在一般认为用 MD5 来做加密是不太安全的更多是利用 MD5 的高度离散性特点用它来做数字签名、完整性校验云盘秒传等数字签名。我们可以在发布程序时同时发布其 MD5这样别人下载程序后自己计算一遍 MD5一对比就知道程序是否被篡改过比如植入了木马。完整性校验。比如前端向后端传输一段非常大的数据为了防止网络传输过程中丢失数据可以在前端生成一段数据的 MD5 一同传给后端这样后端接收完数据后再计算一次 MD5就知道数据是否完整了。
MD5和SHA MD5 是RSA数据安全公司开发的一种单向散列算法非可逆相同的明文产生相同的密文。 SHASecure Hash Algorithm 可以对任意长度的数据运算生成一个固定位数的数值。 SHA/MD5对比SHA在安全性方面优于MD5并且可以选择多种不同的密钥长度。 但是由于内存需求更高运行速度可能会更慢。 不过MD5因其速度而得到广泛使用但是由于存在碰撞攻击风险因此不再推荐使用。
三、前端常用的加/解方式
前端常用的方式有crypto-js、encryptlong、jsencrypt、bcrypt
1、crypto-js
crypto-js支持多种算法MD5、SHA1、SHA2、SHA3、RIPEMD-160 的哈希散列以及进行 AES、DES、Rabbit、RC4、Triple DES 加解密。
crypto-js 对象如下
1常用加密方法
加密函数的参数(明文字符串, 密钥字符串可选参数对象)返回密文字符串。加密函数Cryptojs.AES.encryptCryptojs.DES.encryptCryptojs.Rabbit.encryptCryptojs.RC4.encryptCryptojs.TripleDES.encrypt
2常用解密方法
解密函数的参数(密文字符串, 密钥字符串可选参数对象)返回的结果必须用.toString(CryptoJS.enc.Utf8)转为明文。解密函数是CryptoJS.AES.decryptCryptoJS.DES.decryptCryptoJS.Rabbit.decryptCryptoJS.RC4.decryptCryptoJS.TripleDES.decrypt
3可选参数对象常用属性
mode加密模式 ECB (Electronic Codebook)将整个明文分成块每个块独立加密。可能存在安全性问题。 CBC (Cipher Block Chaining)前一个块的密文作为下一个块的加密向量提高了安全性。 CFB (Cipher Feedback)前一个密文块作为密钥加密当前明文块可按比块更小单位加密。 OFB (Output Feedback)使用函数产生的密钥流进行异或运算提供加密流。 CTR (Counter)使用计数器的值加密并与明文进行异或运算提供加密效果。 CTRGladmanCTRGladman 模式paddig填充方式 AnsiX923在数据末尾填充零字节最后一个字节表示需要填充的字节数。 Iso10126在数据末尾填充随机字节最后一个字节表示需要填充的字节数。 Iso97971使用 ISO/IEC 9797-1 填充方案在数据末尾填充 \x80 加上零或多个 \x00 直到块的大小。 NoPadding不进行任何填充要求数据长度必须是块大小的整数倍。 Pkcs7使用 PKCS#7填充方案在数据末尾填充字节字节的值表示需要填充的字节数。 ZeroPadding在数据末尾填充零字节直到数据长度满足块大小的整数倍。vi 偏移向量formatter自定义格式enc 指定字符编码模式包含8 个 API“Hex”, “Latin1”, “Utf8”, “Utf16BE”, “Utf16”, “Utf16LE”, “Base64”, “Base64url”algo包含很多算法 哈希算法 MD5 常用生成 128 位哈希值用于校验数据完整性 SHA1 常用系列生成 160 位哈希值 SHA256生成 256 位哈希值 SHA224生成 224 位哈希值 SHA512生成 512 位哈希值 SHA384生成 384 位哈希值 SHA3SHA-3 哈希算法 RIPEMD160另一种生成 160 位哈希值的算法 HMAC基于密钥的哈希消息认证码 PBKDF2密码基于密钥派生函数 EvpKDF另一种密钥派生函数对称加密算法 AES 常用高级加密标准用于对称加密和解密数据 DES 数据加密标准较早的对称加密算法 TripleDES 对 DES 进行多次加密以增加安全性流式加密算法 RC4 流式加密算法 RC4DropRC4 的变种 Rabbit 另一种流式加密算法 RabbitLegacyRabbit 算法的旧版本其他 Blowfish对称加密算法用于加密和解密数据
2、jsencrypt
jsencrypt是一个基于rsa加解密的js库。
new jsencrypt() 如下 jsencrypt 的加解密过程需要用到 OpenSSL 来生成秘钥OpenSSL 是一个开源的软件它是对 SSL 协议的实现。
RSA秘钥生成方式
a. 利用工具在线网站http://tools.jb51.net/password/rsa_encodeb. Mac系统内置OpenSSL开源加密库所以可以直接在终端上使用命令。
命令含义genrsa生成并输入一个RSA私钥rsautl使用RSA密钥进行加密、解密、签名和验证等运算rsa处理RSA密钥的格式转换等问题
具体操作
openssl genrsa -out private.pem 1024 // 生成私钥密钥长度为1024bit
openssl rsa -in private.pem -pubout -out public.pem // 从私钥中提取公钥同时会生成了private.pem 和 public.pem两个文件
cat private.pem // 查看私钥
cat public.pem // 查看公钥jsencrypt使用注意点
jsencrypt加密的对象一定要是字符串jsencrypt加密长对象或者数据太多可能会返回false 或者报错Message too long for RSA。
可能导致问题的原因
openssl生成的密匙可能会有格式问题需要转化一下格式PKCS#1和PKCS#8jsencrypt的加密长度有限制它只能支持100多位的加密当字符串太长会返回false
解决办法用encryptlong
3、encryptlong
encryptlong是基于 jsencrypt 扩展了长文本分段加解密功能即需要进行rsa加密的内容比较长时就用encryptlong进行实现。
new encryptlong() 如下 4、bcryptjs
bcrypt是一种用于密码哈希的加密算法它是基于Blowfish算法的加强版生成的密文为60位。
bcrypt是一种加盐的单向Hash不可逆的加密算法同一种明文每次加密后的密文都不一样而且不可反向破解生成明文破解难度很大。
bcryptjs对象如下 应用场景
用户注册当用户注册时需要将其密码进行哈希处理后再存储到数据库中。用户登录当用户登录时需要将其输入的密码与存储在数据库中的哈希值进行比较从而得知密码是否正确。密码重置当用户忘记密码时可以使用Bcrypt算法生成一个新的哈希值用于重置密码。
bcrypt原理
bcrypt算法是一种密码哈希函数它采用了salt和cost两种机制来增强密码的安全性。
salt为了防止彩虹表攻击bcrypt算法会生成一个随机salt值将salt与密码拼接后再进行哈希运算。这个salt值是由22个可打印字符组成的字符串它的作用是使得相同密码的哈希值在不同的salt值下产生不同的结果从而增加密码破解的难度。costbcrypt算法会将明文密码和salt进行多次迭代的哈希运算。迭代的次数是由cost值决定的cost值越大运算次数越多从而增加密码破解的难度。通常来说建议将cost值设置为12这样可以保证安全性和性能的平衡。
bcrypt加密后值说明
bcrypt 密码强度一般在10-12。默认是10太强会导致速度变慢。
加密得到的字符串的格式$2a $[cost] $[22 character salt] [31 character hash]
cost 是代价因子这里的10 表示是2的10次方也就是1024轮22 character salt16个字节128bits的salt经过base64编码得到的22长度的字符31 character hash24个字节192bits的hash经过bash64的编码得到的31长度的字符
如
四、具体实现示例
通过npm安装 npm install crypto-js encryptlong jsencrypt bcrypt
1、crypto-js实现RSA加/解密
import CryptoJS from crypto-js;const encryptByRSA (content, publicKey) {const rsa new JSEncrypt();rsa.setPublicKey(publicKey);return rsa.encrypt(content);
};const decryptFromRSA (content, privateKey) {const rsa new JSEncrypt();rsa.setPrivateKey(privateKey);return rsa.decrypt(content);
};2、crypto-js实现AES加/解密
import CryptoJS from crypto-js;const encryptByAES (content, key, iv) {try {if (typeof content object) {content JSON.stringify(content);}const data CryptoJS.enc.Utf8.parse(data);const aes CryptoJS.AES.encrypt(data, key, {mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.Pkcs7,iv: CryptoJS.enc.Utf8.parse(iv)});return aes.ciphertext.toString();} catch (e) {return content;}
};const decryptFromAES (content, key, iv) {try {const encryptedHexStr CryptoJS.enc.Hex.parse(content);const data CryptoJS.enc.Base64.stringify(encryptedHexStr);const aes CryptoJS.AES.decrypt(data, key, {mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.Pkcs7,iv: CryptoJS.enc.Utf8.parse(iv)});const originalText aes.toString(CryptoJS.enc.Utf8);return originalText.toString();} catch (e) {return content;}
};3、jsencrypt进行RSA加/解密
import JSEncrypt from jsencrypt;// 注如果是对象/数组的话需要先JSON.stringify转换成字符串
const encryptByRSA (content, publicKey) {const rsa new JSEncrypt();rsa.setPublicKey(publicKey);return rsa.encrypt(content);
};const decryptFromRSA (content, privateKey) {const rsa new JSEncrypt();rsa.setPrivateKey(privateKey);return rsa.decrypt(content);
};4、encryptlong进行RSA加/解密
import JSEncryptLong from encryptlong;// 注如果是对象/数组的话需要先JSON.stringify转换成字符串
const encryptLongByRSA (content, publicKey) {const rsa new JSEncryptLong();rsa.setPublicKey(publicKey);return rsa.encryptLong(content);
};const decryptLongFromRSA (content, privateKey) {const rsa new JSEncryptLong();rsa.setPrivateKey(privateKey);return rsa.decryptLong(content);
};测试示例
const PUBLIC_KEY MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKX1Fs2JUD25zrAEwPnjnZC0azrl1XjGzGrJ64eb1lr9QVVOO2zGKZdqDLZD4Ut4Mp6GHMaqqFXKmzN7IAXumqZbUrqUziHE5YGC02wObiZEzfa6V9a8ZvqpBZ8KOhAkkjzjMlEhDORpZmez3SMzetn7mcCeLw8/vmxz3QIDAQAB;const PRIVATE_KEY MIICXgIBAAKBgQDKX1Fs2JUD25zrAEwPnjnZC0azrl1XjGzGrJ64eb1lr9QVVOO2zGKZdqDLZD4Ut4Mp6GHMaqqFXKmzN7IAXumqZbUrqUziHE5YGC02wObiZEzfa6V9a8ZvqpBZ8KOhAkkjzjMlEhDORpZmez3SMzetn7mcCeLw8/vmxz3QIDAQABAoGBAJBr6b4V6nJwXdHPyngy4PGl/HTqcK60BkTamALqzmEtU9tNU5z2yz7dy6awTsjo7Vao8CwNrUp5fHGXw65EEc1/3Iu2Fiix0XF7RP4NFSoxbBmzQW1nUK/5DFi4VR1uhEmdbgLwGabsdqzeUqhRKkRGAPVCotBjaDBOu0J3Mu5AkEASM7Ctu7evOvZwjWrp9a5MGxJ9yLLabbIuWL420jr2G6ojaTZ2ROA2DWWQPx4JqWxDHttomrb38dk2emP2WAwJBAM/yU58YRQdTeuTzNYC1JdWcs35n9hoVP7yx29CmcqDTPp3nRBbbq88yMb2nZdlwthWi7BurNHsRJFqj0GJ8CQF5gJCuW1UxcJ2PGi1yW7R2e6fcJqoden8B2aDKgmXdBAGyz7s5cE/jB1bH1H60aECPzFVSFCwXh5FMEUEHwPfUCQQC7JqZ57lbhebrSRcA58GwzFFvY40wu8gIHWvwqgti2xsZgWWqZCPXf9gSBWaUhmJPDa0fGAxesGN7VyhswNuTAkEAzCFNqL/zwHXcwh9YyHTdk/bRWIJq49jTAvbgGv0szKIvGRKoRbub3NEUiI80TDsCAvbJ6R80J7RjnpmShOwcA;const constent {phone: 8000000001,firstName: vickie,id: 1234XXXX4567,data: {timestamp: 1572321851823,inter1: [123123123, 123123123, 123123123, 123123123, 123123123],inter2: [123123123, 123123123, 123123123, 123123123, 123123123],inter3: [123123123, 123123123, 123123123, 123123123, 123123123],inter4: [123123123, 123123123, 123123123, 123123123, 123123123],inter5: [123123123, 123123123, 123123123, 123123123, 123123123],inter6: [123123123, 123123123, 123123123, 123123123, 123123123],stream: {},caton: {},card: []}
};
const encryptResult encryptLongByRSA(JSON.stringify(constent), PUBLIC_KEY);
const decryptResult decryptLongFromRSA(encryptResult, PRIVATE_KEY);5、bcrypt进行哈希加密
import bcrypt from bcryptjs;// 同步实现hash加密每一次生成的hash都会不一样, cost数字越大哈希值就越安全,但性能会差一点
const encryptHash (plaintextPassword, cost) {const salt bcrypt.genSaltSync(cost);const hash bcrypt.hashSync(plaintextPassword, salt);return hash;
};// 同步验证
const isPass (plaintextPassword, hash) {return bcrypt.compareSync(plaintextPassword, hash);
};// 测试
const passwordHash encryptHash(test, 10);
console.log(passwordHash, isPass(test, passwordHash)); // 生成的不可逆密文 true