I spent a very long time trying to figure out how to encrypt something with an IPFS peer's ID so that only they can decrypt it (in JavaScript). This gist is to save anyone else from that same time-sink.
Say you have an IPFS node as your peer, and their public key is this protobuf-encoded gibberish spit out by IPFS:
// for example from the command: node.id()
let publicKey = 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDC7gCqYWtRFmfQ8XZHnFnqB2sdPjprZgDOvz3Hl6NLGPpz95JVqguxQ9XDLnmPPFVOXEdMWohXOmWkQ4AF/6MDLz68q9/+xlvGRrwXE6gbhF15rBV+2A6LtCsbTNnzd7G+YmHMgBNk8UF4zB6Cg/6o2770fqp8khrTG1rwRXX2Cl0z/hEcIMFCAHEQpnmigP1gibtJi6cEjfjHQkqRF8ndCSNyUucgBkWPuJKEFWwAh5AJBVeEbWZngFGQ4jhp14RQ57cHv7COOQk8X3rSkJKMnyURm1iHK635TaJXpjaW8gD13imKUZHFCxS1JLIa3QTh8bk33+kK1jzkPN/XAC2BAgMBAAE='
You'll need the following imports:
let p2pcrypto = require("libp2p-crypto")
let NodeRSA = require("node-rsa")
First reformat:
let buf = Buffer.from(publicKey, 'base64')
publicKey = p2pcrypto.keys.unmarshalPublicKey(buf)
publicKey = {
n: Buffer.from(publicKey._key.n, 'base64'),
e: Buffer.from(publicKey._key.e, 'base64'),
}
let usefulPubKey = new NodeRSA()
usefulPubKey.importKey(publicKey, 'components-public')
Then encrypt:
let message = 'this is a test message'
let cipher = key.encrypt(message)
And what you end up with is the ciphertext as a Buffer
.
Getting an IPFS node's private key is not well documented. The only way I know is like so:
// Note: `node` is an ipfs node set up like so:
// const node = new IPFS();
let privateKey = node._peerInfo.id._privKey;
Make it useful (note: not a protobuf this time):
let usefulPrivKey = new NodeRSA();
usefulPrivKey.importKey({
n: Buffer.from(privateKey._key.n, 'base64'),
e: Buffer.from(privateKey._key.e, 'base64'),
d: Buffer.from(privateKey._key.d, 'base64'),
p: Buffer.from(privateKey._key.p, 'base64'),
q: Buffer.from(privateKey._key.q, 'base64'),
dmp1: Buffer.from(privateKey._key.dp, 'base64'),
dmq1: Buffer.from(privateKey._key.dq, 'base64'),
coeff: Buffer.from(privateKey._key.qi, 'base64'),
}, 'components');
Decrypt:
let messageBytes = usefulPrivKey.decrypt(cipher)
let m = messageBytes.toString()
console.log(m)
Profit:
/*** your code here ***/
I've been using js-ipns for that so I don't have an example for you, but I'm petty sure the keys used by IPFS have a
sign
function you can use. I think it's on thePeerId
's key object but I don't remember exactly.