<p>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.</p>

CC BY-SA 4.0
2018-11-03T00:44:59.020Z
While 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
CC BY-SA 4.0
2018-11-03T01:09:13.540Z
The 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
CC BY-SA 4.0
2018-11-03T02:54:05.283Z
I 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
CC BY-SA 4.0
2018-11-02T19:47:17.313Z
2018-11-02T19:47:17.313Z
G. Maxwell
<p>Be sure to follow the warnings given previously in other answers, but for the record this was implemented in a project called <a href="https://bitmessage.org/wiki/Main_Page" rel="nofollow noreferrer">Bitmessage</a>. The main implementation is in Python at <a href="https://github.com/Bitmessage/PyBitmessage" rel="nofollow noreferrer">https://github.com/Bitmessage/PyBitmessage</a>.  There is also an npm module for node.js that implemented this for the server and browser using openssl c libraries under the hood: <a href="https://www.npmjs.com/package/eccrypto" rel="nofollow noreferrer"><code>eccrypto</code></a>:</p>

<p><strong>Install dependencies</strong></p>

<pre><code>$ npm install -g eccrypto
</code></pre>

<p><strong>index.js</strong></p>

<pre><code>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());
  });
});
</code></pre>

CC BY-SA 4.0
2018-11-02T20:52:53.153Z
2018-11-09T02:13:55.470Z
2018-11-09T02:13:55.470Z
JBaczuk
<p>Yes, this is possible.</p>
<p>However, I want to upfront state that this is not advisable for multiple reasons:</p>
<ul>
<li>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.</li>
<li>There may be ugly and dangerous interactions when keys are used for multiple protocols independently.</li>
<li>You're much better off using systems that were actually designed for encryption than trying to piggy-back off Bitcoin's cryptography.</li>
<li>Implementing your own cryptography is very dangerous (in general, unless you know what you're doing, and get plenty of review from experts).</li>
</ul>
<p>A scheme called <a href="https://en.wikipedia.org/wiki/Integrated_Encryption_Scheme" rel="nofollow noreferrer">ECIES</a> exists that lets you leverage elliptic curve keys to create an encryption system.</p>
<p>In short, it works by:</p>
<p>The sender:</p>
<ul>
<li>generates an ephemeral private key <em>k</em> using a strong cryptographic random number generator, with associated public key <em>K = kG</em> (multiplication refers to <a href="https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication" rel="nofollow noreferrer">Elliptic Curve multiplication here</a>).</li>
<li>computes an <a href="https://en.wikipedia.org/wiki/Elliptic-curve_Diffie%E2%80%93Hellman" rel="nofollow noreferrer">ECDH</a> shared secret <em>s = H(kP)</em>, where <em>P</em> is the public key of the recipient.</li>
<li>computes two symmetric keys <em>x<sub>1</sub></em> and <em>x<sub>2</sub></em> using a <a href="https://en.wikipedia.org/wiki/Key_derivation_function" rel="nofollow noreferrer">KDF</a> seeded by <em>s</em>: <em>(x<sub>1</sub>, x<sub>2</sub>) = KDF(s)</em>.</li>
<li>encrypts the message <em>m</em> using AES, with <em>x<sub>1</sub></em> as the key, to obtain <em>c = AESEnc<sub>x<sub>1</sub></sub>(m)</em>.</li>
<li>compute a <a href="https://en.wikipedia.org/wiki/Message_authentication_code" rel="nofollow noreferrer">MAC</a> on <em>K</em> and <em>c</em> with <em>x<sub>2</sub></em> as key: <em>h = MAC<sub>x<sub>2</sub></sub>(K || c)</em>.</li>
<li>sends <em>(K, c, h)</em> to the recipient.</li>
</ul>
<p>The recipient:</p>
<ul>
<li>computes the ECDH shared secret, using <em>s = H(pK)</em>, where <em>p</em> is his private key.</li>
<li>computes the same two symmetric keys <em>x<sub>1</sub></em> and <em>x<sub>2</sub></em>: <em>(x<sub>1</sub>, x<sub>2</sub>) = KDF(s)</em>.</li>
<li>computes the same MAC <em>h' = MAC<sub>x<sub>2</sub></sub>(K || c)</em></li>
<li>verifies that <em>h' = h</em>, and fails if not.</li>
<li>decrypts the message using <em>s</em>, <em>m' = AESDec<sub>x<sub>1</sub></sub>(c)</em>.</li>
</ul>

CC BY-SA 4.0
2018-11-03T02:43:04.447Z
If 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
CC BY-SA 4.0
2018-11-03T02:53:44.470Z
@G.Maxwell Good point, fixed.
Pieter Wuille
CC BY-SA 4.0
2018-11-30T11:10:38.693Z
couple of typos: `with associated public key k = kG` .. here it should be capital `K = kG`; and `AECEnc` should be `AESEnc`
Wapac
CC BY-SA 4.0
2018-11-02T19:58:55.013Z
2023-03-08T18:13:05.727Z
2023-03-08T18:13:05.727Z
Pieter Wuille
<p>I have the following text string:</p>

<p><em>This is a test message.</em></p>

<ul>
<li><p>Using my bitcoin public key (bitcoin address?), how can I encrypt this message?</p></li>
<li><p>How would I decrypt the message using a bitcoin private key?</p></li>
</ul>

CC BY-SA 4.0
2018-11-02T19:30:37.723Z
Do you want to encrypt to a public key, or using a password? Those two require very different technologies.
Pieter Wuille
CC BY-SA 4.0
2018-11-02T19:37:15.433Z
basically 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 パトシ
CC BY-SA 4.0
2018-11-02T19:44:04.790Z
But you're also mentioning AES and needing a password to decrypt?
Pieter Wuille
CC BY-SA 4.0
2018-11-02T19:45:52.757Z
updated question. removed aes reference. was confusing.
Patoshi パトシ
CC BY-SA 4.0
2018-11-03T00:05:37.813Z
Bitcoin **address** is _derived from_ publickey but is **not sufficient** to encrypt.
dave_thompson_085
CC BY-SA 4.0
2021-09-23T20:15:08.607Z
Have been looking at this. My thought was having a key thats super portable like a BTC key. Something that can be stored via a mnemonic as opposed to huge files.
Jikku Jose
<private-key><public-key><encryption>
How would one "Encrypt" a message using a Bitcoin *public key* and use its private key to decrypt it?
Patoshi パトシ
# How would one "Encrypt" a message using a Bitcoin *public key* and use its private key to decrypt it?

(Asked by: username_0 on 2018-11-02)

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?

**Tags:** private-key, public-key, encryption

> **Comments:**
> **username_1**: Do you want to encrypt to a public key, or using a password? Those two require very different technologies.  
> **username_0**: basically 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?  
> **username_1**: But you're also mentioning AES and needing a password to decrypt?  
> **username_0**: updated question. removed aes reference. was confusing.  
> **username_2**: Bitcoin **address** is _derived from_ publickey but is **not sufficient** to encrypt.  
> **username_3**: Have been looking at this. My thought was having a key thats super portable like a BTC key. Something that can be stored via a mnemonic as opposed to huge files.  

---

## 3 answers

### Answer by username_1 on 2018-11-02. Score: 22 | Accepted answer

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](https://en.wikipedia.org/wiki/Integrated_Encryption_Scheme) 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](https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication)).
* computes an [ECDH](https://en.wikipedia.org/wiki/Elliptic-curve_Diffie%E2%80%93Hellman) shared secret *s = H(kP)*, where *P* is the public key of the recipient.
* computes two symmetric keys *x1* and *x2* using a [KDF](https://en.wikipedia.org/wiki/Key_derivation_function) seeded by *s*: *(x1, x2) = KDF(s)*.
* encrypts the message *m* using AES, with *x1* as the key, to obtain *c = AESEncx1(m)*.
* compute a [MAC](https://en.wikipedia.org/wiki/Message_authentication_code) 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)*.

> **Comments:**
> **username_4**: If 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.  
> **username_1**: @G.Maxwell Good point, fixed.  
> **username_7**: couple of typos: `with associated public key k = kG` .. here it should be capital `K = kG`; and `AECEnc` should be `AESEnc`  

---

### Answer by username_4 on 2018-11-02. Score: 4

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.

> **Comments:**
> **username_5**: While 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.  
> **username_4**: The 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.  
> **username_5**: I 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.  

---

### Answer by username_6 on 2018-11-02. Score: 4

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());
  });
});


---

