Blog Address:NodeJS Module Studies – Crypto
Making:Github.com/dongyuanxin…
The crypto module in NodeJS provides apis for various encryption algorithms. This article records the types, features, uses and code implementation of commonly used encryption algorithms. Among them, there are many algorithms and wide application, and each algorithm has its own applicable scene. Several common algorithms documented in this article are listed for fluency:
- Content Summary: Hash algorithm
- Abstract: HMac algorithm
- Content Encryption and decryption: Symmetric Encryption (AES) and Asymmetric Encryption and Decryption (RSA)
- Content signing: Signature and validation algorithms
Hash algorithm
A Hash function, also known as a Hash algorithm, is a method of creating small digital “fingerprints” from any kind of data. The basic idea is to take any length of data and output a fixed-length result.
The Hash algorithm has the following features:
- The original data cannot be pushed backwards from the hash value
- Different inputs, different outputs
- A good hash algorithm has a lower conflict probability
Because of these features, the Hash algorithm is mainly used for encryption, data verification, version identification, load balancing, and distribution (consistent hash).
The following implements a function to get the file identity:
const crypto = require("crypto");
const fs = require("fs");
function getFileHash(file, algorithm) {
if(! crypto.getHashes().includes(algorithm)) {throw new Error("This hash function is not supported.");
}
return new Promise(resolve= > {
const hash = crypto.createHash(algorithm);
const rs = fs.createReadStream(file);
rs.on("readable", () = > {const data = rs.read();
if(data) { hash.update(data); }}); rs.on("end", () => {
resolve(hash.digest("hex"));
});
});
}
// Usage: get file MD5
getFileHash("./db.json"."md5").then(val= > {
console.log(val);
});
Copy the code
HMac algorithm
An attacker can use a “rainbow table” to crack a hash table. The way to deal with rainbow tables is to salt the password and hash the PWD and salt together. The salt is randomly generated, the longer the better, and needs to be stored in the data table corresponding to the user name and password.
Although the hash length is extended by adding salt, the attacker can also crack the attack by submitting passwords and hash values. The server makes a string of the submitted password and salt and compares it with the submitted hash value. If the system cannot commit a hash value, it is not subject to such attacks.
Obviously, there is no absolutely safe way. However, the HMac algorithm is not recommended. It can use any Hash function, such as MD5 => HmacMD5 and sha1 => HmacSHA1.
Here are the functions that use Hmac to encrypt data:
const crypto = require("crypto");
function encryptData(data, key, algorithm) {
if(! crypto.getHashes().includes(algorithm)) {throw new Error("This hash function is not supported.");
}
const hmac = crypto.createHmac(algorithm, key);
hmac.update(data);
return hmac.digest("hex");
}
// output: 30267bcf2a476abaa9b9a87dd39a1f8d6906d1180451abdcb8145b384b9f76a5
console.log(encryptData("root"."7(23y*&745^%I"."sha256"));
Copy the code
Symmetric Encryption (AES) vs. Asymmetric Encryption and Decryption (RSA)
A lot of data needs to be stored encrypted and decrypted for use. This is different from the irreversible hash function. These algorithms are divided into two categories:
- Symmetric encryption (AES) : Encryption and decryption use the same key
- Asymmetric encryption and decryption (RSA) : public key encryption and private key decryption
Symmetric encryption (AES)
View all encryption algorithms supported by NodeJS:
crypto.getCiphers();
Copy the code
Nodejs provides Cipher and Decipher classes for encryption and decryption, respectively. Both inherit from Transfrom Stream and use the API in a similar way to hash functions.
The following is plaintext encryption using aes-256-CBC algorithm:
const crypto = require("crypto");
const secret = crypto.randomBytes(32); / / key
const content = "hello world!"; // The plaintext to be encrypted
const cipher = crypto.createCipheriv(
"aes-256-cbc",
secret,
Buffer.alloc(16.0)); cipher.update(content,"utf8");
/ / the encrypted results: e2a927165757acc609a89c093d8e3af5
console.log(cipher.final("hex"));
Copy the code
Initiv (Cipher, Credential, iv, authTagLength); This [kHandle]. Initiv (Cipher, Credential, iv, authTagLength); Error: Invalid key length… The error. For example, the AES-256-CBC algorithm requires a key of 256 bits = 32 bytes. Similarly, THE IV of AES is also required and requires 128bits. (Please refer to the “Reference Links” section)
Using 32 consecutive as a key, I use aes – 256 – CBC is a061e67f5643d948418fdb150745f24d encrypted result. Here is the reverse decryption process:
const secret = "I".repeat(32);
const decipher = crypto.createDecipheriv(
"aes-256-cbc",
secret,
Buffer.alloc(16.0)); decipher.update("a061e67f5643d948418fdb150745f24d"."hex");
console.log(decipher.final("utf8")); // Decrypt the result: Hello world!
Copy the code
Asymmetric Encryption and Decryption (RSA)
Generate private and public keys with OpenSSL:
#Generate the private key
openssl genrsa -out privatekey.pem 1024
#To generate a public key
openssl rsa -in privatekey.pem -pubout -out publickey.pem
Copy the code
The hello world! The encryption and decryption codes are as follows:
const crypto = require("crypto");
const fs = require("fs");
const privateKey = fs.readFileSync("./privatekey.pem");
const publicKey = fs.readFileSync("./publickey.pem");
const content = "hello world!"; // Plain text to be encrypted
// Public key encryption
const encodeData = crypto.publicEncrypt(publicKey, Buffer.from(content));
console.log(encodeData.toString("base64"));
// Private key decryption
const decodeData = crypto.privateDecrypt(privateKey, encodeData);
console.log(decodeData.toString("utf8"));
Copy the code
Signature and validation algorithms
In addition to irreversible hashing algorithms, data encryption algorithms, there are special algorithms for signature and verification. Openssl is also used to generate public and private keys.
The code example is as follows:
const crypto = require("crypto");
const fs = require("fs");
const assert = require("assert");
const privateKey = fs.readFileSync("./privatekey.pem");
const publicKey = fs.readFileSync("./publickey.pem");
const data = "Transmitted data";
// Step 1: use the private key pair to generate the corresponding signature
const sign = crypto.createSign("sha256");
// Add data
sign.update(data, "utf8");
sign.end();
// Generate a signature based on the private key
const signature = sign.sign(privateKey, "hex");
// Step 2: Verify the accuracy of the signature with the public key
const verify = crypto.createVerify("sha256");
verify.update(data, "utf8");
verify.end();
assert.ok(verify.verify(publicKey, signature, "hex"));
Copy the code
As can be seen from the previous code, using the private key to encrypt, get the signature value; Finally, the public key is used for verification.
conclusion
Before has been a little knowledge, some concepts are very vague, often confused with hash algorithm and encryption algorithm. After finishing this note, I made clear the functions and uses of common encryption algorithms.
In addition, crypto module also provides other algorithmic tools, such as ECDH in blockchain applications. This article is not recorded, interested students can go to the relevant information.
Refer to the link
- NodeJS docs: crypto
- Recommended: Node.js encryption algorithm library Crypto
- Recommended: What is hash? – Answer from Tencent Technology Engineering – Zhihu
- Wiki: Hash functions
- Store and validate hashed password
- Wiki: rainbow tables
- Nodejs 6.10.2 crypto AES Invalid key length
- Encrypting using AES-256, can I use 256 bits IV?
- Crypto encryption and decryption
👇 scan code to pay attention to the “xin Tan blog”, view the “front-end atlas” & “algorithm problem solving”, adhere to sharing, grow together 👇