在线生成秘钥

  1. 非对称加密公钥私钥对
  2. 在线生成公私钥对
  3. RSA Key pair create
  4. 生成RSA密钥对

http://web.chacuo.net/netrsakeypair
image.png

RSA参考资料 https://blog.csdn.net/aihouti2211/article/details/101167013

  1. const NodeRSA = require('node-rsa')
  2. const BASE64 = 'base64'
  3. const UTF8 = 'utf8'
  4. const pkcsSize = 512
  5. const str = '服务端测试 -> miaomiaomiao~~~'
  6. demo()
  7. function demo() {
  8. pkcsType = 'pkcs8'//不为空则 设置为传入参数,为空则 设置为 pkcs8
  9. // 1.创建RSA对象,并指定 秘钥长度
  10. var key = new NodeRSA({ b: pkcsSize })
  11. key.setOptions({ encryptionScheme: 'pkcs1' })//指定加密格式
  12. // 2.生成 公钥私钥,使用 pkcs8标准,pem格式
  13. var publicPem = key.exportKey(pkcsType+'-public-pem')//制定输出格式
  14. var privatePem = key.exportKey(pkcsType + '-private-pem')
  15. // console.log(key.$options)
  16. console.log(pkcsType+'公钥:',publicPem)
  17. console.log(pkcsType+'私钥:', privatePem)
  18. //---------------------demo1:服务端私钥加密公钥解密----------------------
  19. // 3.使用 私钥 加密 数据,并指定 字符编码 和 字符集
  20. var encryData = key.encryptPrivate(str, BASE64, UTF8)
  21. console.log('私钥加密后的数据:', encryData) //加密后数据为 base64 编码
  22. // 4.使用 公钥 解密 数据,并指定字符集
  23. var decryptData = key.decryptPublic(encryData, UTF8)
  24. console.log('公钥解密后的数据:', decryptData)
  25. //---------------------demo2:服务端加载公钥后解密----------------------
  26. // 1.创建RSA对象,并指定 秘钥长度
  27. var publicKey = new NodeRSA({ b: pkcsSize })
  28. // 2.导入 公钥,并指定使用 pkcs标准,pem格式
  29. publicKey.importKey(publicPem, pkcsType+'-public-pem')
  30. // 3.使用 公钥 解密数据
  31. var decrypted = publicKey.decryptPublic(encryData, UTF8)
  32. console.log('使用公钥解密后的数据',decrypted)
  33. //---------------------demo3:服务端使用私钥签名----------------------
  34. // 1. 私钥
  35. var privateKey = new NodeRSA({ b: pkcsSize })
  36. // 2.导入 私钥,并指定使用 pkcs标准,pem格式
  37. privateKey.importKey(privatePem, pkcsType+'-private-pem')
  38. var signedData = privateKey.sign(Buffer.from(str), BASE64).toString(BASE64)
  39. console.log('\n使用私钥签名:', signedData)
  40. //---------------------demo4:服务端使用公钥验证签名----------------------
  41. var result = publicKey.verify(Buffer.from(str), signedData, 'Buffer', BASE64)
  42. console.log('验证签名结果', result)
  43. }

key的格式

  1. pkcs1格式:
    • ——-BEGIN RSA PRIVATE KEY——-
    • ——-END RSA PRIVATE KEY———
  2. pkcs8格式:
    • ——-BEGIN PRIVATE KEY——-
    • ——-END PRIVATE KEY——

pub.key

非对称加密公钥,用txt记事本,将下面加密字符串存为 pub.key

  1. -----BEGIN PUBLIC KEY-----
  2. MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCoesjh94ijH7jHcgyIEcj9JaJq
  3. rNGVNq/sOoYdBD9t21hUZdTdfGQ2jQi62rFXLDvmHlrWdSO1InNZ0UWeWtLIpD7F
  4. +aiKtjidVbATIh4ZONzOHyXUE/xO2L1mtssoNFP/wtyAAgBsw27Wun9jyHq5nyt2
  5. +7S7uqH6tvkD7LBdcwIDAQAB
  6. -----END PUBLIC KEY-----

pri.key

