
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
browser-rsa
Advanced tools
纯 js 实现 rsa,无第三方依赖,适用于某些环境无 crypto 场景。比如:微信小程序。
支持: 私钥加密 -> 公钥解密 公钥加密 -> 私钥解密
生成私钥
➜ openssl genrsa -out key1.pem 512
➜ cat key1.pem
-----BEGIN RSA PRIVATE KEY-----
MIIBOwIBAAJBAKBKx4EJPI9rjYV1nfyPjdOZoeyHVxbYwrRLkxyNRoRGYRPmaShJ
Zd0dGlMw1Cm70BCpzz0iswMyJIj88yoVg18CAwEAAQJAPUwbewbzN81jc1QFNJ4Z
GIA54d/nt/7whk4YVeTYwKAmYJ7nXV1G9rioQ2CUb0MuBOVBgZaPdKNT+3bkbrEb
kQIhANEpPGOruTbTSbWIlTNxRxZvsPT/kUKeraNpBT6k2rBrAiEAxC/8/DBAysAz
yilUg+V3OY54czTtA1la7KLpI91TZd0CIQC16K0y6lkNS7mhfoZ01SJEayN2EQee
7y6JHn+HOg1QvQIhAJz0Q3JC7GMIt6ZBwIKw/txGNej9a6zlPM/aWai+tazlAiA0
w9ttPRc/TukSp8fHZBzWdszSU5SO/IwTKVmeLmnC0g==
-----END RSA PRIVATE KEY-----
从私钥生成公钥
➜ openssl rsa -in key1.pem -pubout -out pubkey.pem
➜ cat pubkey.pem
-----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKBKx4EJPI9rjYV1nfyPjdOZoeyHVxbY
wrRLkxyNRoRGYRPmaShJZd0dGlMw1Cm70BCpzz0iswMyJIj88yoVg18CAwEAAQ==
-----END PUBLIC KEY-----
npm install browser-rsa
RSA
import BrowserRsa from 'browser-rsa'
import utils from 'browser-rsa/lib/utils.js'
const pubkey = `MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKBKx4EJPI9rjYV1nfyPjdOZoeyHVxbY
wrRLkxyNRoRGYRPmaShJZd0dGlMw1Cm70BCpzz0iswMyJIj88yoVg18CAwEAAQ==`
const privateKey = `MIIBOwIBAAJBAKBKx4EJPI9rjYV1nfyPjdOZoeyHVxbYwrRLkxyNRoRGYRPmaShJ
Zd0dGlMw1Cm70BCpzz0iswMyJIj88yoVg18CAwEAAQJAPUwbewbzN81jc1QFNJ4Z
GIA54d/nt/7whk4YVeTYwKAmYJ7nXV1G9rioQ2CUb0MuBOVBgZaPdKNT+3bkbrEb
kQIhANEpPGOruTbTSbWIlTNxRxZvsPT/kUKeraNpBT6k2rBrAiEAxC/8/DBAysAz
yilUg+V3OY54czTtA1la7KLpI91TZd0CIQC16K0y6lkNS7mhfoZ01SJEayN2EQee
7y6JHn+HOg1QvQIhAJz0Q3JC7GMIt6ZBwIKw/txGNej9a6zlPM/aWai+tazlAiA0
w9ttPRc/TukSp8fHZBzWdszSU5SO/IwTKVmeLmnC0g==`
const rsa = new BrowserRsa()
// 设置 key,二选一
rsa.setPublicKey(pubkey)
rsa.setPrivateKey(privateKey)
const str = 'hello world'
const pStr = rsa.publicEncrypt(str)
const pdStr = rsa.privateDecrypt(pStr)
console.log(str == pdStr, pStr)
AES-CTR,对称加密的工具类
import BrowserAesCtr from 'browser-rsa/BrowserAesCtr.js'
import utils from 'browser-rsa/lib/utils.js';
const text = "测试文本🧰"
const counter = new Uint8Array([191, 167, 0, 170, 152, 141, 171, 32, 5, 69, 177, 137, 21, 204, 229, 225]); // set random initialisation vector
const key = new Uint8Array([87, 219, 91, 67, 114, 196, 219, 8, 184, 193, 91, 186, 139, 33, 7, 212])
// 内部 counter 会自增
let aesCtr = new BrowserAesCtr(key, counter)
const encrypt = aesCtr.encrypt(text)
aesCtr = new BrowserAesCtr(key, counter)
const decrypt = aesCtr.decrypt(encrypt)
console.log(text == utils.utf8.fromByteArray(decrypt))
RSA
class BrowserRsa {
/**
* @param {String} padding rsa padding, support RSA_PKCS1_PADDING and RSA_PKCS1_OAEP_PADDING, default is RSA_PKCS1_OAEP_PADDING
* padding set only for : private key decrypt, public key encrypt
* private key encrypt, public key decrypt is use RSA_PKCS1_PADDING
*/
constructor(padding)
setPublicKey(base64str)
/**
* https://crypto.stackexchange.com/questions/21102/what-is-the-ssl-private-key-file-format
* @param {String} base64str
*/
setPrivateKey(base64str)
/**
* @param {String} str
* @param {String} resultEncoding return encoding, array, base64 or hex, default base64
* @returns {String|Array}
*/
publicEncrypt(str, resultEncoding = 'base64')
/**
*
* @param {String} ctext hex or base64
* @param {String} encoding ctext encoding, array, base64 or hex, default base64
* @param {String} resultEncoding return encoding, array or utf8 default utf8
* @returns {String|Array}
*/
publicDecrypt(ctext, encoding = 'base64', resultEncoding)
/**
* @param {String} str
* @param {String} resultEncoding return encoding, array, base64 or hex, default base64
* @returns {String|Array}
*/
privateEncrypt(str, resultEncoding = 'base64')
/**
*
* @param {String} ctext hex or base64
* @param {Boolean} encoding ctext encoding, array, base64 or hex, default base64
* @param {Boolean} resultEncoding return encoding, array or utf8 default utf8
* @returns {String|Array}
*/
privateDecrypt(str, encoding = 'base64', resultEncoding)
}
AES
class BrowserAesCtr {
/**
*
* @param {Uint8Array|Array} key
* @param {Uint8Array|Array} counter
*/
constructor(key, counter)
/**
*
* @param {Array|String} data
* @returns {Uint8Array}
*/
encrypt(data)
/**
*
* @param {Array|String} data if string, must be base64
* @returns {Uint8Array}
*/
decrypt(data)
}
utils 工具类
import utils from "browser-rsa/lib/utils";
// base64 处理
utils.base64.encode // 支持 utf8 字符集。(TextEncoder + btoa)
utils.base64.decode // 支持 utf8 字符集。(TextDecoder + atob)
utils.base64.fromHex
utils.base64.toHex
utils.base64.toByteArray
utils.base64.fromByteArray
utils.base64.fromBase64Url
utils.base64.toBase64Url
utils.hex.toByteArray
utils.hex.fromByteArray
// 同 TextEncoder.encode
utils.utf8.toByteArray
// 同 TextDecoder.decode
utils.utf8.fromByteArray
// 生成随机数
utils.random.nextByte()
utils.random.nextBytes(arr)
RSA 算法基于:http://www-cs-students.stanford.edu/~tjw/jsbn/
简单说下密钥解析。
RSAPrivateKey ::= SEQUENCE {
version Version,
modulus INTEGER, -- n
publicExponent INTEGER, -- e
privateExponent INTEGER, -- d
prime1 INTEGER, -- p
prime2 INTEGER, -- q
exponent1 INTEGER, -- d mod (p-1)
exponent2 INTEGER, -- d mod (q-1)
coefficient INTEGER -- (inverse of q) mod p
}
(n、d):私钥,这个我们要私密保存。
(n、e):公钥,可以对外公布。
n:模数(Modulus),私钥和公钥都包含有这个数。
e:公钥指数(publicExponent),一般是固定值65537。
d:私钥指数(privateExponent)。
密钥是使用 ASN.1 编码 ,然后再 base64。
用如下命令,可以解析出上面的格式。
➜ openssl rsa -in key1.pem -text -noout
RSA Private-Key: (512 bit)
modulus:
00:cf:14:0d:20:e3:fc:79:2f:42:b1:e2:0e:ea:26:
fb:e4:4a:1e:ab:7e:3c:56:41:a9:ae:fa:43:b2:17:
16:7c:55:c9:38:03:0f:9b:7d:68:c9:e2:7a:55:be:
95:80:f9:41:f9:13:62:48:fe:f3:d4:44:00:a2:32:
a7:ac:5b:2d:fd
publicExponent: 65537 (0x10001)
privateExponent:
02:ba:11:de:30:02:60:1a:26:37:af:71:60:d5:f8:
95:2e:00:af:63:6f:29:f7:9d:63:67:7a:42:bb:19:
19:b4:05:6c:4a:b2:32:c7:cb:62:41:ed:fe:b0:79:
37:61:15:1d:1d:84:f9:e5:ca:96:6a:d0:e3:13:10:
35:57:ef:a1
prime1:
00:ed:1b:8a:fb:c5:a2:fe:b2:5e:53:84:dc:fc:f3:
4a:2b:5e:f7:ac:6e:fc:6a:aa:e6:f5:52:fa:38:7e:
0d:54:19
prime2:
00:df:93:fa:c0:0a:a8:3b:cc:f7:78:35:4d:99:c8:
a0:68:1e:84:b1:93:2e:97:56:a1:2e:58:6e:56:bc:
5a:05:85
exponent1:
20:91:89:f3:af:60:06:30:25:f8:be:e5:43:f1:7f:
1c:99:fc:d7:38:9f:7f:5f:5e:3e:10:59:c2:6c:be:
13:f1
exponent2:
31:19:f5:b2:e1:64:4b:25:db:9f:89:cd:4e:1d:d2:
a4:ab:37:27:2c:94:c9:e5:db:a6:2b:03:a8:86:db:
1a:65
coefficient:
20:22:85:e8:ca:e1:ce:fa:b8:c8:fc:ed:05:4e:16:
a9:8f:51:c6:c0:60:50:15:72:56:b2:e6:88:3e:20:
4f:05
解析过程只需要用 js 实现,然后再加上 jsbn 就组成了 RSA 加密、解密。
FAQs
pure js rsa, rsa for browser, 微信小程序 rsa
The npm package browser-rsa receives a total of 2 weekly downloads. As such, browser-rsa popularity was classified as not popular.
We found that browser-rsa demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.