Crypto - NodeJS 實作
https://nodejs.org/api/crypto.html#crypto
對稱加密
Cipher
Cipher 類別是實例是用來加密資料,有兩種使用方式:
- readstream / writestream生成加密stream資料
- cipher.update() 和 cipher.final()生成加密資料 Cipher 實例(instance)無法透過 new 直接建立,而是透過 crypto.createCipher() 或 crypto.createCipheriv() 這些方法。
// 'aes-128-cbc': {HashKey: crypto.randomBytes (16), HashIV: crypto.randomBytes (16)},
// 'aes-192-cbc': {HashKey: crypto.randomBytes (24), HashIV: crypto.randomBytes (16)},
// 'aes-256-cbc': {HashKey: crypto.randomBytes (32), HashIV: crypto.randomBytes (16)},
let info = 'orderid=abc1234';
let HashKey = 'Buffer';
let HashIV = 'Buffer';
let algorithm = 'aes-128-cbc';
let encrypt = createCipheriv (algorithm, HashKey, HashIV);
let enc = encrypt.update (info, 'utf8', 'hex');
let encode = enc + encrypt.final ('hex');
Decipher
Decipher 類別是實例是用來解密資料,有兩種使用方式:
- readstream / writestream生成解密stream資料
- cipher.update() 和 cipher.final()生成解密資料 Decipher 實例(instance)無法透過 new 直接建立,而是透過 crypto.createDecipher() 或 crypto.createDecipheriv() 這些方法。
// 'aes-128-cbc': {HashKey: crypto.randomBytes (16), HashIV: crypto.randomBytes (16)},
// 'aes-192-cbc': {HashKey: crypto.randomBytes (24), HashIV: crypto.randomBytes (16)},
// 'aes256': {HashKey: crypto.randomBytes (32), HashIV: crypto.randomBytes (16)},
let info = 'orderid=abc1234';
let HashKey = 'Buffer';
let HashIV = 'Buffer';
let algorithm = 'aes-128-cbc';
let encode = 'utf8';
let decrypt = crypto.createDecipheriv (algorithm, HashKey, HashIV); // 'aes-128-cbc'
decrypt.setAutoPadding (false);
let text = decrypt.update (info, 'hex', encode);
let plainText = text + decrypt.final (encode);
let decode = plainText.replace (/[\x00-\x20]+/g, '');
非對稱加密
生成RSA公私鑰匙
let { publicKey, privateKey } = generateKeyPairSync ('rsa', {
modulusLength: 1024,
publicKeyEncoding: {
type: 'spki',
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem',
cipher: 'aes-256-cbc',
passphrase: 'top secret'
}
});
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCiPJ5NMx3y1L0K6+oYAGjClPLC
E0t7FzYiKEEo6/rd1zxGRg1xeRH2GZzuwpIIefAAOl+nLIsDxAct79FyVqUjNXmU
oNe+1khXLx5BdLNgK61EfVujnBhfssgskUuzK9ONUiggrAK1pi5HZ2dfmsuqmFOt
dlYpiBmQdVVYeEEEhQIDAQAB
-----END PUBLIC KEY-----
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIC3TBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQI0w3sm1ScM2cCAggA
MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBDEqyxfB2XCpoa7JEdSOdOWBIIC
gAywshhuRc44lJ3zu+7hiC3pMLNLwT53EqiXACRH105OPXHPUvTnDWu6zSfWAhHg
EAXbl7gtjAmabbP71Q4D9NcfIpUL08SYmsVtJ63efLDEcgJAa0/NNiogsFa1v+33
6g6XsUgeEnb6iFHkfgRxKHn2QeycpaQXNPfkAefnIap+oulmo98SSaJvjKNTQWhR
0qFU/+TBwgAKW9DmSe39oA7AzcB3LI3Bj2sJhVaOeY8/0Nd4KkOGaerZe+dRCLOz
iXmPnp4y9tkjG+QHnJ5Si4fZkFSIrek2ZmFOy+DPRysoC9llJGJh0FDrJ2Tz73gU
gNdk99ZCQT/leRuNFnA3qs9VwKFDvJJFEYHEK0dNq5tk0eYaHxTE4hh5ZI9KPcln
IcIOgpCkYRnDkv2OoTziYrkgQYvx1hCgiFLId+hLxVeOdaImUBLmnHsQZrI9FVpM
Pk/nSyZxvphlUkeAaqZ/0XmzDUVzqE4JStMgT5OzLfcoKNKpIQTPcV/DPTGi5krS
sJm4h+EpAZLdHd9Qdi/LVcDKik6NN0zA87LaxFAsZ69J6krvz8wHHvYRCULWUFEd
G+SAkIYifPY4BzouEnXsBceoAfH9adGGL0VY3qFN3S62+j/47IkVfgg6eDIZ4UaH
hHC856+x/w2ljrQTwuHaTB7Jom/LCZh8tWoo1joSbhWAuJum4tpY3hStfIvGeOYU
SkPQFgDZA5rte7PeZoG0ZwnBO1YIH+qmUiZ1MsrJ9mW3h1SMRGNBUq69qNMFU2LT
lx0QXtWKyhW8tiM4vNk1Gw3JkiqapXibuYucnKcbLvWqtIKcQ55I1et5ysbOqvlL
3TsJwGgsXSndqTFxcYKqjK8=
-----END ENCRYPTED PRIVATE KEY-----
安全散列算法 SHA (Secure Hash Algorithm)
CreateHash
依據algorithm生成固定長度Hash code,支援的algorithms,在terminal 執行 openssl list -digest-algorithms
let sha = createHash (algorithm); // * algorithm SHA256、SHA512
let plainText = `HashKey=${HashKey}&${TradeInfo}&HashIV=${HashIV}`;
return sha.update (plainText).digest ('hex').toUpperCase ();
加解密
Base64 encoding
加解密例子
默認是使用的 PKCS7 填充模式
const key = crypto.randomBytes (192 / 8); // * based on algorithm
const iv = crypto.randomBytes (128 / 8); // * fixed length
const algorithm = 'aes-192-cbc';
const encoding = 'hex';
const encrypt = (text) => {
let cipher = crypto.createCipheriv (algorithm, key, iv);
let ctext = cipher.update (text, 'utf8', 'hex');
return ctext + cipher.final('hex');
};
const decrypt = (encrypted) => {
let decipher = crypto.createDecipheriv (algorithm, key, iv);
let dtext = decipher.update (encrypted, 'hex', 'utf8');
// * 禁用自動填充
decrypt.setAutoPadding (false);
let plainText = dtext + decipher.final ('utf8');
return plainText.replace (/[\x00-\x20]+/g, '');
};
const content = 'Hello Node.js';
const crypted = encrypt (content);
const decrypted = decrypt (crypted);