Home Node.js: 7 cryptography concepts using ctypto module
Post
Cancel

Node.js: 7 cryptography concepts using ctypto module

這篇要介紹nodejs中的crypto module的用法,如何使用這個module來實現密碼學中常見的概念, 包含hashsaltpassword hashingMAC(message authentication code)Symmetric EncryptionAsymmetric EncryptionDigital Signature

cryptography in node.js cryto module

Hash

可以使用指令openssl list -digest-algorithms來查詢可用的algorithms,以下使用sha256為例, 並輸出base64的字串。

1
2
3
4
5
const { createHash } = require('crypto');

function hash(input) {
    return createHash('sha256').update(input).digest('base64');
}

Salt

randomBytes可以幫我們隨機產生你所想要長度的隨機亂數,用來作為salt, 它的回傳值是一個Buffer。

1
2
3
4
5
6
const { randomBytes } = require('crypto');

function salt(len) {
    return randomBytes(len).toString('hex')
}

Password hashing

利用scryptscryptSync這個KDF(一個為非同步,一個為同步的API), function的前三個參數分別為:

  1. 欲hash的明文資料,此處為密碼
  2. salt
  3. output的長度
1
2
3
4
5
6
7
8
const { scryptSync, randomBytes } = require('crypto');

function passwordHash(password) {
    const salt = randomBytes(16).toString('hex');
    const hashedPassword = scryptSync(password, salt, 32).toString('hex');

    return `${salt}:${hashedPassword}`
}

以上例子使用randomBytes來產生salt,接著將密碼與salt一起hash成32 bytes的hash value,最後跟salt一起回傳。

MAC

跟hash一樣可以使用指令openssl list -digest-algorithms來查詢可用的演算法。

1
2
3
4
5
6
const { createHmac } = require('crypto');

const key = 'my-secret!';
const message = 'foo bar👻';

const hmac = createHmac('sha256', key).update(message).digest('hex');

Symmetric Encryption

支援的對稱式加密的演算法一樣可以透過這個指令來取得openssl list -cipher-algorithms,此處使用aes256

1
2
3
4
5
6
7
8
9
10
11
12
13
const { randomBytes, createCipheriv, createDecipheriv } = require('crypto');

const message = 'This is the message I wanna deliver';
const key = 'key shared between two parties';
const iv = randomBytes(16);

//Encrypt
const cipher = createCipheriv('aes256', key, iv);
const encryptedMessage = cipher.update(message, 'utf8', 'hex') + cipher.final('hex');

//Decrypt
const decipher = createDecipheriv('aes256', key, iv);
const decryptedMessage = decipher.update(encryptedMessage, 'hex', 'utf-8') + decipher.final('utf8');

Asymmetric Encryption

首先使用generateKeyPairgenerateKeyPairSync來產生公鑰及私鑰。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const { generateKeyPairSync } = require('crypto');

const { publicKey, privateKey } = generateKeyPairSync('rsa', {
    modulusLength: 4096,
    publicKeyEncoding: {
        type: 'spki',
        format: 'pem'
    },
    privateKeyEncoding: {
        type: 'pkcs8',
        format: 'pem',
        cipher: 'aes-256-cbc',
        passphrase: 'top secret'
    }
})

接者使用publicEncryptprivateDecrypt來encrypt、decrypt message。

1
2
3
4
5
6
7
8
9
const {  publicEncrypt, privateDecrypt } = require('crypto');

const message = "I am the message to be encypted🥳"

//加密 Encrypt
const encryptedData = publicEncrypt(publicKey, Buffer.from(message));

//解密 Decrypt
const decryptedData = privateDecrypt(privateKey, encryptedData);

Digital Signature

數位簽章牽扯到hash及非對稱加密,使用crypto module中的createSigncreateVerify, 回傳的SignVerify Object都幫我們做好好囉~

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const { createSign, createVerify } = require('crypto');

//取得你的公私鑰匙
const publicKey = require('./ssl/key.pem')
const privateKey = require('./ssl/cert.pem');

const message = 'this data must be signed';

//使用私鑰sign
const signer = createSign('rsa-sha256');
signer.update(message);
const signature = signer.sign(privateKey, 'hex');


// 使用公鑰verify
const verifier = createVerify('rsa-sha256');
verifier.update(message);
const isVerified = verifier.verify(publicKey, signature, 'hex');

Summay

其實就是從官方document裡,把比較常用的整理到這裡,這篇就只有紀錄在Nodejs裡如何實作, 並沒有討論為何需要上述的每一個東西,以及有何用途,有機會再陸續補上~ 掰掰👋

參考資料

This post is licensed under CC BY 4.0 by the author.

[System Design] 淺談Database Partition. Centralized and Distributed.

[System Design] 淺談Database Replication,有何優缺點、做法及何處可見?

Comments powered by Disqus.