本文是通过 Node.js 实现密码学中所涉及到的哈希算法对称加密算法非对称加密算法密钥交换算法数字证书生成算法等实现方式的模版代码。
涉及到的 npm 模块为:cryptscryptbcryptforge 等。

密码哈希函数 - bcrypt

  1. const bcrypt = require('bcrypt');
  2. // 封装 hash 函数
  3. function bcrypt_encrypt(username, password) {
  4. // 1. bcrypt 内置了生成盐值的方法:bcrypt.genSalt()
  5. // 第一个参数是循环次数(或者称因子,默认为 10)
  6. bcrypt.genSalt(10, (err, salt) => {
  7. if (err) throw err;
  8. // 2. 生成哈希值:bcrypt.hash()
  9. bcrypt.hash(password, salt, (err, key) => {
  10. if (err) throw err;
  11. // 3. 把用户名、密码哈希值和盐值存入数据库
  12. // username、key、salt
  13. });
  14. });
  15. }
  16. // 调用示例
  17. bcrypt_encrypt('zhangsan', '123456');
  18. // 对比哈希值,验证密码:
  19. bcrypt.compare(password, hash, (err, same) => {
  20. // 返回 true 或 false
  21. });

密码哈希函数 - egg-bcrypt

  1. // config.default.js
  2. exports.bcrypt = {
  3. saltRounds: 10 // 循环次数,默认为 10
  4. }
  5. // {app_root}/config/plugin.js
  6. exports.bcrypt = {
  7. enable: true,
  8. package: 'egg-bcrypt'
  9. }
  10. // {app_root}/app/contoller/user.js
  11. async generate() {
  12. // 生成哈希值:ctx.genHash(plainText)
  13. const hash = await this.ctx.genHash(this.ctx.request.body.plainText);
  14. // Store hash in your password DB
  15. }
  16. async compare() {
  17. const { hash, plainText } = this.ctx.request.body;
  18. // 比较哈希值和原始字符串:ctx.compare(plainText, hash)
  19. const checked = await this.ctx.compare(plainText, hash);
  20. this.ctx.body = { checked };
  21. }

密码哈希函数 - PBKDF2

  1. /*
  2. * PBKDF2 是 Node.js 的 crypto 模块原生支持的标准方法。
  3. */
  4. // 【加密示例】
  5. // PBKDF2 算法
  6. function pbkdf2_encrypt(username, password) {
  7. // 1. crypto.randomBytes()方法生成 32 字节的随机盐值
  8. crypto.randomBytes(32, (err, salt) => {
  9. if (err) throw err;
  10. // 2. 参数列表:(密码,盐值,迭代次数,输出密钥长度,摘要算法)
  11. crypto.pbkdf2(password, salt, 4096, 512, 'sha256', (err, key) => {
  12. if (err) throw err;
  13. // 3. 将用户名、密码哈希值和盐值存入数据库
  14. // Salt 盐值是明文保存的,一般不和最终生成的密钥保存在一起。
  15. console.log(username, key.toString('hex'), salt.toString('hex'));
  16. });
  17. });
  18. }
  19. // 调用示例
  20. pbkdf2_encrypt('zhangSan', '123456');
  21. // 对比哈希值,验证密码
  22. const dbsalt = 'USER RECORD SALT FROM YOUR DATABASE';
  23. const dbhash = 'USER RECORD KEY FROM YOUR DATABASE';
  24. crypto.pbkdf2(password, dbsalt, 4096, 512, 'sha256', (err, comparsehash) => {
  25. if (err) throw err;
  26. // 比较
  27. if (dbhash.toString('hex') === comparsehash.toString('hex')) {
  28. // 密码匹配
  29. } else {
  30. // 密码不匹配
  31. }
  32. });

密码哈希函数 - scrypt

  1. const scrypt = require('scrypt');
  2. const crypto = require('crypto');
  3. function scrypt_encrypt(username, password) {
  4. // 1. 使用 crypto 的 crypto.randomBytes(...) 方法生成盐值。
  5. crypto.randomBytes(32, (err, salt) => {
  6. if (err) throw err;
  7. // 2. scrypt.hash(...) 生成 64 位的哈希值
  8. // - N: scrypt 最多使用多长时间(秒数)计算密钥(偶数)。
  9. // - r: 计算密钥时最多使用多少字节 RAM(整数)。默认为0。
  10. // - p: 计算密钥时所用 RAM 占可用值的比例(0-1,换算成百分比)默认为0.5。
  11. scrypt.hash(password, {"N":16384,"r":8,"p":1}, 64, salt, (err, key) => {
  12. if (err) throw err;
  13. // 3. 把用户名、密码哈希值和盐值存入数据库
  14. console.log(`key is ${key}`);
  15. });
  16. });
  17. }

