Asymmetric encryption using PHP

11,112

Solution 1

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.

Solution 2

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.

Solution 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.

:)

Solution 4

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).

Share:
11,112
Dail
Author by

Dail

Updated on August 04, 2022

Comments

  • Dail
    Dail almost 2 years

    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