9

I have a problem that is driving me crazy.

I have created a pair of keys doing:

$res = openssl_pkey_new(array('private_key_bits' => 2048));

/* Extract the private key from $res to $privKey */
openssl_pkey_export($res, $privKey);

/* Extract the public key from $res to $pubKey */
$pubKey = openssl_pkey_get_details($res);
$pubKey = $pubKey["key"];

Using this code, I have $pubKey and $privKey.

I can encrypt/decrypt correctly, but I have a big doubt regarding the DECRYPTION.

At the moment I crypt data doing:

openssl_public_encrypt($data, $encrypted, $pubKey);

It encrypt my data correctly, but reading the PHP Doc, I found:

http://php.net/manual/en/function.openssl-public-decrypt.php

Can I decrypt data using PUBLIC KEY ?? Why ??

I know the public key is useful to ENCRYPT data, but only the owner of the private key can DECRYPT data.

If I can decrypt data using the public key, let the users that know the public key decrypt easily the messages.

Could someone explain this to me? I'm looking for a method to use two keys, the first to ENCRYPT and the second (only the second) to DECRYPT.

Thanks

Ilmari Karonen
  • 49,047
  • 9
  • 93
  • 153
Dail
  • 4,622
  • 16
  • 74
  • 109
  • You can encrypt with either key. You can _attempt_ to decrypt with either key but only one of them will succeed. Whichever one is used to encrypt, only the opposite will successfully decrypt. There are some situations where you encrypt with the private key and decrypt with the public - for example as proof that you have access to the private key. – Abhi Beckert Dec 21 '20 at 21:40
  • The documentation you mentioned does not return the decrypted message. It returns whether the owner of the private key encrypted the message or not. In order to decrypt the message you need the private key. – Tim Anthony Mar 10 '21 at 08:39

4 Answers4

14

In asymmetric public/private key encription usually:

  1. Bob generated his public/private key pair
  2. Bob shared his public key
  3. Alice crypts some message with the public key of Bob
  4. She sends the message
  5. Only Bob can decrypt with his private key.

enter image description here

Now we can use the openssl library to learn basic cryptography. Note that the following code is not suitable for production software, use it only to learn the basics of asymmetric encryption.

Using that aproach and the following code Alice can succesfully send a message to Bob

/**  BOB CODE  **/
$key = openssl_pkey_new(array('private_key_bits' => 2048));

$bob_key = openssl_pkey_get_details($key);
$bob_public_key = $bob_key['key'];

That's the basic infrastructure you had in your code and now is code that Bob executes. Bob generates the key pair and sends to Alice, in a real environment there must be a public key sharing mechanism.

When Alice gets Bob's public key, she cyphers her message with this key:

/** ALICE CODE **/
$alice_msg = "Hi Bob, im sending you a private message";
openssl_public_encrypt($alice_msg, $pvt_msg, $bob_public_key);

Finally Bob receives the message and decrypts it

/**  BOB CODE **/
openssl_private_decrypt( $pvt_msg, $bob_received_msg, $key);
print $bob_received_msg;

Recommended encryption library for production

Use libsodium if you aim for a secure production system. With it you can crypt messages...

// Generating your encryption key
$key = \Sodium\randombytes_buf(\Sodium\CRYPTO_SECRETBOX_KEYBYTES);

// Using your key to encrypt information
$nonce = \Sodium\randombytes_buf(\Sodium\CRYPTO_SECRETBOX_NONCEBYTES);
$ciphertext = \Sodium\crypto_secretbox('test', $nonce, $key);

... and decrypt messages...

$plaintext = \Sodium\crypto_secretbox_open($ciphertext, $nonce, $key);
if ($plaintext === false) {
    throw new Exception("Bad ciphertext");
}

...among other things.

What is a nonce?

Check the Full manual for using it with PHP

Read it carefully, encryption is not a thing one can learn in a week. There are some caveats.

David Lemon
  • 1,560
  • 10
  • 21
  • 1
    Here's a gist that illustrates this flow: https://gist.github.com/datashaman/1c4133928df1f7146f0921fa957e99b5 – datashaman Jul 24 '20 at 10:24
7