crypto 模块 - 生成随机数

  1. const crypto = require('crypto');
  2. // 1.异步方法生成盐值
  3. // crypto.randomBytes() 生成 16 位强加密的伪随机数
  4. crypto.randomBytes(16, (err, buf) => {
  5. if (err) throw err;
  6. console.log(`${buf.length} bytes of random data: ${buf.toString('hex')}`);
  7. console.log(`${buf.length} bytes of random data: ${buf.toString('base64')}`);
  8. });
  9. // 2.同步方法生成盐值
  10. const buf = crypto.randomBytes(256);

crypto 模块 - aes-256-gcm 示例1

  1. /*
  2. * AES-256-GCM 对称加密算法,加密、解密示例
  3. */
  4. const crypto = require('crypto');
  5. // 初始化参数
  6. const text = 'Encryption Testing AES GCM mode'; // 要加密和解密的数据
  7. const key = crypto.randomBytes(32); // 256 位的共享密钥
  8. const iv = crypto.randomBytes(16); // 初始向量,16 字节
  9. const algorithm = 'aes-256-gcm'; // 加密算法和操作模式
  10. // 加密
  11. const cipher = crypto.createCipheriv(algorithm, key, iv); // 初始化加密算法
  12. let encrypted = cipher.update(text, 'utf8', 'hex');
  13. encrypted += cipher.final('hex');
  14. const tag = cipher.getAuthTag(); // 生成标签,用于验证密文的来源
  15. // 解密
  16. const decipher = crypto.createDecipheriv(algorithm, key, iv); // 初始化解密算法
  17. decipher.setAuthTag(tag); // 传入验证标签,验证密文的来源
  18. let decrypted = decipher.update(encrypted, 'hex', 'utf8');
  19. decrypted += decipher.final('utf8');
  20. console.log(decrypted); // Encryption Testing AES GCM mode

crypto 模块 - aes-256-gcm 示例2

  1. const crypto = require('crypto');
  2. const aes256gcm = key => {
  3. const ALGO = 'aes-256-gcm'; // 加密算法和操作模式
  4. // encrypt returns base64-encoded ciphertext
  5. const encrypt = str => {
  6. // Hint: the 'iv' should be unique (but not necessarily random).
  7. // 'randomBytes' here are (relatively) slow but convenient for demonstration
  8. const iv = new Buffer.from(crypto.randomBytes(16), 'utf8'); // 初始向量,16 字节
  9. const cipher = crypto.createCipheriv(ALGO, key, iv); // 初始化加密算法
  10. // Hint: Larger inputs (it's GCM, after all!) should use the stream API
  11. let enc = cipher.update(str, 'utf8', 'base64');
  12. enc += cipher.final('base64');
  13. return [ enc, iv, cipher.getAuthTag() ];
  14. };
  15. // decrypt decodes base64-encoded ciphertext into a utf8-encoded string
  16. const decrpt = (enc, iv, authTag) => {
  17. const decipher = crypto.createDecipheriv(ALGO, key, iv);
  18. decipher.setAuthTag(authTag);
  19. let str = decipher.update(enc, 'base64', 'utf8');
  20. str += decipher.final('utf8');
  21. return str;
  22. };
  23. return { encrypt, decrpt };
  24. };
  25. // 加密密钥
  26. // Note: a key size of 16 bytes will use AES-128, 24 => AES-192, 32 => AES-256
  27. const KEY = new Buffer.from(crypto.randomBytes(32), 'utf8');
  28. const aesCipher = aes256gcm(KEY);
  29. // 加密
  30. const [ encrypted, iv, authTag ] = aesCipher.encrypt('hello world');
  31. // 解密
  32. const decrypted = aesCipher.decrpt(encrypted, iv, authTag);
  33. console.log(decrypted); // hello world