非对称加密私钥,用txt记事本,将下面加密字符串存为 pri.key

  1. -----BEGIN PRIVATE KEY-----
  2. MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKh6yOH3iKMfuMdy
  3. DIgRyP0lomqs0ZU2r+w6hh0EP23bWFRl1N18ZDaNCLrasVcsO+YeWtZ1I7Uic1nR
  4. RZ5a0sikPsX5qIq2OJ1VsBMiHhk43M4fJdQT/E7YvWa2yyg0U//C3IACAGzDbta6
  5. f2PIermfK3b7tLu6ofq2+QPssF1zAgMBAAECgYBYZeQUu94TSMeYzfxJQJumRyLK
  6. udZVZhYz6hkIDHyDVX0o+y0O8P9bp/AWqjw2Mt1SxkZ/E4MivOqtC6JtjdXd2k9q
  7. FnLiG1a7DqS75533pddTGdDEPqMwWKbE1KHJlSv6V/IrsY/n9PeyksPsrv+r+KTG
  8. FHVQMWCC0/MTCwlb0QJBANbziZiUJOYiQLZ5pnL5V/iPM5+2iUg2sqpcvRNkd3yd
  9. kgoiF46jWw4hbeGuoVf/HQwZWcJ7leJD2K50McXjwV8CQQDIp1sgrJT/NQ/D+h3q
  10. I0lJICNTjjfBot1qG2oEymQDYsBrhVQgya3GwXqTxJGjgersE4nGl2FiYDdK3lDk
  11. ffhtAkEAkA3cy/2UkQqpleEHNQx38WN/NG0vqc7GhDfsmx98mG49Xj8kzHob3ud2
  12. bYYMKR4WyHIA3r7WXzIa+Cd05+tQPwJBAIzJF+BaFwTllxU7hgfFEGOVgBPdQnPD
  13. sTUE3SNVWk0h2b7XQsrqltpQ4I+TqVgfDNTtdIr5piOfPMx0Ji/bzxUCQATRPvrd
  14. 0PObEhRTaeXmdPCFZhROtuyBkg85q/qZXwnKNvz1ivwi48DEDxGQXM2WINi2n78x
  15. MxrbsZhZtTycXVE=
  16. -----END PRIVATE KEY-----

pub.key报错

——-BEGIN RSA PRIVATE KEY——- ,替换为 ——-BEGIN PUBLIC KEY——-

node服务端加密

node-rsa

  1. github文档 https://github.com/rzcoder/node-rsa
  2. node-rsa加解密、签名以及验签
  3. RSA加密的好处
    1. 签名防止参数篡改
    2. 加密防止参数敏感信息泄漏


加密解密流程

双方都维护一套公私钥, 发送方(a,b)-> 接收方 (c,d)
a. 自己的私钥签名
b. 对方的公钥加密
c. 私钥解密
d. 公钥验证签名,参数是否被篡改 && 调用方是否是期望的

rsa/index.js

  1. const NodeRSA = require('node-rsa')
  2. const fs = require('fs')
  3. // 公钥加密
  4. export function encrypt(data) {
  5. const publicKey = fs.readFileSync('./files/rsa.pub.key')
  6. const nodersa = new NodeRSA(publicKey)
  7. // 要加上是个配置,否则后端解密失败,不写setOptions,加密的结果是错误的
  8. // 在node-rsa模块中加解密默认使用 pkcs1_oaep ,而在js中加密解密默认使用的是 pkcs1
  9. nodersa.setOptions({ encryptionScheme: 'pkcs1' })
  10. const encrypted = nodersa.encrypt(data, 'base64')
  11. return encrypted
  12. }
  13. // 私钥解密
  14. export function decrypt(data) {
  15. const privateKey = fs.readFileSync('./files/rsa.pri.key')
  16. const nodersa = new NodeRSA(privateKey)
  17. const decrypted = nodersa.decrypt(data, 'utf8')
  18. return decrypted
  19. }

使用

  1. import { encrypt, decrypt} from './rsa/index.js'
  2. const data = { name: 'owen', age: 20 }
  3. // 加密
  4. const encrypted = encrypt(data)
  5. console.log('encrypted:', encrypted)
  6. // 解密
  7. const decrypted = decrypt(encrypted)
  8. console.log('decrypted:', decrypted)

pscs1

RSA是一种块加密的算法,所以对于明文需要将他们分成固定的块长度,考虑到输入的数据长度的问题:
所以加解密的填充有好几种:

  1. 无填充,就是直接对明文进行加密

  2. PKCS1。将数据长度分成密钥长度-11byte,比如密钥是1024bit,那么长度就是1024/8-11=117bytes,具体的格式:先填0,2,然后随机生成其他的byte,后面才是真正的数据

  3. PKCS1_OAEP将数据长度分成密钥长度-41byte,比如密钥是1024bit,那么长度就是1024/8-41=77bytes,先填0,随机或者是固定的测试向量加20个bytes,然后加20个数字签名的数据,最后才是数据

  4. SSLV23,将数据长度分成密钥长度-11byte,比如密钥是1024bit,那么长度就是1024/8-11=117bytes,具体的格式:先填0,2,填入8个3,填入一个’\0’,最后才是真正的数据

