npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

seededrsa

v1.1.1

Published

This is a simple lib that takes a bip39 seed phrase and generates a rsa key from it. This is useful in certain situations where you need to be able to restore a rsa key. It also contains a seeded random number generator that should pass all uniformity tes

Downloads

5

Readme

SeededRSA

The inspiration for this came from a project I was doing research for. In this project I was wanting to use ipfs in combination with orbitdb for a dapp(decentralized application). IPFS uses 2048 bit rsa keys for the peerid and orbitdb uses secp256k1 for read/write access in the db. In the cryptocurrency community we are used to using bip39 seed phrases to make backing up or restoring a bitcoin(or other cryptocurrency) wallet much easier. For my application I wanted an easy way for a user to restore their peerid and secp256k1 keys on another device while avoiding unnecessary overhead(like storing encrypted keys that were previously generated). Instead with this a user can simply restore their RSA key using a bip39 phrase when/if needed.

Most of rsa.js was taken from jsencrypt/cryptico which has been in the wild for years. I did research and wasn't able to find any security complaints regarding their implementation of the rsa keys so I felt safe in using that implementation. Cryptico uses a seeded rng and replaces the global Math.random() with that RNG. This means that any calls to Math.random() after using it are deterministic. This package uses it's own PRNG.

The rng was basically the product of this comment on stackoverflow regarding seeded random generators. It uses MurmurHash3's hashing function as a seed for the scf32 prng from pactrand. Right now it only tests for 8 bit but can be tested for any size that practrand supports. After a little while I realized there may be people that would need to use the RSA or RNG without having a valid bip39 seed. The rng can now accept a string of any size, including 0, and still work. If the supplied string is a valid bip39 seed it is coverted into the seed value and if not then I use a sha256 hash in place of the seed. It still passes all practrand tests. I will most likely move the RNG into a its own package

My goal here was to use existing implementations for both rsa and the rng to minimize the risk of me causing a dumbster fire of a situation. I still wouldn't trust this until it has been properly tested for randomness.

Install

npm install seededrsa

Example usage

const RSA = require("./rsa");
const seed = "praise you muffin lion enable neck grocery crumble super myself license ghost"
const key = new RSA(seed);
key.generateNew(2048).then(function(key) {
  console.log(key.privateKey)
  console.log(key.publicKey)
}).catch(function(error){
  console.error(error)
})

/*
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEA3NdzUHz53SeYrpoR1JXtx/IokPeMhMcNEp3HtB7DW3rTRImg
SlxPv2doHSbYOZ1eEGexmAeJ7ClySm8Icj1vgetNq1mNTfi07LXHO0lQvburYOcX
q1yk+OshdurWfoIa7tsiiregYF1cjGh9kdjUaI+x59OUW+s1pWS9sfhnDwaK/lyQ
TG6vCSiyXX3tktc0Sso+8xOMg41jX0OZayKWNc63K0CHtUlVvTNqQ3x7W1YM1wyH
rzOm8MqRF1behCva73F9M8f1+zo9aqmASSgxs7wGQyozit/F/I4gDKEnrW2+1b+z
OKwQP+lKypSEeanmkZj3H1k95R2uctoOkuBgjQIDBlU3AoIBAEoVNIls76hBbflj
r8XsrxO/jBtJIp0vsRHFWbE0QHgl8VNS7fhV/PzgxR/cCJLRG/Ny5j4mnT0gNhxy
u62WAfPyEtLe+cwewmc73EdudPkDEBkCCwAHEYT7wuoBNN5UPm4916+kdKDQpcNN
LYk9mdZF3W/2j7kREKlAhAKsUz+yTA864w4iKKbVHnVAKSBMacfQI9FJ4rS/DwtE
SaE2IH4XO/CBm3jhnQ8kG0RHOssfVReWcnArdigmm4xJ8qGfE+BDzkLbvDbCRh3g
KIG1Tkr4tat5Q0eSkYJqV5fJ1igc97ARlBk3mBJ+aFHzV9Yn9eLWyeKonYHCtxDc
nuShjycCgYEA8o1va8Lg4e8m93UScRuQkwIup1CW+BlxYefIZTS9RQQ1CuBYQASU
9xOMN+RgJyRB+Kr7ACGmfpw9ASV7NNUF88aaUbx5HbEqXd18+5XEa4nbTqqjtCOH
rbSLYMTVClB1hTWqg2xwzbAcJ/rQeqlE9piVwV4MaOhIn9XgD0OBbrkCgYEA6RXf
BEpoLVjZYR8rbl6SIltMDINgFfS3D7uHOdQn+64b6Z2Hc25GZspqiwGbajoohHF2
pPGcqTOd+13rs6n40oAmHvO+8ygkipOtFKvR3blt27QlVZT6rtO34L38SJ+YvzVi
LgEMA/EQoaqWzWlH4O1/MTx3XlwZJdeJNRlr9nUCgYB8TtPcnLZHlLytM1Av8HWr
ZXAvscradmTPcWxg362lZtiamZqyfR8f7IjlJMe+Qz3BDfl7amVFxHA8chuSqm5F
n7ZAUeB089yrzAk1yWJkijEGkBYuGIMDWis9GLCK1QwOUcys4GcflUyxTOXst3qm
VY/h6RLOjYVadxycHSgkfwKBgBVT43uKpu5+7avz6aQDiKTVtBsc991UkMkHNOuO
R8Yr1wdWMl6D4525y+zCsy4CuYmnpcGz15GB7vgmH1ORnrc3SaCj72lNaTnP7OpK
36xXZU59/s5XrwfW6MVFcR0fbGdngF/7i86gqeyF+20Pe+GKXtOX1bP8Niu6OyDf
w9enAoGAU1rF0ty3hi6uJgG/4UPyZBeKlYJA1xqgXJrsSbD4UE3yMpn+MPGEZCr3
NfwNbc03UcrJoLva8mbspVz73udtR4SiecwD7o44S23+zn63w4NdEEQ8+KF2J1wT
XJqOG8nR/SfQHt/TH3ErQK4OfqEw/wExadhSZgCIUlpuULmi2MQ=
-----END RSA PRIVATE KEY-----

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3NdzUHz53SeYrpoR1JXt
x/IokPeMhMcNEp3HtB7DW3rTRImgSlxPv2doHSbYOZ1eEGexmAeJ7ClySm8Icj1v
getNq1mNTfi07LXHO0lQvburYOcXq1yk+OshdurWfoIa7tsiiregYF1cjGh9kdjU
aI+x59OUW+s1pWS9sfhnDwaK/lyQTG6vCSiyXX3tktc0Sso+8xOMg41jX0OZayKW
Nc63K0CHtUlVvTNqQ3x7W1YM1wyHrzOm8MqRF1behCva73F9M8f1+zo9aqmASSgx
s7wGQyozit/F/I4gDKEnrW2+1b+zOKwQP+lKypSEeanmkZj3H1k95R2uctoOkuBg
jQIDBlU3
-----END PUBLIC KEY-----
*/