crypto 模块 - DH 密钥交换

  1. /*
  2. DiffieHellman 类是一个用来创建 Diffie-Hellman 键交换的工具。
  3. DiffieHellman 类的实例可以使用 crypto.createDiffieHellman() 方法。
  4. */
  5. const crypto = require('crypto');
  6. const assert = require('assert');
  7. // Generate Alice's keys...
  8. const alice = crypto.createDiffieHellman(2048);
  9. const aliceKey = alice.generateKeys();
  10. // Generate Bob's keys...
  11. const bob = crypto.createDiffieHellman(alice.getPrime(), alice.getGenerator());
  12. const bobKey = bob.generateKeys();
  13. // Exchange and generate the secret...
  14. const aliceSecret = alice.computeSecret(bobKey);
  15. const bobSecret = bob.computeSecret(aliceKey);
  16. // OK
  17. assert.strictEqual(aliceSecret.toString('hex'), bobSecret.toString('hex'));

crypto 模块 - ECDH 密钥交换

  1. /*
  2. ECDH 类是创建椭圆曲线 Diffie-Hellman(Elliptic Curve Diffie-Hellman (ECDH))键交换的实用工具。
  3. ECDH 类的实例可以使用 crypto.createECDH() 方法。
  4. crypto.getCurves() 方法会返回一个数组,其中包含支持的椭圆曲线的名称。
  5. */
  6. const crypto = require('crypto');
  7. const assert = require('assert');
  8. // Generate Alice's keys...
  9. const alice = crypto.createECDH('secp521r1');
  10. const aliceKey = alice.generateKeys();
  11. // Generate Bob's keys...
  12. const bob = crypto.createECDH('secp521r1');
  13. const bobKey = bob.generateKeys();
  14. // Exchange and generate the secret...
  15. const aliceSecret = alice.computeSecret(bobKey);
  16. const bobSecret = bob.computeSecret(aliceKey);
  17. assert.strictEqual(aliceSecret.toString('hex'), bobSecret.toString('hex'));
  18. // OK

crypto 模块 - Hmac

  1. const crypto = require('crypto');
  2. const key = crypto.randomBytes(16); // 密钥
  3. const hmac = crypto.createHmac('sha1', key.toString('ascii'));
  4. hmac.update('hello world');
  5. console.log(hmac.digest('hex'));
  6. // 4e1926fdb2992c927574cc9cbdc2f9d167191e89

crypto 模块 - MD5

  1. const crypto = require('crypto');
  2. const md5 = crypto.createHash('md5');
  3. // 1. 直接对明文进行 Hash
  4. md5.update('123456');
  5. console.log(md5.digest('hex'));
  6. // 2. 加盐 Hash
  7. let password = '123456';
  8. let salt = 'hhug6dcKyCNBQ5sUC0i6hja5dCTqdSzV'; // 盐值
  9. // 将密码拼接上任意长度的随机字符串后,再进行 Hash
  10. md5.update(password+salt);
  11. console.log(md5.digest('hex'));

crypto 模块 - RSA 的加密和解密

  1. const crypto = require('crypto');
  2. const fs = require('fs');
  3. const path = require('path');
  4. const root = __dirname;
  5. const publicKey = fs.readFileSync(path.join(root, './mypubkey.pem')).toString('ascii');
  6. const privateKey = fs.readFileSync(path.join(root, './ mykey.pem')).toString('ascii');
  7. const data = 'data to crypt';
  8. // 公钥加密
  9. const encryptData = crypto.publicEncrypt(publicKey, Buffer.from(data)).toString('base64');
  10. console.log('encode', encryptData);
  11. // 私钥解密
  12. const decryptData = crypto.privateDecrypt(privateKey, Buffer.from(encryptData.toString('base64'), 'base64'));
  13. console.log('decode', decryptData.toString());

