js 加密解密

MD5 (Message-Digest Algorithm) 信息摘要算法

  • 羅納德·李維斯特(Ron Rivest)開發(fā)出的一種被廣泛使用的密碼散列函數(shù),可以產(chǎn)生出一個(gè)128位(16字節(jié))的散列值(hash value)length為32的String,用于確保信息傳輸完整一致。
  • 該算法于1992年發(fā)布,但是在2004年,證實(shí)MD5算法無法防止碰撞(collision),因此不適用于安全性認(rèn)證,如SSL公開密鑰認(rèn)證或是數(shù)字簽名等用途。
  • js中的應(yīng)用
npm install md5
import md5 from 'md5'
md5(message) // message: String, Buffer, Array or Uint8Array

Hmac

  • Hmac算法也是一種哈希算法,它可以利用MD5或SHA1等哈希算法。不同的是,Hmac還需要一個(gè)密鑰
// node.js 的crypto模塊
const crypto = require('crypto');
const hmac = crypto.createHmac('sha256', 'secret-key');
hmac.update('Hello, world!');
hmac.update('Hello, nodejs!');
console.log(hmac.digest('hex')); // 80f7e22570...

Diffie-Hellman

// node的crypto模塊
DH算法是一種密鑰交換協(xié)議,它可以讓雙方在不泄漏密鑰的情況下協(xié)商出一個(gè)密鑰來。
示例見https://www.liaoxuefeng.com/wiki/1022910821149312/1023025778520640

RSA算法

  • RSA是1977年由羅納德·李維斯特(Ron Rivest)、阿迪·薩莫爾(Adi Shamir)和倫納德·阿德曼(Leonard Adleman)一起提出的。當(dāng)時(shí)他們?nèi)硕荚?a target="_blank">麻省理工學(xué)院工作。
  • 是一個(gè)典型的**非對(duì)稱加密**,公開密鑰體制,使用不同的加密密鑰與解密密鑰,加密密鑰(即公開密鑰)PK是公開信息,而解密密鑰(即秘密密鑰)SK是需要保密的,加密算法和解密算法也都是公開的。雖然解密密鑰SK是由公開密鑰PK決定的,但卻不能根據(jù)PK計(jì)算出SK。
  • 安全性:RSA允許你選擇公鑰的大小。512位的密鑰被視為不安全的;768位的密鑰不用擔(dān)心受到除了美國國家安全局(NSA)外的其他事物的危害;1024位的密鑰幾乎是安全的。
  • 通常是先生成一對(duì)RSA密鑰,其中之一是保密密鑰,由用戶保存;另一個(gè)為公開密鑰,可對(duì)外公開,信息采用改進(jìn)的DES或IDEA對(duì)話密鑰加密,然后使用RSA密鑰加密對(duì)話密鑰和信息摘要。對(duì)方收到信息后,用不同的密鑰解密并可核對(duì)信息摘要
  • 公鑰、私鑰有何特點(diǎn)?
    公鑰加密的,私鑰可以解密;
    私鑰加密的,公鑰可以解密。
    但公鑰加密的,公鑰無法解密;
    私鑰加密的,私鑰也無法解密!
  • js 中應(yīng)用
以下網(wǎng)址可以生成pem標(biāo)準(zhǔn)格式的秘鑰字符串
`http://web.chacuo.net/netrsakeypair`
// 公鑰
let pk = `-----BEGIN PUBLIC KEY-----
          MIGfMA......Qm
          -----END PUBLIC KEY-----`
  // 私鑰
let sk = `-----BEGIN PRIVATE KEY-----
           MIICeA......gJeAgEAAoGBAP        
          -----END PRIVATE KEY-----`;
  // 原文
let msg = "好厲害";
// 使用jsencrypt
npm install jsencrypt
import JsEncrypt from 'jsencrypt'
// 獲取加密 jsencrypt 
const encryptBody = function(data) {
  let encode = new JsEncrypt();
  // 寫入公鑰
  encode.setPublicKey(pk);
  // 返回加密數(shù)據(jù)
  return encode.encrypt(data);
};

