在线生成秘钥
- 非对称加密公钥私钥对
- 在线生成公私钥对
- RSA Key pair create
- 生成RSA密钥对
http://web.chacuo.net/netrsakeypair
RSA参考资料 https://blog.csdn.net/aihouti2211/article/details/101167013
const NodeRSA = require('node-rsa')
const BASE64 = 'base64'
const UTF8 = 'utf8'
const pkcsSize = 512
const str = '服务端测试 -> miaomiaomiao~~~'
demo()
function demo() {
pkcsType = 'pkcs8'//不为空则 设置为传入参数,为空则 设置为 pkcs8
// 1.创建RSA对象,并指定 秘钥长度
var key = new NodeRSA({ b: pkcsSize })
key.setOptions({ encryptionScheme: 'pkcs1' })//指定加密格式
// 2.生成 公钥私钥,使用 pkcs8标准,pem格式
var publicPem = key.exportKey(pkcsType+'-public-pem')//制定输出格式
var privatePem = key.exportKey(pkcsType + '-private-pem')
// console.log(key.$options)
console.log(pkcsType+'公钥:',publicPem)
console.log(pkcsType+'私钥:', privatePem)
//---------------------demo1:服务端私钥加密公钥解密----------------------
// 3.使用 私钥 加密 数据,并指定 字符编码 和 字符集
var encryData = key.encryptPrivate(str, BASE64, UTF8)
console.log('私钥加密后的数据:', encryData) //加密后数据为 base64 编码
// 4.使用 公钥 解密 数据,并指定字符集
var decryptData = key.decryptPublic(encryData, UTF8)
console.log('公钥解密后的数据:', decryptData)
//---------------------demo2:服务端加载公钥后解密----------------------
// 1.创建RSA对象,并指定 秘钥长度
var publicKey = new NodeRSA({ b: pkcsSize })
// 2.导入 公钥,并指定使用 pkcs标准,pem格式
publicKey.importKey(publicPem, pkcsType+'-public-pem')
// 3.使用 公钥 解密数据
var decrypted = publicKey.decryptPublic(encryData, UTF8)
console.log('使用公钥解密后的数据',decrypted)
//---------------------demo3:服务端使用私钥签名----------------------
// 1. 私钥
var privateKey = new NodeRSA({ b: pkcsSize })
// 2.导入 私钥,并指定使用 pkcs标准,pem格式
privateKey.importKey(privatePem, pkcsType+'-private-pem')
var signedData = privateKey.sign(Buffer.from(str), BASE64).toString(BASE64)
console.log('\n使用私钥签名:', signedData)
//---------------------demo4:服务端使用公钥验证签名----------------------
var result = publicKey.verify(Buffer.from(str), signedData, 'Buffer', BASE64)
console.log('验证签名结果', result)
}
key的格式
- pkcs1格式:
- ——-BEGIN RSA PRIVATE KEY——-
- ——-END RSA PRIVATE KEY———
- ——-BEGIN RSA PRIVATE KEY——-
- pkcs8格式:
- ——-BEGIN PRIVATE KEY——-
- ——-END PRIVATE KEY——
pub.key
非对称加密公钥,用txt记事本,将下面加密字符串存为 pub.key
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCoesjh94ijH7jHcgyIEcj9JaJq
rNGVNq/sOoYdBD9t21hUZdTdfGQ2jQi62rFXLDvmHlrWdSO1InNZ0UWeWtLIpD7F
+aiKtjidVbATIh4ZONzOHyXUE/xO2L1mtssoNFP/wtyAAgBsw27Wun9jyHq5nyt2
+7S7uqH6tvkD7LBdcwIDAQAB
-----END PUBLIC KEY-----
pri.key
非对称加密私钥,用txt记事本,将下面加密字符串存为 pri.key
-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKh6yOH3iKMfuMdy
DIgRyP0lomqs0ZU2r+w6hh0EP23bWFRl1N18ZDaNCLrasVcsO+YeWtZ1I7Uic1nR
RZ5a0sikPsX5qIq2OJ1VsBMiHhk43M4fJdQT/E7YvWa2yyg0U//C3IACAGzDbta6
f2PIermfK3b7tLu6ofq2+QPssF1zAgMBAAECgYBYZeQUu94TSMeYzfxJQJumRyLK
udZVZhYz6hkIDHyDVX0o+y0O8P9bp/AWqjw2Mt1SxkZ/E4MivOqtC6JtjdXd2k9q
FnLiG1a7DqS75533pddTGdDEPqMwWKbE1KHJlSv6V/IrsY/n9PeyksPsrv+r+KTG
FHVQMWCC0/MTCwlb0QJBANbziZiUJOYiQLZ5pnL5V/iPM5+2iUg2sqpcvRNkd3yd
kgoiF46jWw4hbeGuoVf/HQwZWcJ7leJD2K50McXjwV8CQQDIp1sgrJT/NQ/D+h3q
I0lJICNTjjfBot1qG2oEymQDYsBrhVQgya3GwXqTxJGjgersE4nGl2FiYDdK3lDk
ffhtAkEAkA3cy/2UkQqpleEHNQx38WN/NG0vqc7GhDfsmx98mG49Xj8kzHob3ud2
bYYMKR4WyHIA3r7WXzIa+Cd05+tQPwJBAIzJF+BaFwTllxU7hgfFEGOVgBPdQnPD
sTUE3SNVWk0h2b7XQsrqltpQ4I+TqVgfDNTtdIr5piOfPMx0Ji/bzxUCQATRPvrd
0PObEhRTaeXmdPCFZhROtuyBkg85q/qZXwnKNvz1ivwi48DEDxGQXM2WINi2n78x
MxrbsZhZtTycXVE=
-----END PRIVATE KEY-----
pub.key报错
——-BEGIN RSA PRIVATE KEY——- ,替换为 ——-BEGIN PUBLIC KEY——-
node服务端加密
node-rsa
- github文档 https://github.com/rzcoder/node-rsa
- node-rsa加解密、签名以及验签
- RSA加密的好处
- 签名防止参数篡改
- 加密防止参数敏感信息泄漏
加密解密流程
双方都维护一套公私钥, 发送方(a,b)-> 接收方 (c,d)
a. 自己的私钥签名
b. 对方的公钥加密
c. 私钥解密
d. 公钥验证签名,参数是否被篡改 && 调用方是否是期望的
rsa/index.js
const NodeRSA = require('node-rsa')
const fs = require('fs')
// 公钥加密
export function encrypt(data) {
const publicKey = fs.readFileSync('./files/rsa.pub.key')
const nodersa = new NodeRSA(publicKey)
// 要加上是个配置,否则后端解密失败,不写setOptions,加密的结果是错误的
// 在node-rsa模块中加解密默认使用 pkcs1_oaep ,而在js中加密解密默认使用的是 pkcs1
nodersa.setOptions({ encryptionScheme: 'pkcs1' })
const encrypted = nodersa.encrypt(data, 'base64')
return encrypted
}
// 私钥解密
export function decrypt(data) {
const privateKey = fs.readFileSync('./files/rsa.pri.key')
const nodersa = new NodeRSA(privateKey)
const decrypted = nodersa.decrypt(data, 'utf8')
return decrypted
}
使用
import { encrypt, decrypt} from './rsa/index.js'
const data = { name: 'owen', age: 20 }
// 加密
const encrypted = encrypt(data)
console.log('encrypted:', encrypted)
// 解密
const decrypted = decrypt(encrypted)
console.log('decrypted:', decrypted)
pscs1
RSA是一种块加密的算法,所以对于明文需要将他们分成固定的块长度,考虑到输入的数据长度的问题:
所以加解密的填充有好几种:
无填充,就是直接对明文进行加密
PKCS1。将数据长度分成密钥长度-11byte,比如密钥是1024bit,那么长度就是1024/8-11=117bytes,具体的格式:先填0,2,然后随机生成其他的byte,后面才是真正的数据
PKCS1_OAEP将数据长度分成密钥长度-41byte,比如密钥是1024bit,那么长度就是1024/8-41=77bytes,先填0,随机或者是固定的测试向量加20个bytes,然后加20个数字签名的数据,最后才是数据
SSLV23,将数据长度分成密钥长度-11byte,比如密钥是1024bit,那么长度就是1024/8-11=117bytes,具体的格式:先填0,2,填入8个3,填入一个’\0’,最后才是真正的数据
react前端POST加密
const NodeRSA = require('node-rsa')
// 公钥加密
export function encrypt(data) {
const publicKey = `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCoesjh94ijH7jHcgyIEcj9JaJq
rNGVNq/sOoYdBD9t21hUZdTdfGQ2jQi62rFXLDvmHlrWdSO1InNZ0UWeWtLIpD7F
+aiKtjidVbATIh4ZONzOHyXUE/xO2L1mtssoNFP/wtyAAgBsw27Wun9jyHq5nyt2
+7S7uqH6tvkD7LBdcwIDAQAB
-----END PUBLIC KEY-----`
const nodersa = new NodeRSA(publicKey)
const encrypted = nodersa.encrypt(data, 'base64')
return encrypted
}
// 私钥解密
export function decrypt(data) {
const privateKey = `-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKh6yOH3iKMfuMdy
DIgRyP0lomqs0ZU2r+w6hh0EP23bWFRl1N18ZDaNCLrasVcsO+YeWtZ1I7Uic1nR
RZ5a0sikPsX5qIq2OJ1VsBMiHhk43M4fJdQT/E7YvWa2yyg0U//C3IACAGzDbta6
f2PIermfK3b7tLu6ofq2+QPssF1zAgMBAAECgYBYZeQUu94TSMeYzfxJQJumRyLK
udZVZhYz6hkIDHyDVX0o+y0O8P9bp/AWqjw2Mt1SxkZ/E4MivOqtC6JtjdXd2k9q
FnLiG1a7DqS75533pddTGdDEPqMwWKbE1KHJlSv6V/IrsY/n9PeyksPsrv+r+KTG
FHVQMWCC0/MTCwlb0QJBANbziZiUJOYiQLZ5pnL5V/iPM5+2iUg2sqpcvRNkd3yd
kgoiF46jWw4hbeGuoVf/HQwZWcJ7leJD2K50McXjwV8CQQDIp1sgrJT/NQ/D+h3q
I0lJICNTjjfBot1qG2oEymQDYsBrhVQgya3GwXqTxJGjgersE4nGl2FiYDdK3lDk
ffhtAkEAkA3cy/2UkQqpleEHNQx38WN/NG0vqc7GhDfsmx98mG49Xj8kzHob3ud2
bYYMKR4WyHIA3r7WXzIa+Cd05+tQPwJBAIzJF+BaFwTllxU7hgfFEGOVgBPdQnPD
sTUE3SNVWk0h2b7XQsrqltpQ4I+TqVgfDNTtdIr5piOfPMx0Ji/bzxUCQATRPvrd
0PObEhRTaeXmdPCFZhROtuyBkg85q/qZXwnKNvz1ivwi48DEDxGQXM2WINi2n78x
MxrbsZhZtTycXVE=
-----END PRIVATE KEY-----`
const nodersa = new NodeRSA(privateKey)
const decrypted = nodersa.decrypt(data, 'utf8')
return decrypted
}
node-rsa错误
react npm run build node-rsa 1.1.1 版本会报错,版本降级为 “node-rsa”: “1.0.5”
Failed to minify the code from this file
./node_modules/node-rsa/src/formats/openssh.js
后端无法解密的错误
- 原因:因为加密标准:“RSA/ECB/PKCS1Padding” 与’RSA”不一样 ```jsx // Android中应该使用这个标准 Cipher cipher = Cipher.getInstance(“RSA/ECB/PKCS1Padding”)
// 服务端使用这个标准 Cipher cipher = Cipher.getInstance(“RSA”) ```
- 前端RSA加密后的Base64位的密文,在后端接收到时,字符”+”被转为了空格,导致无法解密成功
- 解决: 后端解密之前先做一次字符替换,将空格转回”+”,再进行解密