crypto 模块 - RSA 的签名和验证

  1. const crypto = require('crypto');
  2. const fs = require('fs');
  3. const path = require('path');
  4. const root = __dirname;
  5. // 加载私钥文件
  6. const pem = fs.readFileSync(path.join(root, './rsa_private_key.pem'));
  7. const key = pem.toString('ascii');
  8. // 加载公钥文件
  9. const publicKey = fs.readFileSync(path.join(root, './rsa_public_key.pem')).toString('ascii');
  10. // 签名
  11. const sign = crypto.createSign('RSA-SHA256'); // 创建签名算法
  12. sign.update('data to sign'); // 更新待签名内容
  13. const result = sign.sign(key, 'hex'); // sign.sign() 方法用于生成并返回签名
  14. console.log('result:', result);
  15. // 验证
  16. const verify = crypto.createVerify('RSA-SHA256'); // 创建验证算法
  17. verify.update('data to sign');
  18. console.log(verify.verify(publicKey, result, 'hex')); // true

crypto 模块 - RSA 密钥对生成

  1. /*
  2. crypto.generateKeyPair(type, options, callback)
  3. 参数:
  4. * `type`:<string> 类型,要生成的算法名称,必须是 `'rsa'`、`'dsa'` 或者 `'ec'` 之一;
  5. * `options`:<Object> 类型:
  6. * `modulusLength`:<number> 类型,密钥长度(RSA,DSA);
  7. * `publicExponent`:<number> 类型,公共指数(RSA),默认值:`0x10001`;
  8. * `divisorLength`:<number> 类型,以比特为单位的 q 的大小(DSA);
  9. * `namedCurve`:<string> 类型,要使用的椭圆曲线名称(EC);
  10. * `publicKeyEncoding`:<Object> 类型,公钥编码格式:
  11. * `type`:<string> 类型,必须是 `'pkcs1'`(仅限 RSA)或 `'spki'` 之一;
  12. * `format`:<string> 类型,公钥输出格式,必须是 `'pem'` 或 `'der'` 之一;
  13. * `privateKeyEncoding`:<Object> 类型,私钥编码格式:
  14. * `type`:<string> 类型,必须是 `'pkcs1'`(仅限 RSA)或 `'pkcs8'` 或 `'sec1'`(仅限 EC) 之一;
  15. * `format`:<string> 类型,公钥输出格式,必须是 `'pem'` 或 `'der'` 之一;
  16. * `cipher`:<string> 类型,如果指定算法,将使用基于 PKCS#5 v2.0 规范的算法和密钥加密,使用给定的算法和密钥加密私钥;
  17. * `passphrase`:<string> 类型,用于加密的密钥;
  18. * `callback`:<Function> 类型:
  19. * `err`:<Error> 类型
  20. * `publicKey`:<string> 类型 | <Buffer> 类型,设置为 PEM 编码时返回 String 类型,DER 编码则返回 Buffer 类型
  21. * `privateKey`:<string> 类型 | <Buffer> 类型
  22. */
  23. // 建议将公钥编码为 'spki' 格式,将私钥编码为 'pkcs8' 格式并加密保存:
  24. const { generateKeyPair } = require('crypto');
  25. generateKeyPair('rsa', {
  26. modulusLength: 4096,
  27. publicKeyEncoding: {
  28. type: 'spki', // pkcs1、spki
  29. format: 'pem'
  30. },
  31. privateKeyEncoding: {
  32. type: 'pkcs8', // pkcs1、pkcs8、sec1
  33. format: 'pem',
  34. cipher: 'aes-256-cbc',
  35. passphrase: 'top secret'
  36. }
  37. }, (err, publicKey, privateKey) => {
  38. // Handle errors and use the generated key pair.
  39. });

crypto 模块 - sha256

  1. const crypto = require('crypto');
  2. // 创建哈希函数 sha256
  3. const hash = crypto.createHash('sha256');
  4. // 输入流编码:utf8、ascii、binary(默认)
  5. hash.update('some data to hash', 'utf8');
  6. // 输出编码:hex、binary、base64
  7. console.log(hash.digest('hex'));