//解密
const decryptBody = function(data) {
  let decode = new JSEncrypt();
  // 寫入私鑰
  decode.setPrivateKey(sk)
  // 返回解密數(shù)據(jù)
  return decode.decrypt(data);
};
// request body msg
encryptBody(msg)
// response body msg
decryptBody(msg)
// 使用jsrsasign
npm install jsrsasign
import rs from 'jsrsasign'
// 加密
let prvKey = rs.KEYUTIL.getKey(pk);
let enc = rs.KJUR.crypto.Cipher.encrypt(msg, prvKey);
console.log(enc,rs.hextob64(enc));
// 解密
let prv = rs.KEYUTIL.getKey(sk);
// get enc from fava
let dec = rs.KJUR.crypto.Cipher.decrypt(enc, prv);
console.log("jsrsasign decrypt: " + dec);
// 簽名
    var key = rs.KEYUTIL.getKey(sk);
    let signature=new rs.KJUR.crypto.Signature({alg:"SHA1withRSA"});
    signature.init(key);
    signature.updateString(msg);
    let a = signature.sign();
    let sign = rs.hextob64(a);
    console.log(sign);
// 驗(yàn)簽
    let signatureVf = new 
    rs.KJUR.crypto.Signature({alg:"SHA1withRSA",prvkeypem:pk});
    signatureVf.updateString(msg);
    // get sign from java
    let boolean = signatureVf.verify(rs.b64tohex(sign));
    console.log("jsrsasign verify: "+boolean);

AES (Advanced Encryption Standard)高級(jí)加密標(biāo)準(zhǔn)

  • 2001年發(fā)布,是**對(duì)稱密鑰加密**體系
  • 這個(gè)標(biāo)準(zhǔn)用來替代原先的DES(Data Encryption Standard)
  • JS中的應(yīng)用
import CryptoJS from 'crypto-js'
// 加密
export const encrypt = (word, keyStr) => {
  keyStr = keyStr || '16進(jìn)制的字符串'
  var key = CryptoJS.enc.Utf8.parse(keyStr)
  var srcs = CryptoJS.enc.Utf8.parse(word)
  var iv = CryptoJS.enc.Utf8.parse('ABCDEF1234123412');
  var encrypted = CryptoJS.AES.encrypt(srcs, key, {
    iv: iv,
    mode: CryptoJS.mode.ECB,
    padding: CryptoJS.pad.Pkcs7
  })
  return encrypted.toString()
}
// 解密
export const decrypt = (word, keyStr) => {
  keyStr = keyStr || '16進(jìn)制的字符串'
  // 如果后端給的是WordBuffer類型的數(shù)據(jù),將Utf8換成hex
  // 如果后端進(jìn)行base64編碼
  // CryptoJS.enc.Base64.stringify(encryptedHexStr);
  var key = CryptoJS.enc.Utf8.parse(keyStr)
  var iv = CryptoJS.enc.Utf8.parse('ABCDEF1234123412');
  var decrypt = CryptoJS.AES.decrypt(word, key, {
    iv: iv,
    mode: CryptoJS.mode.ECB,
    padding: CryptoJS.pad.Pkcs7
  })
  return CryptoJS.enc.Utf8.stringify(decrypt).toString()
}

DES (Data Encryption Standard)即數(shù)據(jù)加密標(biāo)準(zhǔn)

import CryptoJS from 'crypto-js'
//DES加密
function encryptByDES(message, key){
    var keyHex = CryptoJS.enc.Utf8.parse(key);
    var encrypted = CryptoJS.DES.encrypt(message, keyHex, {
        mode: CryptoJS.mode.ECB,
        padding: CryptoJS.pad.Pkcs7
    });
    return encrypted.ciphertext.toString();
}
//DES解密
function decryptByDES(ciphertext, key){
    var keyHex = CryptoJS.enc.Utf8.parse(key);
    var decrypted = CryptoJS.DES.decrypt({
        ciphertext: CryptoJS.enc.Hex.parse(ciphertext)
    }, keyHex, {
        mode: CryptoJS.mode.ECB,
        padding: CryptoJS.pad.Pkcs7
    });
    var result_value = decrypted.toString(CryptoJS.enc.Utf8);
    return result_value;
}

