How would one "Encrypt" a message using a Bitcoin *public key* and use its private key to decrypt it?

9

1

I have the following text string:

This is a test message.

  • Using my bitcoin public key (bitcoin address?), how can I encrypt this message?

  • How would I decrypt the message using a bitcoin private key?

Patoshi パトシ

Posted 2018-11-02T19:17:45.637

Reputation: 8 911

1Do you want to encrypt to a public key, or using a password? Those two require very different technologies.Pieter Wuille 2018-11-02T19:30:37.723

2basically take anyone's bitcoin address and encrypt a message, then send this person the encrypted message where he can decrypt with his bitcoin private key. Or that doesn't work at all?Patoshi パトシ 2018-11-02T19:37:15.433

But you're also mentioning AES and needing a password to decrypt?Pieter Wuille 2018-11-02T19:44:04.790

1updated question. removed aes reference. was confusing.Patoshi パトシ 2018-11-02T19:45:52.757

1Bitcoin address is derived from publickey but is not sufficient to encrypt.dave_thompson_085 2018-11-03T00:05:37.813

Answers

19

Yes, this is possible.

However, I want to upfront state that this is not advisable for multiple reasons:

  • Bitcoin keys are intended to be single use for privacy reasons, and leveraging them for encryption unnecessarily encourages treating them as a long-lived identity.
  • There may be ugly and dangerous interactions when keys are used for multiple protocols independently.
  • You're much better off using systems that were actually designed for encryption than trying to piggy-back off Bitcoin's cryptography.
  • Implementing your own cryptography is very dangerous (in general, unless you know what you're doing, and get plenty of review from experts).

A scheme called ECIES exists that lets you leverage elliptic curve keys to create an encryption system.

In short, it works by:

The sender:

  • generates an ephemeral private key k using a strong cryptographic random number generator, with associated public key k = kG (multiplication refers to Elliptic Curve multiplication here).
  • computes an ECDH shared secret s = H(kP), where P is the public key of the recipient.
  • computes two symmetric keys x1 and x2 using a KDF seeded by s: (x1, x2) = KDF(s).
  • encrypts the message m using AES, with x1 as the key, to obtain c = AECEncx1(m).
  • compute a MAC on K and c with x2 as key: h = MACx2(K || c).
  • sends (K, c, h) to the recipient.

The recipient:

  • computes the ECDH shared secret, using s = H(pK), where p is his private key.
  • computes the same two symmetric keys x1 and x2: (x1, x2) = KDF(s).
  • computes the same MAC h' = MACx2(K || c)
  • verifies that h' = h, and fails if not.
  • decrypts the message using s, m' = AESDecx1(c).

Pieter Wuille

Posted 2018-11-02T19:17:45.637

Reputation: 54 032

4If you don't have a MAC then what you've implemented is not ECIES and would often be vulnerable to decryption oracle attacks. E.g. I take a message,to you I want to decrypt and then send a series of messages to you reusing the ephemeral key and probing how you respond to different junk ciphertexts.G. Maxwell 2018-11-03T02:43:04.447

@G.Maxwell Good point, fixed.Pieter Wuille 2018-11-03T02:53:44.470

couple of typos: with associated public key k = kG .. here it should be capital K = kG; and AECEnc should be AESEncWapac 2018-11-30T11:10:38.693

5

If you want to encrypt messages, you should use a proper message/file encryption tool like PGP/GPG. Homebrewed cryptography using bitcoin things is prone to having poor security properties.

G. Maxwell

Posted 2018-11-02T19:17:45.637

Reputation: 6 039

1While you're probably right. This doesn't really seem to answer the question. I would think you're saying "it can't be done", but then again it seems you're saying it can be done, but are not answering "how", which is the question.JoL 2018-11-03T00:44:59.020

1The answer is "you probably shouldn't". I think this is a much more valuable answer than giving a tutorial that ultimately leaves the asker less informed and potentially completely insecure.G. Maxwell 2018-11-03T01:09:13.540

2I disagree "you probably shouldn't" is an answer at all. It could be part of an answer, as a disclaimer like in Pieter's answer. Alone, however, is more like denying an answer. Though questions at times ask things that seem like no one should need, there could be rare legitimate use-cases. Even if the OP's need isn't legitimate, a future reader's might.JoL 2018-11-03T02:54:05.283

3

Be sure to follow the warnings given previously in other answers, but for the record this was implemented in a project called Bitmessage. The main implementation is in Python at https://github.com/Bitmessage/PyBitmessage. There is also an npm module for node.js that implemented this for the server and browser using openssl c libraries under the hood: eccrypto:

Install dependencies

$ npm install -g eccrypto

index.js

var crypto = require("crypto");
var eccrypto = require("eccrypto");

var privateKeyA = crypto.randomBytes(32);
var publicKeyA = eccrypto.getPublic(privateKeyA);
var privateKeyB = crypto.randomBytes(32);
var publicKeyB = eccrypto.getPublic(privateKeyB);

// Encrypting the message for B.
eccrypto.encrypt(publicKeyB, Buffer("msg to b")).then(function(encrypted) {
  // B decrypting the message.
  eccrypto.decrypt(privateKeyB, encrypted).then(function(plaintext) {
    console.log("Message to part B:", plaintext.toString());
  });
});

// Encrypting the message for A.
eccrypto.encrypt(publicKeyA, Buffer("msg to a")).then(function(encrypted) {
  // A decrypting the message.
  eccrypto.decrypt(privateKeyA, encrypted).then(function(plaintext) {
    console.log("Message to part A:", plaintext.toString());
  });
});

JBaczuk

Posted 2018-11-02T19:17:45.637

Reputation: 6 172