Node.js——crypto加密模块

张开发
2026/4/5 6:24:17 15 分钟阅读

分享文章

Node.js——crypto加密模块
crypto加密模块1、crypto模块概述1.1、支持的加密算法1.2、支持的散列算法2、散列算法3、HMAC算法4、公钥加密4.1、Cipher加密数据4.2、Decipher解密4.3、Sign签名4.4、Verify验签1、crypto模块概述在Node.js中使用OpenSSL类库作为其内部实现加密与解密处理的基础手段这是因为目前OpenSSL已经成为了一个经过严格测试的可靠的加密与解密算法的实现工具。在Node.js中OpenSSL类库被封装在crypto模块中因此开发者可以使用crypto模块来实现各种不同的加密与解密处理。例如crypto模块中包含了类似MD5或SH-2之类的散列算法。开发者也可以通过crypto模块来实现HMAC运算 。在crypto模块中提供了一些加密方法来实现数据的可靠加密。另外在crypto模块中也提供了一些利用HMAC运算来实现数字签名以及对数字签名进行验证的方法。1.1、支持的加密算法在crypto模块中为每一种加密算法定义了一个类。可以使用getCiphers方法来查看Node.js中能够使用的所有加密算法。该方法的使用方式如下所示。crypto.getCiphers()aes-128-cbc aes-128-cbc-hmac-sha1 aes-128-cbc-hmac-sha256 aes-128-ccm aes-128-cfb aes-128-cfb1 aes-128-cfb8 aes-128-ctr aes-128-ecb aes-128-gcm aes-128-ocb aes-128-ofb aes-128-xts aes-192-cbc aes-192-ccm aes-192-cfb aes-192-cfb1 aes-192-cfb8 aes-192-ctr aes-192-ecb aes-192-gcm aes-192-ocb aes-192-ofb aes-256-cbc aes-256-cbc-hmac-sha1 aes-256-cbc-hmac-sha256 aes-256-ccm aes-256-cfb aes-256-cfb1 aes-256-cfb8 aes-256-ctr aes-256-ecb aes-256-gcm aes-256-ocb aes-256-ofb aes-256-xts aes128 aes128-wrap aes192 aes192-wrap aes256 aes256-wrap aria-128-cbc aria-128-ccm aria-128-cfb aria-128-cfb1 aria-128-cfb8 aria-128-ctr aria-128-ecb aria-128-gcm aria-128-ofb aria-192-cbc aria-192-ccm aria-192-cfb aria-192-cfb1 aria-192-cfb8 aria-192-ctr aria-192-ecb aria-192-gcm aria-192-ofb aria-256-cbc aria-256-ccm aria-256-cfb aria-256-cfb1 aria-256-cfb8 aria-256-ctr aria-256-ecb aria-256-gcm aria-256-ofb aria128 aria192 aria256 bf bf-cbc bf-cfb bf-ecb bf-ofb blowfish camellia-128-cbc camellia-128-cfb camellia-128-cfb1 camellia-128-cfb8 camellia-128-ctr camellia-128-ecb camellia-128-ofb camellia-192-cbc camellia-192-cfb camellia-192-cfb1 camellia-192-cfb8 camellia-192-ctr camellia-192-ecb camellia-192-ofb camellia-256-cbc camellia-256-cfb camellia-256-cfb1 camellia-256-cfb8 camellia-256-ctr camellia-256-ecb camellia-256-ofb camellia128 camellia192 camellia256 cast cast-cbc cast5-cbc cast5-cfb cast5-ecb cast5-ofb chacha20 chacha20-poly1305 des des-cbc des-cfb des-cfb1 des-cfb8 des-ecb des-ede des-ede-cbc des-ede-cfb des-ede-ecb des-ede-ofb des-ede3 des-ede3-cbc des-ede3-cfb des-ede3-cfb1 des-ede3-cfb8 des-ede3-ecb des-ede3-ofb des-ofb des3 des3-wrap desx desx-cbc id-aes128-CCMid-aes128-GCMid-aes128-wrap id-aes128-wrap-pad id-aes192-CCMid-aes192-GCMid-aes192-wrap id-aes192-wrap-pad id-aes256-CCMid-aes256-GCMid-aes256-wrap id-aes256-wrap-pad id-smime-alg-CMS3DESwrap idea idea-cbc idea-cfb idea-ecb idea-ofb rc2 rc2-128rc2-40rc2-40-cbc rc2-64rc2-64-cbc rc2-cbc rc2-cfb rc2-ecb rc2-ofb rc4 rc4-40rc4-hmac-md5 seed seed-cbc seed-cfb seed-ecb seed-ofb sm4 sm4-cbc sm4-cfb sm4-ctr sm4-ecb sm4-ofb1.2、支持的散列算法使用getHashes方法查看所有散列算法:crypto.getHashes()RSA-MD4 RSA-MD5 RSA-MDC2 RSA-RIPEMD160 RSA-SHA1 RSA-SHA1-2 RSA-SHA224 RSA-SHA256 RSA-SHA3-224 RSA-SHA3-256 RSA-SHA3-384 RSA-SHA3-512 RSA-SHA384 RSA-SHA512 RSA-SHA512/224 RSA-SHA512/256 RSA-SM3 blake2b512 blake2s256 id-rsassa-pkcs1-v1_5-with-sha3-224 id-rsassa-pkcs1-v1_5-with-sha3-256 id-rsassa-pkcs1-v1_5-with-sha3-384 id-rsassa-pkcs1-v1_5-with-sha3-512 md4 md4WithRSAEncryption md5 md5-sha1 md5WithRSAEncryption mdc2 mdc2WithRSA ripemd ripemd160 ripemd160WithRSA rmd160 sha1 sha1WithRSAEncryption sha224 sha224WithRSAEncryption sha256 sha256WithRSAEncryption sha3-224 sha3-256 sha3-384 sha3-512 sha384 sha384WithRSAEncryption sha512 sha512-224 sha512-224WithRSAEncryption sha512-256 sha512-256WithRSAEncryption sha512WithRSAEncryption shake128 shake256 sm3 sm3WithRSAEncryption ssl3-md5 ssl3-sha1 whirlpool2、散列算法在Node.js中为了使用散列算法首先应该使用createHash方法创建一个hash对象。createHash方法的使用方式如下所示。crypto.createHash(algorithm)algorithm一个在Node.js中可以使用的算法例如’sha1’、‘md5’、‘sha256’、sha512’和’ripemd160’等在创建了一个hash对象后可以通过使用该对象的update方法创建一个摘要。该方法的使用方式如下所示代码中的hash代表一个hash对象​。可以在摘要被输出前使用多次update方法来添加摘要内容。hash.update(data,[input_encoding])data一个Buffer对象或一个字符串用于指定摘要内容input_encoding可选用于指定摘要内容所需使用的编码格式可指定参数值为“utf8”​、​“ascii”或“binary”​。如果不使用input_encoding参数则data参数值必须为一个Buffer对象。可以使用hash对象的digest方法来输出摘要内容。在使用了hash对象的digest方法后不能再向hash对象中追加摘要内容。digest方法的使用方式如下所示代码中的hash代表一个hash对象​。hash.digest([encoding])encoding可选参数值为一个字符串用于指定输出摘要的编码格式可指定参数值为“hex”​、​“binary”及“base64”​。如果使用了该参数那么digest方法返回字符串格式的摘要内容如果不使用该参数那么digest方法返回一个Buffer对象。在hash对象的digest方法被调用之后该对象不能再被使用。示例sha1算法为app.js生成一个摘要constcryptorequire(crypto);constfsrequire(fs);letshasumcrypto.createHash(sha1);letsfs.ReadStream(./index.js);s.on(data,(data){shasum.update(data);});s.on(end,(){letdshasum.digest(hex);console.log(d);});//输出 68e7997830b957c2d58645561b5e17af57b8bdbd//使用openssl验证$ openssl dgst-sha1index.js SHA1(index.js)68e7997830b957c2d58645561b5e17af57b8bdbd3、HMAC算法HMAC算法将散列算法与一个密钥结合在一起以阻止对签名完整性的破坏。在Node.js中为了使用HMAC算法首先应该使用createHmac方法创建一个hmac对象。createHmac方法的使用方式如下所示。crypto.createHmac(algorithm,key)algorithm一个在Node.js中可以使用的算法例如’sha1’、‘md5’、‘sha256’、sha512’和’ripemd160’等key为一个字符串用于指定一个PEM格式的密钥。在OpenSSL工具中可以使用如下命令创建一个密钥。openssl genrsa-outkey.pem1024在创建了一个hmac对象后可以通过使用该对象的update方法来创建一个摘要。该方法的使用方式如下所示代码中的hmac代表一个hmac对象​。hmac.update(data)data一个Buffer对象或一个字符串用于指定摘要内容。可以在摘要被输出前使用多次update方法来添加摘要内容。可以使用hmac对象的digest方法输出摘要内容。在使用了hmac对象的digest方法后不能再向hmac对象中追加摘要内容。digest方法的使用方式如下所示代码中的hmac代表一个hmac对象​。hmac.digest([encoding])encoding可选参数值为一个字符串用于指定输出摘要的编码格式可指定参数值为“hex”​、​“binary”及“base64”​。如果使用了该参数digest方法返回字符串格式的摘要内容如果不使用该参数digest方法返回一个Buffer对象。当hmac对象的digest方法被调用之后该对象不能再被使用。示例使用sha1算法以及key.pem密钥index.js文件生成一个摘要constcryptorequire(crypto);constfsrequire(fs);letpemfs.readFileSync(key.pem);letkeypem.toString(ascii);letshasumcrypto.createHmac(sha1,key);letsfs.ReadStream(./index.js);s.on(data,(d){shasum.update(d);});s.on(end,(){vardshasum.digest(hex);console.log(d);});48c97f16616f8aba06a8b9ec83989234e09f3b3d4、公钥加密Node.js提供了以下4个与公钥加密相关的类。Cipher类用于加密数据。Decipher类用于解密数据。Sign类用于生成签名。Verify类用于验证签名。在使用HMAC算法时只需要使用一个私钥但在使用公钥加密技术时需要使用公钥及私钥其中私钥用于解密数据以及对数据进行签名而公钥用于创建只有私钥的拥有者能够读出的加密数据以及对私钥的拥有者的签名进行验证。在OpenSSL工具中可以使用如下命令来为一个私钥创建一个PEM格式的公钥。openssl req-keykey.pem-new-x509-outcert.pem4.1、Cipher加密数据在crypto模块中Cipher类用于对数据进行加密操作。在加密数据之前首先需要创建一个cipher对象。可以通过如下所示的两种方法创建cipher对象。createCipher方法(不推荐)该方法使用指定的算法与密码来创建cipher对象。该方法的使用方式如下所示。crypto.createCipher(algorithm,password)algorithm指定在加密数据时所使用的算法例如“blowfish’”​、​“aes-256-cbc”等。password指定加密时所使用的密码参数值必须为一个二进制格式的字符串或一个Buffer对象。createCipheriv方法(推荐)该方法使用指定的算法、密码与初始向量Initialization VectorIV来创建cipher对象。该方法的使用方式如下crypto.createCipheriv(algorithm,password,iv)algorithm指定在加密数据时所使用的算法例如“blowfish’”​、​“aes-256-cbc”等。password指定加密时所使用的密码参数值必须为一个二进制格式的字符串或一个Buffer对象。iv指定加密时所使用的初始向量参数值必须为一个二进制格式的字符串或一个Buffer对象。在Node.js中使用分块加密法进行加密。分块加密法将固定长度的数据块或纯文本数据加密成长度相同的密码块数据。该转换的前提是用户提供密码。在解密时要使用相同的密码对密码块数据进行逆转换。此处的“固定长度”称为数据块的尺寸。根据使用算法的不同数据块的尺寸也各不相同。例如在使用blowfish算法时数据块的尺寸为40字节。分块加密法可以在网站被攻击时防止加密数据以及加密时所使用的密码泄漏。在创建了一个cipher对象后可以通过使用该对象的update方法来指定需要被加密的数据。该方法的使用方式如下所示代码中的cipher代表一个cipher对象​。cipher.update(data,[input_encoding],[output_encoding])data一个Buffer对象或一个字符串用于指定需要加密的数据input_encoding可选指定被加密的数据所需使用的编码格式可指定参数值为“utf8”​、​“ascii”及“binary”​。如果不使用input_encoding参数则data参数值必须为一个Buffer对象。output_encoding可选指定输出加密数据时使用的编码格式可指定参数值为“hex”​、​“binary”或“base64”​。update方法返回被加密的数据。可以使用update方法多次以添加需要加密的数据。如果在update方法中使用output_encoding参数则该方法返回被编码的字符串如果在update方法中不使用output_encoding参数则该方法返回一个存放了加密数据的Buffer对象。与hash对象及hmac对象的update方法不同的是cipher对象的update方法总是返回一个被分块的加密数据因此块的大小是非常关键的。如果加密数据的字节数足够创建一个或多个块update方法将返回被加密的数据。如果加密数据的字节数不足以创建一个块加密数据将被缓存在cipher对象中。使用cipher对象的final方法来返回加密数据。当该方法被调用时任何cipher对象中所缓存的数据都将被加密如果加密数据的字节数不足以创建一个块将使用PKCS填充方式来填充这个块。在使用了cipher对象的final方法后不能再向cipher对象中追加加密数据。final方法的使用方式如下所示代码中的cipher代表一个cipher对象​。cipher.final([output_encoding])output_encoding一个字符串用于指定在输出加密数据的编码格式可指定参数值为“hex”​、​“binary”及“base64”​。如果使用了该参数那么final方法返回字符串格式的加密数据如果不使用该参数那么final方法返回一个Buffer对象。当cipher对象的final方法被调用之后该对象不能再被使用。示例使用cipher对象加密“test”字符串加密算法为blowfish密码从应用程序根目录下的key.pem私钥中读出在完成数据加密后在控制台中输出加密数据的hex编码格式字符串。constcryptorequire(crypto);constfsrequire(fs);letpemfs.readFileSync(key.pem);letkeypem.toString(ascii);letciphercrypto.createCipheriv(blowfish,key,Buffer.from(12345678));lettexttest;cipher.update(text,binary,hex);letcryptedcipher.final(hex)console.log(crypted);44e0d7b155a3a89f4.2、Decipher解密在crypto模块中Decipher类用于对加密后的数据进行解密操作。在解密数据之前首先需要创建一个decipher对象。可以通过如下所示的两种方法创建decipher对象。createDecipher方法(不推荐)该方法使用指定的算法与密码来创建decipher对象。该方法的使用方式如下所示。crypto.createDecipher(algorithm,password)algorithm指定在解密数据时所使用的算法例如“blowfish”​、​“aes-256-cbc”等该算法必须与加密该数据时所使用的算法保持一致。passwordpassword参数用于指定解密时所使用的密码其参数值必须为一个二进制格式的字符串或一个Buffer对象该密码必须与加密该数据时所使用的密码保持一致。createDecipheriv方法推荐*该方法使用指定的算法、密码与初始向量来创建decipher对象。该方法的使用方式如下所示。crypto.createDecipheriv(algorithm,password,iv)algorithm指定在解密数据时所使用的算法例如“blowfish”​、​“aes-256-cbc”等该算法必须与加密该数据时所使用的算法保持一致password指定解密时所使用的密码参数值必须为一个二进制格式的字符串或一个Buffer对象该密码必须与加密该数据时所使用的密码保持一致iv指定解密时所使用的初始向量参数值必须为一个二进制格式的字符串或一个Buffer对象该初始向量必须与加密该数据时所使用的初始向量保持一致。在创建了一个decipher对象之后可以通过使用该对象的update方法来指定需要被解密的数据。该方法的使用方式如下所示decipher.update(data,[input_encoding],[output_encoding])data一个Buffer对象或一个字符串用于指定需要被解密的数据input_encoding可选指定被解密的数据所使用的编码格式可指定参数值为“hex”​、​“binary”及“base64”​。如果不使用input_encoding参数则data参数值必须为一个Buffer对象output_encoding可选指定输出解密数据时使用的编码格式可指定参数值为“utf8”​、​“ascii”或“binary”​update方法返回被解密的数据。可以使用多次update方法来添加需要被解密的数据。如果在update方法中使用output_encoding参数该方法返回被编码的字符串如果在update方法中不使用output_encoding参数该方法返回一个存放了解密数据的Buffer对象。使用decipher对象的final方法来返回经过解密之后的原始数据。final方法的使用方式如下所示代码中的decipher代表一个decipher对象​。decipher.final([output_encoding])output_encoding可选一个字符串用于指定在输出解密数据时使用的编码格式可指定参数值为“utf8”​、​“ascii”或“binary”​。如果使用了该参数final方法返回字符串格式的解密数据如果不使用该参数final方法返回一个Buffer对象。在decipher对象的final方法被调用之后该对象不能再被使用。示例将经过加密后的数据进行解密并且在控制台中输出经过解密操作后原始数据的utf8格式的字符串。constcryptorequire(crypto);constfsrequire(fs);letpemfs.readFileSync(key.pem);letkeypem.toString(ascii);letciphercrypto.createCipheriv(blowfish,key,Buffer.from(12345678));lettexttest;cipher.update(text,binary,hex);letcryptedcipher.final(hex)console.log(crypted);//解密letdeciphercrypto.createDecipheriv(blowfish,key,Buffer.from(12345678));letdecdecipher.update(crypted,hex,utf8);decdecipher.final(utf8);console.log(dec);44e0d7b155a3a89f test4.3、Sign签名在网络中私钥的拥有者可以在一段数据被发送之前先对该数据进行签名操作在签名的过程中将对这段数据执行加密处理。在经过加密后的数据发送之后数据的接收者可以通过公钥的使用来对该签名进行解密及验证操作以确保这段数据是私钥的拥有者所发出的原始数据且在网络的传输过程中未被修改。在Node.js中在进行签名操作之前首先需要使用createSign方法创建一个sign对象该方法的使用方式如下所示。crypto.createSign(algorithm)algorithm指定在加密该数据时所使用的算法例如“RSA-SHA256”​。在创建了一个sign对象后可以通过使用该对象的update方法来指定需要被加密的数据。该方法的使用方式如下所示sign.update(data)data一个Buffer对象或一个字符串用于指定需要被加密的数据。可以在对数据进行签名前使用多次update方法来添加数据。使用sign对象的sign方法对数据进行签名。在使用了sign对象的sign方法之后不能再使用sign对象的update方法追加数据。sign方法的使用方式如下所示sign.sign(private_key,[output_format])private_key一个字符串用于指定PEM格式的私钥output_format可选指定签名输出时所使用的编码格式可指定参数值为“hex”​、​“binary”或“base64”​。如果使用了该参数sign方法返回字符串格式的签名内容如果不使用该参数sign方法返回一个Buffer对象。当sign对象的sign方法被调用之后该对象不能再被使用。示例使用sign对象对“test”字符串进行签名加密算法为RSA-SHA256私钥从应用程序根目录下的key.pem文件中读出在数据签名完毕后在控制台中输出数据签名的hex编码格式字符串。constcryptorequire(crypto);constfsrequire(fs);letpemfs.readFileSync(key.pem);letkeypem.toString(ascii);letsigncrypto.createSign(RSA-SHA256);sign.update(test);console.log(sign.sign(key,hex));812da8dae8ec5b09f010d81c06afd2a3dc766801ea466f46763d31a98d04d7f5f55a2a0e7ef66a60551495ddbfde73c5ffc9d3822257a25195c115d2f41753d9685988653ddb0036adb753f8eff3ea0ec2248c32d5e19824b5d3dc2ed74bbb922b5b5457c243fd25b5399e061def56e788f9a4ec759ff4f764f95d04879547374.4、Verify验签在crypto模块中Verify类用于对签名进行验证操作。在对签名进行验证之前首先需要创建一个verify对象可以通过createVerify方法创建verify对象该方法的使用方式如下所示。crypto.createVerify(algorithm)algorithm指定在验证签名数据时所使用的算法例如“RSA-SHA256”​该算法必须与加密该数据时所使用的算法保持一致。通过使用该对象的update方法来指定需要被验证的数据。该方法的使用方式如下所示verify.update(data)data一个Buffer对象或一个字符串用于指定需要验证的数据。可以使用多次update方法来添加需要验证的数据。使用verify对象的verify方法来对签名进行验证。verify方法的使用方式如下所示verify.verify(object,signature,[signature_format])object指定验证时所使用的对象参数值为一个字符串该字符串值可以为一个RSA公钥、一个DSA公钥或一个X.509证书signature必须为sign对象用于指定被验证的签名signature_format可选指定在生成该签名时所使用的编码格式可指定参数值为“hex”​、​“binary”及“base64”​示例使用sign对象对“test”字符串进行签名加密算法为RSA-SHA256私钥从应用程序根目录下的key.pem文件中读出在数据签名完毕后创建一个verify对象指定验证数据为“test”字符串使用从应用程序根目录下的cert.pem公钥文件中读取的公钥进行验证最后在控制台中输出验证结果。constcryptorequire(crypto);constfsrequire(fs);//私钥letprivatePemfs.readFileSync(key.pem);//包含公钥的证书letpublicPemfs.readFileSync(cert.pem);letkeyprivatePem.toString();letpubkeypublicPem.toString();letdatatestletsigncrypto.createSign(RSA-SHA256);sign.update(data);//签名letsigsign.sign(key,hex);//验签letverifycrypto.createVerify(RSA-SHA256);verify.update(data);console.log(verify.verify(pubkey,sig,hex));true

更多文章