3DES (Triple Data Encryption Algorithm)三重?cái)?shù)據(jù)加密算法

  • 也叫Triple DES,1981年發(fā)布,是DES向AES過渡的加密算法
  • 由于計(jì)算機(jī)運(yùn)算能力的增強(qiáng),DES密碼的密鑰長度變得容易被暴力破解,3DES就是通過增加DES的密鑰長度來避免類似的攻擊
  • js中的應(yīng)用
import CryptoJS from 'crypto-js'
//秘鑰key
var key = "12345677654321";
//key不足24位自動(dòng)以0(最小位數(shù)是0)補(bǔ)齊,如果多余24位,則截取前24位,后面多余則舍棄掉
var base64 = CryptoJS.enc.Utf8.parse(key)
//加密使用的是3DES中的ECB,解密對(duì)應(yīng)的使用ECB
function encrypt() {
  var text = document.getElementById("content").innerText;
  var encrypt = CryptoJS.TripleDES.encrypt(text, base64, {
    iv: CryptoJS.enc.Utf8.parse('01234567'),//iv偏移量
    // mode: CryptoJS.mode.CBC,  //CBC模式
    mode: CryptoJS.mode.ECB,  //ECB模式
    padding: CryptoJS.pad.Pkcs7//padding處理
  });
  return encrypt.toString()
}
//解密
function decrypt() {
  var text = document.getElementById("encrypt").innerText;
  var decrypt = CryptoJS.TripleDES.decrypt(text, base64, {
    iv: CryptoJS.enc.Utf8.parse('01234567'),
    // mode: CryptoJS.mode.CBC,
    mode: CryptoJS.mode.ECB,
    padding: CryptoJS.pad.Pkcs7
  });
  return decrypt.toString(CryptoJS.enc.Utf8)
}

SHA-2/3安全散列算法2/3

SHA-1不夠安全,不能繼續(xù)使用,是SHA-1的后繼者

國密SM2/4

數(shù)字簽名過程

其實(shí)就是瀏覽器的網(wǎng)頁與服務(wù)器之間的認(rèn)證過程
其中使用了rsa加密算法
a、b都有公鑰,z有私鑰,az為朋友,b為詐騙中間人

  1. a給z發(fā)一封信件,a使用公鑰加密后發(fā)給z,z使用私鑰解密
    z給a回信,決定使用數(shù)字簽名
  2. z寫完回信后先用Hash函數(shù),生成信件的摘要(digest),然后,使用私鑰,對(duì)這個(gè)摘要加密,生成"數(shù)字簽名"(signature),然后將回信和簽名發(fā)送給a
  3. a收信后,取下數(shù)字簽名,用z的公鑰解密,得到信件的摘要。由此證明,這封信確實(shí)是z發(fā)出的。
  4. a再對(duì)信件本身使用Hash函數(shù),將得到的摘要結(jié)果,與上一步得到的摘要進(jìn)行對(duì)比。如果兩者一致,就證明這封信未被修改過。
  5. 復(fù)雜情況來了,b用a的電腦時(shí)將a的公鑰換成了b的公鑰,a和b就可以如上述流程就行通信了,b以此來冒充z,與a進(jìn)行通信
  6. 后來,a感覺不對(duì)勁,發(fā)現(xiàn)自己無法確定公鑰是否真的屬于z。她想到了一個(gè)辦法,要求z去找"證書中心"(certificate authority,簡稱CA),為公鑰做認(rèn)證。證書中心用自己的私鑰,對(duì)z的公鑰和一些相關(guān)信息一起加密,生成"數(shù)字證書"(Digital Certificate)。
  7. z拿到數(shù)字證書以后,就可以放心了。以后再給a寫信,只要在簽名的同時(shí),再附上數(shù)字證書就行了。
  8. a收信后,用CA的公鑰(瀏覽器中預(yù)置了ca)解開數(shù)字證書,就可以拿到z真實(shí)的公鑰了,然后就能證明"數(shù)字簽名"是否真的是z簽的
    此過程參考https://www.ruanyifeng.com/blog/2011/08/what_is_a_digital_signature.html
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容