forge 模块 - 生成自签名证书

  1. const forge = require('node-forge');
  2. // 生成 RSA 密钥对,以创建自签名证书,并保存到 MongoDB 数据库
  3. const cert = forge.pki.createCertificate();
  4. const keys = forge.pki.rsa.generateKeyPair(2048);
  5. cert.publicKey = keys.publicKey;
  6. cert.serialNumber = '01';
  7. // 证书有效期
  8. cert.validity.notBefore = new Date();
  9. cert.validity.notAfter = new Date();
  10. cert.validity.notAfter.setFullYear(
  11. cert.validity.notBefore.getFullYear() + 1
  12. );
  13. const attrs = [
  14. {
  15. name: 'commonName',
  16. value: payload.username, // 默认名称为用户名
  17. },
  18. {
  19. name: 'countryName',
  20. value: 'china',
  21. },
  22. {
  23. shortName: 'ST',
  24. value: 'Virginia',
  25. },
  26. {
  27. name: 'localityName',
  28. value: 'Blacksbury',
  29. },
  30. {
  31. name: 'organizationName',
  32. value: 'tonintech',
  33. },
  34. {
  35. shortName: 'OU',
  36. value: 'test',
  37. },
  38. ];
  39. cert.setSubject(attrs);
  40. cert.setIssuer(attrs);
  41. // 证书扩展
  42. cert.setExtensions([
  43. {
  44. name: 'basicConstraints',
  45. cA: true,
  46. pathLenConstraint: 4,
  47. },
  48. {
  49. name: 'keyUsage',
  50. keyCertSign: true,
  51. digitalSignature: true,
  52. nonRepudiation: true,
  53. keyEncipherment: true,
  54. dataEncipherment: true,
  55. },
  56. {
  57. name: 'extKeyUsage',
  58. serverAuth: true,
  59. clientAuth: true,
  60. codeSigning: true,
  61. emailProtection: true,
  62. timeStamping: true,
  63. },
  64. {
  65. name: 'nsCertType',
  66. client: true,
  67. server: true,
  68. email: true,
  69. objsign: true,
  70. sslCA: true,
  71. emailCA: true,
  72. objCA: true,
  73. },
  74. {
  75. name: 'subjectAltName',
  76. altNames: [
  77. {
  78. type: 6, // URI
  79. value: 'http://example.org/webid#me',
  80. },
  81. {
  82. type: 7, // IP
  83. ip: '127.0.0.1',
  84. },
  85. ],
  86. },
  87. {
  88. name: 'subjectKeyIdentifier',
  89. },
  90. ]);
  91. // TODO: add authorityKeyIdentifier extension
  92. // 自签名证书
  93. cert.sign(keys.privateKey, forge.md.sha256.create());
  94. this.logger.debug('证书创建成功');
  95. // PEM-format keys and cert
  96. const pem = {
  97. privateKey: forge.pki.privateKeyToPem(keys.privateKey),
  98. publicKey: forge.pki.publicKeyToPem(keys.publicKey),
  99. certificate: forge.pki.certificateToPem(cert),
  100. };
  101. // 保存到 mongoDB 数据库:数字证书
  102. const CertificateEntity = new ctx.model.Certificates({
  103. certificate: pem.certificate,
  104. privateKey: pem.privateKey,
  105. });
  106. const certificate = await CertificateEntity.save();

Forge 模块 - PKCS#5

  1. /*
  2. 实现基于 PKCS#5 的基于口令的密钥派生功能。
  3. PBKDF2 !!!
  4. */
  5. // 生成基于口令的 16 进制密钥
  6. // note an optional message digest can be passed as the final parameter
  7. // 注意,可以将可选的消息摘要算法作为最终参数传递
  8. var salt = forge.random.getBytesSync(128);
  9. var derivedKey = forge.pkcs5.pbkdf2('password', salt, numIterations, 16);
  10. // 异步生成密钥
  11. // note an optional message digest can be passed before the callback
  12. forge.pkcs5.pbkdf2('password', salt, numIterations, 16, function(err, derivedKey) {
  13. // do something w/derivedKey
  14. });

