Js-ipfs restoring rsa keys

I am in the discovery/research phase for a decenteralized app and have some really basic questions regarding js-ipfs. I was planning on using orbitdb and noticed that they use secp256k1keys. For those keys I was thinking of using bitcoin’s bip39 mnemonic seed phrase so that recovering the keys in a different browser/system would be easy. The issue is with the rsa keys. When looking at ipfs-js I don’t see an easy way to give ipfs the keys when initializing it. If I had some other mechanism for saving the rsa keys how would I start an ipfs node in the browser using those previously saved keys?

I’ve thought about possibly using bip39 seed to seed a rng and then using that rng when generating the rsa keys but I’m not sure how secure that would be and I’m not sure how I could boot ipfs in the browser using those generated keys.

1 Like

Well the solution was actually as simple as possibly could be. The way to restore a key from a previous session in jsipfs is to supply the config.Identity option when initalizing ipfs. In addition to figuring that out I wrote an rsa implementation(more like edited parts of jsencrypt) which uses a seeded rng(seeded with a bip39 seed) to generate a private key. With this system the user first creates, or restores, a bip39 seed phrase when they first register. I could then AES encrypt the indentity and secp256k1 keys and save it in a cookie/local storage. Then when a user returns on the same system have them enter their pass phrase to decrypt the stored keys. In the event that they need to restore on any other system they simply need to remember their mnemonic phrase.