Verifying the generated RSA Keys

I save the private and public keys from above to say key.pem(private) and key.pub(public). Then you can use openssl to verify them like this:

openssl rsa -in key.pem -check
RSA key ok
writing RSA key
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEA3NdzUHz53SeYrpoR1JXtx/IokPeMhMcNEp3HtB7DW3rTRImg
SlxPv2doHSbYOZ1eEGexmAeJ7ClySm8Icj1vgetNq1mNTfi07LXHO0lQvburYOcX
q1yk+OshdurWfoIa7tsiiregYF1cjGh9kdjUaI+x59OUW+s1pWS9sfhnDwaK/lyQ
TG6vCSiyXX3tktc0Sso+8xOMg41jX0OZayKWNc63K0CHtUlVvTNqQ3x7W1YM1wyH
rzOm8MqRF1behCva73F9M8f1+zo9aqmASSgxs7wGQyozit/F/I4gDKEnrW2+1b+z
OKwQP+lKypSEeanmkZj3H1k95R2uctoOkuBgjQIDBlU3AoIBAEoVNIls76hBbflj
r8XsrxO/jBtJIp0vsRHFWbE0QHgl8VNS7fhV/PzgxR/cCJLRG/Ny5j4mnT0gNhxy
u62WAfPyEtLe+cwewmc73EdudPkDEBkCCwAHEYT7wuoBNN5UPm4916+kdKDQpcNN
LYk9mdZF3W/2j7kREKlAhAKsUz+yTA864w4iKKbVHnVAKSBMacfQI9FJ4rS/DwtE
SaE2IH4XO/CBm3jhnQ8kG0RHOssfVReWcnArdigmm4xJ8qGfE+BDzkLbvDbCRh3g
KIG1Tkr4tat5Q0eSkYJqV5fJ1igc97ARlBk3mBJ+aFHzV9Yn9eLWyeKonYHCtxDc
nuShjycCgYEA8o1va8Lg4e8m93UScRuQkwIup1CW+BlxYefIZTS9RQQ1CuBYQASU
9xOMN+RgJyRB+Kr7ACGmfpw9ASV7NNUF88aaUbx5HbEqXd18+5XEa4nbTqqjtCOH
rbSLYMTVClB1hTWqg2xwzbAcJ/rQeqlE9piVwV4MaOhIn9XgD0OBbrkCgYEA6RXf
BEpoLVjZYR8rbl6SIltMDINgFfS3D7uHOdQn+64b6Z2Hc25GZspqiwGbajoohHF2
pPGcqTOd+13rs6n40oAmHvO+8ygkipOtFKvR3blt27QlVZT6rtO34L38SJ+YvzVi
LgEMA/EQoaqWzWlH4O1/MTx3XlwZJdeJNRlr9nUCgYB8TtPcnLZHlLytM1Av8HWr
ZXAvscradmTPcWxg362lZtiamZqyfR8f7IjlJMe+Qz3BDfl7amVFxHA8chuSqm5F
n7ZAUeB089yrzAk1yWJkijEGkBYuGIMDWis9GLCK1QwOUcys4GcflUyxTOXst3qm
VY/h6RLOjYVadxycHSgkfwKBgBVT43uKpu5+7avz6aQDiKTVtBsc991UkMkHNOuO
R8Yr1wdWMl6D4525y+zCsy4CuYmnpcGz15GB7vgmH1ORnrc3SaCj72lNaTnP7OpK
36xXZU59/s5XrwfW6MVFcR0fbGdngF/7i86gqeyF+20Pe+GKXtOX1bP8Niu6OyDf
w9enAoGAU1rF0ty3hi6uJgG/4UPyZBeKlYJA1xqgXJrsSbD4UE3yMpn+MPGEZCr3
NfwNbc03UcrJoLva8mbspVz73udtR4SiecwD7o44S23+zn63w4NdEEQ8+KF2J1wT
XJqOG8nR/SfQHt/TH3ErQK4OfqEw/wExadhSZgCIUlpuULmi2MQ=
-----END RSA PRIVATE KEY-----
openssl rsa -inform PEM -pubin -in key.pub -text -noout
Public-Key: (2048 bit)
Modulus:
    00:dc:d7:73:50:7c:f9:dd:27:98:ae:9a:11:d4:95:
    ed:c7:f2:28:90:f7:8c:84:c7:0d:12:9d:c7:b4:1e:
    c3:5b:7a:d3:44:89:a0:4a:5c:4f:bf:67:68:1d:26:
    d8:39:9d:5e:10:67:b1:98:07:89:ec:29:72:4a:6f:
    08:72:3d:6f:81:eb:4d:ab:59:8d:4d:f8:b4:ec:b5:
    c7:3b:49:50:bd:bb:ab:60:e7:17:ab:5c:a4:f8:eb:
    21:76:ea:d6:7e:82:1a:ee:db:22:8a:b7:a0:60:5d:
    5c:8c:68:7d:91:d8:d4:68:8f:b1:e7:d3:94:5b:eb:
    35:a5:64:bd:b1:f8:67:0f:06:8a:fe:5c:90:4c:6e:
    af:09:28:b2:5d:7d:ed:92:d7:34:4a:ca:3e:f3:13:
    8c:83:8d:63:5f:43:99:6b:22:96:35:ce:b7:2b:40:
    87:b5:49:55:bd:33:6a:43:7c:7b:5b:56:0c:d7:0c:
    87:af:33:a6:f0:ca:91:17:56:de:84:2b:da:ef:71:
    7d:33:c7:f5:fb:3a:3d:6a:a9:80:49:28:31:b3:bc:
    06:43:2a:33:8a:df:c5:fc:8e:20:0c:a1:27:ad:6d:
    be:d5:bf:b3:38:ac:10:3f:e9:4a:ca:94:84:79:a9:
    e6:91:98:f7:1f:59:3d:e5:1d:ae:72:da:0e:92:e0:
    60:8d