forge 模块 - RSA 加密和解密

  1. const forge = require('node-forge');
  2. // 同步方式生成 RSA-2048 密钥对
  3. const keyPair = forge.pki.rsa.generateKeyPair(2048);
  4. const privateKey = keyPair.privateKey;
  5. const publicKey = keyPair.publicKey;
  6. // 加密和解密,默认 RSAES PKCS#1 v1.5
  7. const encrypted = publicKey.encrypt(bytes);
  8. const decrypted = privateKey.decrypt(encrypted);
  9. // 加密和解密,使用 RSAES PKCS#1 v1.5
  10. const encrypted = publicKey.encrypt(bytes, 'RSAES-PKCS1-V1_5');
  11. const decrypted = privateKey.decrypt(encrypted, 'RSAES-PKCS1-V1_5');
  12. // 加密和解密,使用 RSAES-OAEP
  13. const encrypted = publicKey.encrypt(bytes, 'RSA-OAEP');
  14. const decrypted = privateKey.decrypt(encrypted, 'RSA-OAEP');
  15. // 加密和解密,使用 RSAES-OAEP/SHA-256
  16. const encrypted = publicKey.encrypt(bytes, 'RSA-OAEP', {
  17. md: forge.md.sha256.create(),
  18. });
  19. const decrypted = privateKey.decrypt(encrypted, 'RSA-OAEP', {
  20. md: forge.md.sha256.create(),
  21. });
  22. // 加密和解密,使用 RSAES-OAEP/SHA-256/MGF1-SHA-1
  23. // 兼容 Java 的 RSA/ECB/OAEPWithSHA-256AndMGF1Padding
  24. var encrypted = publicKey.encrypt(bytes, 'RSA-OAEP', {
  25. md: forge.md.sha256.create(),
  26. mgf1: {
  27. md: forge.md.sha1.create(),
  28. },
  29. });
  30. var decrypted = privateKey.decrypt(encrypted, 'RSA-OAEP', {
  31. md: forge.md.sha256.create(),
  32. mgf1: {
  33. md: forge.md.sha1.create(),
  34. },
  35. });

forge 模块 - RSA 签名和验证

  1. const forge = require('node-forge');
  2. // 同步方式生成 RSA-2048 密钥对
  3. const keyPair = forge.pki.rsa.generateKeyPair(2048);
  4. const privateKey = keyPair.privateKey;
  5. const publicKey = keyPair.publicKey;
  6. // ------------------- RSASSA PKCS#1 v1.5 模式 --------------------------------
  7. // 使用私钥对数据进行签名并输出 DER 编码的字节
  8. // 默认为 RSASSA PKCS#1 v1.5 模式
  9. const md = forge.md.sha1.create();
  10. md.update('sign this', 'utf8');
  11. const signature = privateKey.sign(md);
  12. // 使用公钥验证数据
  13. const verified = publicKey.verify(md.digest().bytes(), signature);
  14. console.log(verified); // true
  15. // ------------------- RSASSA-PSS 模式 --------------------------------
  16. // 签名和验证,使用 RSASSA-PSS 模式
  17. // 其中,PSS 使用 SHA-1 作为哈希算法,SHA-1 基于 MGF1 函数,盐值长度为 20 byte
  18. var md = forge.md.sha1.create();
  19. md.update('sign this', 'utf8');
  20. var pss = forge.pss.create({
  21. md: forge.md.sha1.create(),
  22. mgf: forge.mgf.mgf1.create(forge.md.sha1.create()),
  23. saltLength: 20,
  24. // optionally pass 'prng' with a custom PRNG implementation
  25. // optionalls pass 'salt' with a forge.util.ByteBuffer w/custom salt
  26. });
  27. var signature = privateKey.sign(md, pss);
  28. // 验证 RSASSA-PSS 签名
  29. var pss = forge.pss.create({
  30. md: forge.md.sha1.create(),
  31. mgf: forge.mgf.mgf1.create(forge.md.sha1.create()),
  32. saltLength: 20,
  33. // optionally pass 'prng' with a custom PRNG implementation
  34. });
  35. var md = forge.md.sha1.create();
  36. md.update('sign this', 'utf8');
  37. publicKey.verify(md.digest().getBytes(), signature, pss);

forge 模块 - RSA 算法

  1. const forge = require('node-forge');
  2. // 同步方式生成 RSA-2048 密钥对(不推荐)
  3. const keyPair = forge.pki.rsa.generateKeyPair(2048);
  4. // 异步方式生成 RSA-2048 密钥对
  5. rsa.generateKeyPair({bits: 2048, workers: 2}, function(err, keypair) {
  6. // keypair.privateKey, keypair.publicKey
  7. });
  8. // 转换为 PEM 格式
  9. const privateKey = forge.pki.privateKeyToPem(keyPair.privateKey);
  10. const publicKey = forge.pki.publicKeyToPem(keyPair.publicKey);
  11. // 保存到数据库
  12. const KeyPairEntity = new ctx.model.KeyPairs({
  13. publicKey: publicKey,
  14. privateKey: privateKey,
  15. });
  16. const result = await KeyPairEntity.save();