For anyone who may be interested I wrote an RSA implemention which uses a rng that is seeded by a bip39 seed. That same seed can easily be used to generate the secp256k1 keys as well. It is located here: https://github.com/nomadcrypto/seededrsa and can be used with ipfs like this:

  var RSA = require("seededrsa");
  const cryptoKeys = require('libp2p-crypto/src/keys')
  const PeerId = require('peer-id')
  var pem2jwk = require('pem-jwk').pem2jwk
  const fromJwk = cryptoKeys.supportedKeys.rsa.fromJwk;

  function rsaToPeerID(key, callback) {
    fromJwk(pem2jwk(key.privateKey()), function(err, priv) {
      if(err) {
        callback(err)
      } else {
        PeerId.createFromPrivKey(cryptoKeys.marshalPrivateKey(priv), function(err, peerid) {
          if(err) {
            callback(err);
          } else {
            callback(null, peerid.toJSON());
          }
        })
      }
    })
  }

  var phrase = 'praise you muffin lion enable neck grocery crumble super myself license ghost'
  var rsa = new RSA(phrase);
  rsa.generate(2048);

  console.log("private", rsa.privateKey())
  console.log("public", rsa.publicKey())

  rsaToPeerID(rsa, function(err, peerid) {
    console.log("peerid", peerid)
  })


  /*
  private -----BEGIN RSA PRIVATE KEY-----
  MIIEogIBAAKCAQB/fhIBfKuQa003rOXNK+HbIqlegfGYRWepNmDTIbQ2wEdpaJ0i
  TyksL7yYyLvTUvmLUnyJgvZgf1GwF1UD0274NfJgExeCmv5F93SC8XJcvSE9VJTf
  fliszefAgJuoCYaCZiFeZAaYJbiYXvj1W1gj58HAY8OPD1QrqiI+hl3WXvlWkRqo
  oKMJb0PolCGdufBIwR9iW4rv662WmTk4IBi9x40ydRBB+3LMiwLgLr0ErDoOrWna
  AGAF2euohD4PQ1MYfw7GSgIUmLBIHxSGFDOmewytIo5MIeBbKDdjFOhTrqSlyYfN
  wXwa0ZrnjYCe+6oQugFLdqCLMCL2v2mmiNYjAgMGVTcCggEAUyzm8+/yCWgU7ySf
  15nGq3xeQ2V5m7OhQDk8LFtbxaJikhYrUm0oYxaBLKkefMqVfTQpSOU5pSARC7tS
  WeVZYaErfMq11ECbvHMCTt/uhJSQ4b8U6zQBZatCjivfaljQu0qNFrdHtS2l76eQ
  TcA+ibe9EsekfnUP5nuLUQ3Myx31YmaEqjhXmWM96K817Qefofout98bgE2EmhIW
  Em6D7Q/TpUeGH2iUig24BFF9LcT4cWbA/EQwlh23R0TySsQsQerO3FilEysV3hFT
  Mym9P7DBPZsw8rUyRsVr8Mn4KGpCGfxN6e11RZXJ0pQC3yCtruBzZijXawbLJwMv
  rFjORwKBgQC4MzEwNTIxMjIzNDc0MTA0NDU4ODIxNzk3MzE0MzExMDk0MTQ2MzQ5
  MTc2MTIxMzE5NjIxMjQ0MTgzMTUxODcxMzU1NzIxMjM5MjUxMTc0MjcyMzMxNTcx
  MzUxMTUxMTA3MDEwMjIwMjEwNjEzOTExNTUxMDY1ODQwMTMyMTEzewKBgQCxMDEy
  ODM4MzAyNDMxOTAyNDM0MDM2MTM4MTQ3MTczMjAxNzEyMDkyMjExODUxMDkyMTkx
  ODAzNzg1MTQ4MjUwMTc0MjExMTgzMjI0MTg5MjUyNzIxNTkxNTIxOTE1Mzk4NDYx
  MTIzMjQxMTYxNjExNzAxNTAyMDUxMDU3MTIzeQKBgHfA/kV27x4IuEVdqcwbHF67
  FISrA544R+6ZRPWXxMQGs2r4WzhPPCszOTgJZfZ4eCXcd3AcXaAaGOrnOdpKJ7AY
  UhjeCAvQ9eSf6p+vMTekXpa4NZFOoPtqutbXzE0C/wgfN7fmcMem4/5YCl468UrR
  ud8V4jpbGkM9xLNPH4SHAoGBAKtsEvjkyi+5juGmpKf1NkXIW9MK2vH9prmve5hM
  ljXv7NKcPKQ424rijR5sDwvmnrAp8W/txnx1o1WAcdLt+pEUlAI7WXbZsI4HUU/H
  BHBMDDqhoJnLetpvjrry/f/ORMmdAZaeoTl3etwc1vleGY+f7V77PYSI4ZZduL/9
  NIVvAoGASQKnlWtKBnzfgQzecyJDbudJsL2tg+6Il2we90qQ7ZFLRIdL87EyQFrq
  hIdW0liBrdwR04QFmcFO4YPfkIrRph8345vJlgG3uVVFQkgev2cok32VBOJwftGj
  5NumiAqAxHHZHK0ZJottWDNPwwEEKtijEz90DdOjiWiFRKc6wQI=
  -----END RSA PRIVATE KEY-----

  public -----BEGIN PUBLIC KEY-----
  MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQB/fhIBfKuQa003rOXNK+Hb
  IqlegfGYRWepNmDTIbQ2wEdpaJ0iTyksL7yYyLvTUvmLUnyJgvZgf1GwF1UD0274
  NfJgExeCmv5F93SC8XJcvSE9VJTffliszefAgJuoCYaCZiFeZAaYJbiYXvj1W1gj
  58HAY8OPD1QrqiI+hl3WXvlWkRqooKMJb0PolCGdufBIwR9iW4rv662WmTk4IBi9
  x40ydRBB+3LMiwLgLr0ErDoOrWnaAGAF2euohD4PQ1MYfw7GSgIUmLBIHxSGFDOm
  ewytIo5MIeBbKDdjFOhTrqSlyYfNwXwa0ZrnjYCe+6oQugFLdqCLMCL2v2mmiNYj
  AgMGVTc=
  -----END PUBLIC KEY-----

  peerid { id: 'QmUtvkiZrAJ9HKnR5qDf71rLLhKHNF4mfsJjAPHZdwwXYC',
    privKey:
     'CAASpgkwggSiAgEAAoIBAH9+EgF8q5BrTTes5c0r4dsiqV6B8ZhFZ6k2YNMhtDbAR2lonSJPKSwvvJjIu9NS+YtSfImC9mB/UbAXVQPTbvg18mATF4Ka/kX3dILxcly9IT1UlN9+WKzN58CAm6gJhoJmIV5kBpgluJhe+PVbWCPnwcBjw48PVCuqIj6GXdZe+VaRGqigowlvQ+iUIZ258EjBH2Jbiu/rrZaZOTggGL3HjTJ1EEH7csyLAuAuvQSsOg6tadoAYAXZ66iEPg9DUxh/DsZKAhSYsEgfFIYUM6Z7DK0ijkwh4FsoN2MU6FOupKXJh83BfBrRmueNgJ77qhC6AUt2oIswIva/aaaI1iMCAwZVNwKCAQBTLObz7/IJaBTvJJ/XmcarfF5DZXmbs6FAOTwsW1vFomKSFitSbShjFoEsqR58ypV9NClI5TmlIBELu1JZ5VlhoSt8yrXUQJu8cwJO3+6ElJDhvxTrNAFlq0KOK99qWNC7So0Wt0e1LaXvp5BNwD6Jt70Sx6R+dQ/me4tRDczLHfViZoSqOFeZYz3orzXtB5+h+i633xuATYSaEhYSboPtD9OlR4YfaJSKDbgEUX0txPhxZsD8RDCWHbdHRPJKxCxB6s7cWKUTKxXeEVMzKb0/sME9mzDytTJGxWvwyfgoakIZ/E3p7XVFlcnSlALfIK2u4HNmKNdrBssnAy+sWM5HAoGBALgzMTA1MjEyMjM0NzQxMDQ0NTg4MjE3OTczMTQzMTEwOTQxNDYzNDkxNzYxMjEzMTk2MjEyNDQxODMxNTE4NzEzNTU3MjEyMzkyNTExNzQyNzIzMzE1NzEzNTExNTExMDcwMTAyMjAyMTA2MTM5MTE1NTEwNjU4NDAxMzIxMTN7AoGBALEwMTI4MzgzMDI0MzE5MDI0MzQwMzYxMzgxNDcxNzMyMDE3MTIwOTIyMTE4NTEwOTIxOTE4MDM3ODUxNDgyNTAxNzQyMTExODMyMjQxODkyNTI3MjE1OTE1MjE5MTUzOTg0NjExMjMyNDExNjE2MTE3MDE1MDIwNTEwNTcxMjN5AoGAd8D+RXbvHgi4RV2pzBscXrsUhKsDnjhH7plE9ZfExAazavhbOE88KzM5OAll9nh4Jdx3cBxdoBoY6uc52konsBhSGN4IC9D15J/qn68xN6Relrg1kU6g+2q61tfMTQL/CB83t+Zwx6bj/lgKXjrxStG53xXiOlsaQz3Es08fhIcCgYEAq2wS+OTKL7mO4aakp/U2Rchb0wra8f2mua97mEyWNe/s0pw8pDjbiuKNHmwPC+aesCnxb+3GfHWjVYBx0u36kRSUAjtZdtmwjgdRT8cEcEwMOqGgmct62m+OuvL9/85EyZ0Blp6hOXd63BzW+V4Zj5/tXvs9hIjhll24v/00hW8CgYBJAqeVa0oGfN+BDN5zIkNu50mwva2D7oiXbB73SpDtkUtEh0vzsTJAWuqEh1bSWIGt3BHThAWZwU7hg9+QitGmHzfjm8mWAbe5VUVCSB6/ZyiTfZUE4nB+0aPk26aICoDEcdkcrRkmi21YM0/DAQQq2KMTP3QN06OJaIVEpzrBAg==',
    pubKey:
     'CAASpQIwggEhMA0GCSqGSIb3DQEBAQUAA4IBDgAwggEJAoIBAH9+EgF8q5BrTTes5c0r4dsiqV6B8ZhFZ6k2YNMhtDbAR2lonSJPKSwvvJjIu9NS+YtSfImC9mB/UbAXVQPTbvg18mATF4Ka/kX3dILxcly9IT1UlN9+WKzN58CAm6gJhoJmIV5kBpgluJhe+PVbWCPnwcBjw48PVCuqIj6GXdZe+VaRGqigowlvQ+iUIZ258EjBH2Jbiu/rrZaZOTggGL3HjTJ1EEH7csyLAuAuvQSsOg6tadoAYAXZ66iEPg9DUxh/DsZKAhSYsEgfFIYUM6Z7DK0ijkwh4FsoN2MU6FOupKXJh83BfBrRmueNgJ77qhC6AUt2oIswIva/aaaI1iMCAwZVNw==' }
  (env)
  */

This isn’t a solution to the OP’s problem, but I would like to save people who end up here from Google like me.

PSA: If you want to maintain a constant identity across tabs and page refreshes, just use a fixed repo name when initializing your IPFS node in the browser and it will happen automatically.