Exponent: 415031 (0x65537)

The keys generated are fully functional RSA keys.

Testing the RNG

I used practrand to test and will probably test with dieharder as well in the future. To run the test with practrand you will need a working installation first. The build process works on linux, mac and windows.

node test_rng.js |/path/to/practrand/RNG_test stdin8

sample output:

RNG_test using PractRand version 0.93
RNG = RNG_stdin8, seed = 0x3bb19275
test set = normal, folding = standard (8 bit)

rng=RNG_stdin8, seed=0x3bb19275
length= 4 megabytes (2^22 bytes), time= 2.3 seconds 
  no anomalies in 56 test result(s)

rng=RNG_stdin8, seed=0x3bb19275
length= 8 megabytes (2^23 bytes), time= 5.0 seconds 
  no anomalies in 60 test result(s)

rng=RNG_stdin8, seed=0x3bb19275
length= 16 megabytes (2^24 bytes), time= 9.9 seconds
  no anomalies in 66 test result(s)

rng=RNG_stdin8, seed=0x3bb19275
length= 32 megabytes (2^25 bytes), time= 19.1 seconds
  no anomalies in 72 test result(s)

rng=RNG_stdin8, seed=0x3bb19275
length= 64 megabytes (2^26 bytes), time= 38.2 seconds
  no anomalies in 76 test result(s)

rng=RNG_stdin8, seed=0x3bb19275
length= 128 megabytes (2^27 bytes), time= 76.0 seconds
  no anomalies in 82 test result(s)

rng=RNG_stdin8, seed=0x3bb19275
length= 256 megabytes (2^28 bytes), time= 147 seconds
  no anomalies in 88 test result(s)

rng=RNG_stdin8, seed=0x3bb19275
length= 512 megabytes (2^29 bytes), time= 289 seconds
  no anomalies in 92 test result(s)

rng=RNG_stdin8, seed=0x3bb19275
length= 1 gigabyte (2^30 bytes), time= 571 seconds
  no anomalies in 98 test result(s)

From what I've read this test needs to run while before you can say it is safe. Even then there is evidence to suggest that passing those tests doesn't mean a RNG is cryptographically secure.