密碼學術語以及nodejs實現

weixin_34337265發表於2018-02-16

基礎準備工作

const secret = 'Sunshine'
const salt = 'Treasure'
const plainText = '始終相信美好的事情即將發生'
const publicKey = `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7ikxFcifEdVZ7IxSvd65vUQKx
xvYZRx+qSz0Cl1Xj+PwyT9hnw4M6rglvbjgpQhQnnumY/KkmI7CCglXVNjOI9zRA
/IfSv3juPTEFItJUcnfOtgnzDgrzMvu9gP9nH45aD5mnZd+zWaK9BSJSuOk/D6rj
Lts8Iykv1jpQ/KYFPwIDAQAB
-----END PUBLIC KEY-----`
const privateKey = `-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQC7ikxFcifEdVZ7IxSvd65vUQKxxvYZRx+qSz0Cl1Xj+PwyT9hn
w4M6rglvbjgpQhQnnumY/KkmI7CCglXVNjOI9zRA/IfSv3juPTEFItJUcnfOtgnz
DgrzMvu9gP9nH45aD5mnZd+zWaK9BSJSuOk/D6rjLts8Iykv1jpQ/KYFPwIDAQAB
AoGAQdV0nNRL/X0rVKKl+krLIyyPA5VSguEizocG7cfuUM7wyUCaOSK7CHhbu5A3
itQ1ewsf+aKIRmk05zuVofka8ZkOxfdpMgNlP1nuYD6VQHbm6ssPiZP64EX1W64G
djNnOhZjP1dR/JhEMB8tWZDdQOhwHMiTCWGMZZYXtC7aUdECQQDz05OZM2eTZkeu
5srHLVDLWrNTn6yZCnD4PA7ltyuR2uF3K/dziWaCPT6J8dblOnBKJteU0fvMiDPx
iT8KyM7LAkEAxOdPHQ6+k9s/25tpmEXibJytJ8T1HsIxFAdvuHqurjMnb3yOg2F+
0s2fBnH42nvYnJmCA2TDv39G9EczHvKA3QJAAnaCqSuBwlVoJ/Yg2j408Ljr0s5s
GeenGHrS07Mz93c0i9Wf3ETpCivAM/iDaTFb7QPTbadpWbmOfMQcJOm+XQJAMKzh
wNQpRpHXqmkz5GG6RJFCuOcWlWD6EvJ3qsohLo0UvZmz/UR3vpL4MfawxwoAlU3Z
dw9M2KUVHEQRnh/ivQJAD+U1zCsmP6J3+gWZ/lzGE+8CrfxhjywSTtEAsC1GhAA8
BnaJUPhgGM9r9N52NWb/WuhT1PgLZSlW0OhBX1/xJg==
-----END RSA PRIVATE KEY-----`

對稱密碼

一種用相同的金鑰進行加密和解密的技術,用於確保訊息的機密性。在對稱密碼的演算法方面,目前主要使用的是 AES。經管對稱密碼能夠確保訊息的機密性,但需要解決將解密金鑰配送給接收者的金鑰配送問題

  test('對稱密碼', () => {
    //TODO 沒有通過測試,報錯 error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt 
    const cipher = crypto.createCipher('aes192', secret)
    cipher.update(Buffer.from(plainText))
    const cipherText = cipher.final()
    const deCipher = crypto.createDecipher('aes192', secret)
    deCipher.update(cipherText)
    const temp = deCipher.final()
    expect(temp).toBe(Buffer.from(plainText))
  })

公鑰密碼

一種用不同的金鑰進行加密和解密的技術,和對稱密碼一樣用於確保訊息的機密性。使用最廣泛的演算法是 RSA,除此之外還有 ElGamal 和 Robin 等演算法,以及與其相關的Diffie-Hellman 金鑰交換和橢圓曲線 Diffie-Hellman 金鑰交換等技術。和對稱密碼相比,公鑰密碼的速度非常之慢,因此一般都會和對稱密碼一起組成混合密碼系統來使用。公鑰密碼能夠解決對稱密碼中的金鑰交換問題,但存在通過中間人攻擊被偽裝的風險,因此需要對帶有數字簽名的公鑰進行認證

  test('公鑰密碼', () => {
    const publicText = crypto.publicEncrypt(publicKey, Buffer.from(plainText))
    const privateText = crypto.privateDecrypt(privateKey, publicText)
    expect(privateText.toString()).toBe(plainText)
  })

單向雜湊函式

一種將長訊息轉換為短雜湊值的技術,用於確保資訊的完整性。在單向雜湊函式的演算法方面,SHA-1 曾被廣泛使用,但由於人們已經發現了一些針對該演算法的理論上可行的攻擊方式,因此該演算法不再被用於新的用途。今後我們應該主要使用的演算法包括目前已經在廣泛使用的 SHA-2,以及具有全新結構的SHA-3演算法。單向雜湊函式可以單獨使用,也可以用作訊息認證碼、數字簽名以及偽隨機數生成器等技術的組成元素來使用

  test('單向雜湊函式', async () => {
    const hash = crypto.createHash('sha256')
    // 一般對公鑰進行雜湊
    hash.update(publicKey)
    const hex = hash.digest('hex')
    expect(hex).not.toBeNull()
  })

訊息認證碼

一種能夠識別通訊物件傳送的訊息是否被篡改的認證技術,用於驗證訊息的完整性,以及對訊息進行認證。訊息認證碼的演算法中,最常用的是利用單向雜湊函式的 HMAC。HMAC 的構成不依賴於某一種具體的單向雜湊函式演算法。訊息認證碼能夠對通訊物件進行認證,但無法對第三方進行認證。此外,它也無法防止否認。訊息認證碼也可以用來實現認證加密。

  test('訊息認證碼', () => {
    const hmac = crypto.createHmac('sha256', salt)
    hmac.update(plainText)
    const msg = hmac.digest('hex')
    expect(msg).not.toBeNull()
  })

數字簽名

是一種能夠對第三方進行資訊認證,並能夠防止通訊物件做出否認的認證技術。數字簽名的演算法包括RSA、ElGamal、DSA、橢圓曲線DSA、愛德華茲曲線DSA等。公鑰基礎設施 PKI 中使用的證照,就是對公鑰加上認證機構的數字簽名所構成的。要驗證公鑰的數字簽名,需要通過某種途徑獲取認證機構的自身的合法公鑰。

  test('數字簽名', () => {
    const sign = crypto.createSign('RSA-SHA256')
    const signature = sign.sign(privateKey)
    const verify = crypto.createVerify('RSA-SHA256')
    expect(verify.verify(publicKey, signature)).toBeTruthy()
  })

偽隨機數生成器

一種能夠生成具備不可預測性的位元序列的技術,由密碼和單向雜湊函式等技術構成。偽隨機數生成器用於生成金鑰、初始化向量和 nonce 等

  test('偽隨機數生成器', () => {
    const random = crypto.randomBytes(256).toString('hex')
    console.log(random)
    expect(random.length).toBe(512)
  })

完整程式碼

github
歡迎star

相關文章