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.
Encryption
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
.
Decryption
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'm trying to make it work encrypting with the private. Not working... Is it supposed to work?