forge 模块 - SSH 工具

  1. // 将一个 RSA 私钥文件编码(可选加密)为 Putty PPK 文件
  2. forge.ssh.privateKeyToPutty(privateKey, passphrase, comment);
  3. // 将一个 RSA 公钥文件编码为 OpenSSH 文件
  4. forge.ssh.publicKeyToOpenSSH(key, comment);
  5. // 将一个 RSA 私钥文件编码为 OpenSSH 文件
  6. forge.ssh.privateKeyToOpenSSH(privateKey, passphrase);
  7. // 从字节缓冲区(byte buffer)中获取 SSH 公钥指纹
  8. forge.ssh.getPublicKeyFingerprint(key);
  9. // 获取十六进制编码,以冒号分隔的 SSH 公钥指纹
  10. forge.ssh.getPublicKeyFingerprint(key, {encoding: 'hex', delimiter: ':'});

Forge 模块 - X.509

  1. var pki = forge.pki;
  2. // 将 PEM 格式的公钥转换为 Forge 公钥
  3. var publicKey = pki.publicKeyFromPem(pem);
  4. // 将 Forge 公钥转换为 PEM 格式的公钥
  5. var pem = pki.publicKeyToPem(publicKey);
  6. // convert an ASN.1 SubjectPublicKeyInfo to a Forge public key
  7. var publicKey = pki.publicKeyFromAsn1(subjectPublicKeyInfo);
  8. // convert a Forge public key to an ASN.1 SubjectPublicKeyInfo
  9. var subjectPublicKeyInfo = pki.publicKeyToAsn1(publicKey);
  10. // gets a SHA-1 RSAPublicKey fingerprint a byte buffer
  11. // 获取 RSA 公钥的 SHA-1 指纹,Byte buffer 格式
  12. pki.getPublicKeyFingerprint(key);
  13. // gets a SHA-1 SubjectPublicKeyInfo fingerprint a byte buffer
  14. pki.getPublicKeyFingerprint(key, {type: 'SubjectPublicKeyInfo'});
  15. // gets a hex-encoded, colon-delimited SHA-1 RSAPublicKey public key fingerprint
  16. // 获取以十六进制编码,冒号分隔的 SHA-1 RSAPublicKey 公钥指纹
  17. pki.getPublicKeyFingerprint(key, {encoding: 'hex', delimiter: ':'});
  18. // gets a hex-encoded, colon-delimited SHA-1 SubjectPublicKeyInfo public key fingerprint
  19. pki.getPublicKeyFingerprint(key, {
  20. type: 'SubjectPublicKeyInfo',
  21. encoding: 'hex',
  22. delimiter: ':'
  23. });
  24. // gets a hex-encoded, colon-delimited MD5 RSAPublicKey public key fingerprint
  25. // 获取十六进制编码,冒号分隔的 MD5 RSAPublicKey 公钥指纹
  26. pki.getPublicKeyFingerprint(key, {
  27. md: forge.md.md5.create(),
  28. encoding: 'hex',
  29. delimiter: ':'
  30. });
  31. // creates a CA store
  32. // 创建一个 CA 仓库
  33. var caStore = pki.createCaStore([/* PEM-encoded cert */, ...]);
  34. // add a certificate to the CA store
  35. // 添加一张证书到 CA 仓库
  36. caStore.addCertificate(certObjectOrPemString);
  37. // gets the issuer (its certificate) for the given certificate
  38. // 获取给定证书的颁发者(其证书)
  39. var issuerCert = caStore.getIssuer(subjectCert);
  40. // verifies a certificate chain against a CA store
  41. // 根据 CA 仓库验证证书链
  42. pki.verifyCertificateChain(caStore, chain, customVerifyCallback);
  43. // signs a certificate using the given private key
  44. // 使用给定的私钥为证书签名
  45. cert.sign(privateKey);
  46. // signs a certificate using SHA-256 instead of SHA-1
  47. // 使用 SHA-256 而不是 SHA-1 为证书签名
  48. cert.sign(privateKey, forge.md.sha256.create());
  49. // verifies an issued certificate using the certificates public key
  50. // 使用证书公钥验证已颁发的证书
  51. var verified = issuer.verify(issued);
  52. // generate a keypair and create an X.509v3 certificate
  53. // 生成密钥对并创建 X.509v3 证书
  54. var keys = pki.rsa.generateKeyPair(2048);
  55. var cert = pki.createCertificate();
  56. cert.publicKey = keys.publicKey;
  57. // alternatively set public key from a csr
  58. // 或者通过 csr 设置公钥
  59. //cert.publicKey = csr.publicKey;
  60. // NOTE: serialNumber is the hex encoded value of an ASN.1 INTEGER.
  61. // 注意:serialNumber 是 ASN.1 INTEGER 的十六进制编码值。
  62. // Conforming CAs should ensure serialNumber is:
  63. // 符合要求的 CA 应确保 serialNumber 为:
  64. // - no more than 20 octets
  65. // - 不超过20个八位位组
  66. // - non-negative (prefix a '00' if your value starts with a '1' bit)
  67. // - 非负数(如果您的值以“ 1”开头,则前缀为“ 00”)
  68. cert.serialNumber = '01';
  69. cert.validity.notBefore = new Date();
  70. cert.validity.notAfter = new Date();
  71. cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 1);
  72. var attrs = [{
  73. name: 'commonName',
  74. value: 'example.org'
  75. }, {
  76. name: 'countryName',
  77. value: 'US'
  78. }, {
  79. shortName: 'ST',
  80. value: 'Virginia'
  81. }, {
  82. name: 'localityName',
  83. value: 'Blacksburg'
  84. }, {
  85. name: 'organizationName',
  86. value: 'Test'
  87. }, {
  88. shortName: 'OU',
  89. value: 'Test'
  90. }];
  91. cert.setSubject(attrs);
  92. // alternatively set subject from a csr
  93. // 或者通过 csr 设置主题
  94. //cert.setSubject(csr.subject.attributes);
  95. cert.setIssuer(attrs);
  96. // 证书扩展项
  97. cert.setExtensions([{
  98. name: 'basicConstraints',
  99. cA: true
  100. }, {
  101. name: 'keyUsage',
  102. keyCertSign: true,
  103. digitalSignature: true,
  104. nonRepudiation: true,
  105. keyEncipherment: true,
  106. dataEncipherment: true
  107. }, {
  108. name: 'extKeyUsage',
  109. serverAuth: true,
  110. clientAuth: true,
  111. codeSigning: true,
  112. emailProtection: true,
  113. timeStamping: true
  114. }, {
  115. name: 'nsCertType',
  116. client: true,
  117. server: true,
  118. email: true,
  119. objsign: true,
  120. sslCA: true,
  121. emailCA: true,
  122. objCA: true
  123. }, {
  124. name: 'subjectAltName',
  125. altNames: [{
  126. type: 6, // URI
  127. value: 'http://example.org/webid#me'
  128. }, {
  129. type: 7, // IP
  130. ip: '127.0.0.1'
  131. }]
  132. }, {
  133. name: 'subjectKeyIdentifier'
  134. }]);
  135. /* alternatively set extensions from a csr
  136. 或者通过 CSR 设置扩展项
  137. var extensions = csr.getAttribute({name: 'extensionRequest'}).extensions;
  138. // optionally add more extensions
  139. extensions.push.apply(extensions, [{
  140. name: 'basicConstraints',
  141. cA: true
  142. }, {
  143. name: 'keyUsage',
  144. keyCertSign: true,
  145. digitalSignature: true,
  146. nonRepudiation: true,
  147. keyEncipherment: true,
  148. dataEncipherment: true
  149. }]);
  150. cert.setExtensions(extensions);
  151. */
  152. // self-sign certificate
  153. // 自签名证书
  154. cert.sign(keys.privateKey);
  155. // convert a Forge certificate to PEM
  156. // 将 Forge 证书转换为 PEM 格式
  157. var pem = pki.certificateToPem(cert);
  158. // convert a Forge certificate from PEM
  159. // 将 PEM 格式证书转换为 Forge
  160. var cert = pki.certificateFromPem(pem);
  161. // convert an ASN.1 X.509x3 object to a Forge certificate
  162. var cert = pki.certificateFromAsn1(obj);
  163. // convert a Forge certificate to an ASN.1 X.509v3 object
  164. var asn1Cert = pki.certificateToAsn1(cert);