react前端POST加密

  1. const NodeRSA = require('node-rsa')
  2. // 公钥加密
  3. export function encrypt(data) {
  4. const publicKey = `-----BEGIN PUBLIC KEY-----
  5. MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCoesjh94ijH7jHcgyIEcj9JaJq
  6. rNGVNq/sOoYdBD9t21hUZdTdfGQ2jQi62rFXLDvmHlrWdSO1InNZ0UWeWtLIpD7F
  7. +aiKtjidVbATIh4ZONzOHyXUE/xO2L1mtssoNFP/wtyAAgBsw27Wun9jyHq5nyt2
  8. +7S7uqH6tvkD7LBdcwIDAQAB
  9. -----END PUBLIC KEY-----`
  10. const nodersa = new NodeRSA(publicKey)
  11. const encrypted = nodersa.encrypt(data, 'base64')
  12. return encrypted
  13. }
  14. // 私钥解密
  15. export function decrypt(data) {
  16. const privateKey = `-----BEGIN PRIVATE KEY-----
  17. MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKh6yOH3iKMfuMdy
  18. DIgRyP0lomqs0ZU2r+w6hh0EP23bWFRl1N18ZDaNCLrasVcsO+YeWtZ1I7Uic1nR
  19. RZ5a0sikPsX5qIq2OJ1VsBMiHhk43M4fJdQT/E7YvWa2yyg0U//C3IACAGzDbta6
  20. f2PIermfK3b7tLu6ofq2+QPssF1zAgMBAAECgYBYZeQUu94TSMeYzfxJQJumRyLK
  21. udZVZhYz6hkIDHyDVX0o+y0O8P9bp/AWqjw2Mt1SxkZ/E4MivOqtC6JtjdXd2k9q
  22. FnLiG1a7DqS75533pddTGdDEPqMwWKbE1KHJlSv6V/IrsY/n9PeyksPsrv+r+KTG
  23. FHVQMWCC0/MTCwlb0QJBANbziZiUJOYiQLZ5pnL5V/iPM5+2iUg2sqpcvRNkd3yd
  24. kgoiF46jWw4hbeGuoVf/HQwZWcJ7leJD2K50McXjwV8CQQDIp1sgrJT/NQ/D+h3q
  25. I0lJICNTjjfBot1qG2oEymQDYsBrhVQgya3GwXqTxJGjgersE4nGl2FiYDdK3lDk
  26. ffhtAkEAkA3cy/2UkQqpleEHNQx38WN/NG0vqc7GhDfsmx98mG49Xj8kzHob3ud2
  27. bYYMKR4WyHIA3r7WXzIa+Cd05+tQPwJBAIzJF+BaFwTllxU7hgfFEGOVgBPdQnPD
  28. sTUE3SNVWk0h2b7XQsrqltpQ4I+TqVgfDNTtdIr5piOfPMx0Ji/bzxUCQATRPvrd
  29. 0PObEhRTaeXmdPCFZhROtuyBkg85q/qZXwnKNvz1ivwi48DEDxGQXM2WINi2n78x
  30. MxrbsZhZtTycXVE=
  31. -----END PRIVATE KEY-----`
  32. const nodersa = new NodeRSA(privateKey)
  33. const decrypted = nodersa.decrypt(data, 'utf8')
  34. return decrypted
  35. }

node-rsa错误

react npm run build node-rsa 1.1.1 版本会报错,版本降级为 “node-rsa”: “1.0.5”

  1. Failed to minify the code from this file
  2. ./node_modules/node-rsa/src/formats/openssh.js

后端无法解密的错误

  1. 原因:因为加密标准:“RSA/ECB/PKCS1Padding” 与’RSA”不一样 ```jsx // Android中应该使用这个标准 Cipher cipher = Cipher.getInstance(“RSA/ECB/PKCS1Padding”)

// 服务端使用这个标准 Cipher cipher = Cipher.getInstance(“RSA”) ```

  1. 前端RSA加密后的Base64位的密文,在后端接收到时,字符”+”被转为了空格,导致无法解密成功
    1. 解决: 后端解密之前先做一次字符替换,将空格转回”+”,再进行解密