Importing PEM encoded private key

I am a bit confused about the key import API. What type of encoding does it expect exactly?
Is it PEM? In the documentation it says it is a Base64 encoding of a protobuf? If so, why is it not something simpler and more widespread?
Context: I want to create a way for a user (and only for the user) to retrieve and modify data on IPFS, without having to remember CIDs, or private keys etc. The first half of the issue is resolved by IPNS, since it gives us a non-changing address to the changing content. From what I understand ipns publish uses a keypair generated using key gen to generate the k5 'link to our data. However if a user attempts to access this link from another device they either need to remember the link (not an option in my application) or import it from the original device (also not an option). We can however use CrypticoJS to generate a passphrase based RSA keypair (essentially replacing the seed for the CSPRNG in the RSA algorithm with our passphrase). This way, the user needs only to memorize their passphrase which can then be used to generate the same RSA key pair which can then be used to replicate the same IPNS link on any device, from which we can read/write our data. The only issue is that the encoding of a Cryptico keypair is way different from that of the ones in IPFS(or I guess libp2p). Anyone experienced enough to tell me how to convert Cryptico generated keypairs to something that IPFS can import? (With possible intermediary steps like Cryptico-> PEM and then PEM->Whatever encoding IPFS uses)

I had the same need recently myself, where I needed the “key gen” generated key in the form of a PEM (or other standard format) to use elsewhere for other crypto functions.

However I didn’t understand part of what you said in your question. You realize the only person who must have the key is the one UPDATING the IPNS right? You don’t need the key for any access. If you want to update an IPNS address from some other IPFS instance, then you can copy over the exported key file, and import it into that instance. Any instance that has the key imported can update the IPNS too.

You are right about the protobuf-wrapped format, as it uses:

That library has the necessary functions to convert though.

1 Like

Thanks @hector. Just to clarify, in my use case I was wanting to use the same key that controls the IPNS publish as the key that can access encrypted content of the actual data itself.

This would be really clean, because there would be only one single key controlling both the publishing and the encryption of the data. Useful for applications like Social Media for example where a single key should be in control of any “tree of content”.

But this ‘ownership principle’ should extend to all other kinds of apps, so having that key exportable in a usable format would be great. Maybe using an export option like -format=PEM

Yes, correct, basically I want to decouple the user from a device. Every IPFS node hence every self keypair is specific to a device. You could copy over the key file, but that is want to avoid, the inconvenience of having to copy it, and instead use a deterministic RSA key pair generation method, that for a given passphrase generates the same keypair always, regardless of when or where. (Yes I am aware of some security issues regarding this). I find the CrypticoJS library does just this.
This would in principle allow a user to access their data from whatever device using only their memorized passphrase. (This same seeded keypair is also used to encrypt and sign the data)

Allow the user to access and modify their data on an IPNS link from any device, important clarification

I agree with all that. The “KeyPair from passphrase” is an important use-case and is a huge reason why the “key import” needs to accept standard formats (like PEM). I’m glad you did clarify that. What you’re pointing out will definitely be the most common ‘use case’ too I think.

BTW: I’m using the browser built-in “crypto.subtle” API of JavaScript btw, because it’s native in the browser, and can do key import/export too.

This sounds like a well-defined feature request, and I agree we should support more than protobuf-based format to make it easier for people to experiment and build things on top of IPFS/IPNS.

PEM sounds like a good candidate, is already supported by tools like openssl

$ openssl genpkey -algorithm ED25519 | tee ed25519-key-pair.pem
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEIE8ztLJv1FT8cCURj/zc+KqjHWGJRnvsZD8gkgNLnVjs
-----END PRIVATE KEY-----

$ openssl pkey -in ed25519-key-pair.pem -pubout | tee ed25519-key-pair.pub.pem
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEAVf7fNOBHJzMEncjdWh32tpYt0U2RN/7Jhw6zwvjgH9Y=
-----END PUBLIC KEY-----

@godraadam mind filling an issue in go-ipfs repo for “adding ability to opt-in to PEM format in key import/export commands”? We would need a similar issue filled for js-ipfs as it makes sense to support this in both.

  • I’m thinking ipfs key export --format=pem > foo.pem, but we can triage after the issue is created.
  • If you want to see this sooner than later, either in GO or JS, PR welcome :pray:

Reading the core-api doc on js-ipfs repo tells me that in the JS implementation, PEM format is used for export import

1 Like

Indeed, js-ipfs is already doing the sane thing:

I agree, we should not export keys in cleartext by default.
Filled go-ipfs issue and wrote some tips, so it should be easy enough for anyone from IPFS community to pick it up and contribute:

Let’s continue there.