The whole idea of public-key cryptography is that every 'user' has a 'Public key' and a 'Private key'. There are 3 main implementations for these keys: confidential, authenticated and combined. In my answer, I'll go by the 'confidential' technique.

Each user has a 'Public key' that they distribute and which will be used by the other user to encrypt the message that will be sent back, and a 'Private key' that they keep only for themselves which is used to decrypt the messages that they will receive. The key that you have used to encrypt your message, isn't the same key that is used to decrypt.

Example of 'confedential key use':

Bob has: Bob private key, Bob public key, Alice public key
Alice has: Alice private key, Alice public key, Bob public key

Bob wants to send a message to Alice:
Bob uses 'Alice public key' to encrypt the message, sends it =>
Alice uses 'Alice private key' to decrypt the message.

Alice wants to reply and sends a message to Bob:
Alice uses 'Bob public key' to encrypt the message, sends it =>
Bob uses 'Bob private key' to decrypt the message.

Public key is only used to encrypt message
Private key is only used to decrypt message encrypted with Public key

Now that you know what the basic idea of the 'Public key' and 'Private key' is, have a look at this image explaining the typical SSL communication and the use of the keys.

Grzegorz
  • 3,538
  • 4
  • 29
  • 47
Koen Geeraert
  • 343
  • 1
  • 8
  • I know how Asimmetric encryption works... as you wrote me, each user use the public key of the other users to ENCRYPT Messages, but only the user with the respective private key can DECRYPT the message. That's exactly what I need. The problem (doubt) I Have is that Why two keys if i can encrypt/decrypt with ONE key ? My focus is the have one key to encrypt and one (private) to decrypt...can I do it using php ? – Dail Aug 10 '12 at 18:20
  • I believe I now understand what you're looking for. If you want to encrypt with the private key and decrypt with the public, you should use openssl_private_encrypt() on the encrypting end and openssl_public_decrypt() on the decrypting end. I have just noticed you were using openssl_**public_encrypt()** in your opening post. – Koen Geeraert Aug 10 '12 at 18:39
  • if i use the private key to encrypt should someone Decrypt Message with PRIVATE key? I ask you that because if i must to use the private key i will put it in my php script...i do not want someone can read that .php file can use the private key (i will write in a variable) to Decrypt my ecrypted messages – Dail Aug 10 '12 at 19:10
  • No, it actually says so in the function name which key you are using. openssl_public_encrypt() => encrypts using public key; openssl_private_encrypt() => encrypts using private key; openssl_public_decrypt() => decrypts using the public key; openssl_private_decrypt() => decrypts using the private key; You can never decrypt with the same key that was used to encrypt, so if you use the private key to encrypt, you should always use the public key to decrypt and so on. Only the use of the opposite key will work. If you encrypt with the private key - it can only be decrypted with the public key. – Koen Geeraert Aug 10 '12 at 19:13
  • yes thought so but it is not true. In my example as you can see i crypted with the public and decrypted with the public again...it is strange...but it gave me the decrypted data...please try the code – Dail Aug 10 '12 at 20:18
3

Signatures, a kind of hash proving the owner of the private key created the encrypted message. Good for Alice to prove Bob wrote her a message (encrypted with Alice's public key) - rather than Joe. Bob creates a unique signature using his private key, which Alice can confirm using Bob's public.

:)

wally
  • 3,492
  • 25
  • 31
1

Short Answer

A message encrypted by a public key can only be decrypted by the matching private key.

Long Answer

Asymmetric encryption works both ways.

So why is there even an openssl_public_decrypt() function? you might ask. As the documentation states it can decrypt a message which has been encrypted by a private key. As wally mentioned before this can be used for signatures.

Let's say Alice waits for a message from Bob, but not from anybody else. So Bob uses his own private key to encrypt the message (e.g using openssl_private_encrypt()). When Alice recieves any message she tries to decrypt it using Bob's public key. If this succeeds she knows that the message came from Bob.

Note that encrypting using the private key would not be secure because anybody (who has access to the public key) can decrypt the message. In practise you would probably use a combination of both methods (append a signature encrypted with Bob's private key and then encrypt the entire message using Alice's public key).