Public Key Cryptography

Public-Key Cryptography is the common name for Asymmetric-Key Algorithms. Where symmetric-key algorithms used a single key for encrypting and decrypting, asymmetric-key algorithms use a pair of keys.

The simplest illustration is to imagine a box which requires two keys to lock it and which requires two keys to unlock it. Neither can unlock the box without the other person's key. A real-world example of this is bank safety deposit box which require a customer's key and also a bank employee's key.

When encrypting data for communication, it is not practical for both the sender and receiver to be present when a message needs to be encrypted or decrypted. A more complex strategy allows the sender and the receiver to each have two keys one for encrypting and one for decrypting. A software key generation program creates two different keys which are linked together mathematically. One key can be used to lock the data and the other key will unlock it.

The reason it is called "Public-Key Cryptography" is because each person will share one of their keys widely ("public key") so that anyone can use it. Then they will keep the other key private ("private key") so that only they can use it.

Alice wants to send an encrypted message to Bob.

  • Alice writes a plain text message to Bob
  • Alice encrypts the plain text message with Bob's public key

Then Alice sends the encrypted message to Bob.

  • Bob decrypts the encrypted message with his private key
  • Bob reads the message

Digital Signatures

Key pairs can also be used to create digital signatures. The message text is put into an algorithm along with the sender's private key. The result is a digital signature which can be sent along with the message. The recipient can use another algorithm on the message data, the signature, and the sender's public key to verify: 1) message integrity: the data has not been changed, 2) sender authenticity: that the signature was created using the sender's private key.

Messages can be encrypted without adding a signature and unencrypted data can be digitally signed. However, typically in public-key cryptography, both are used together. This provides a message privacy, integrity, and authenticity.

Alice wants to send an encrypted message to Bob.

  • Alice writes a plain text message to Bob
  • Alice encrypts the plain text message with Bob's public key
  • Alice creates a digital signature for the encrypted message with her private key

Then Alice sends the encrypted message and signature to Bob.

  • Bob verifies the digital signature using the encrypted message and Alice's public key
  • Bob decrypts the encrypted message with his private key
  • Bob reads the plain text message

In our example, Bob will know that the message he received is truly from Alice because only Alice should possess the private key which he unlocked with her public key. (This is only true if Bob can trust that the public key he downloaded is really Alice's public key.)


Public-Key Cryptography Pros and Cons

The primary benefit is that all of the information can be communicated over an open network. There does not need to be a pre-arrangement or a secret channel for the sender to tell the recipient the password to use for decrypting a message. This is ideal for use on the Internet. This is in contrast to symmetric key algorithms which suffer from a "key distribution problem".

In addition, digital signatures confirm the integrity and authenticity of a message.

Asymmetric algorithms take a relatively long time compared to symmetric algorithms, and they are limited in the amount of data which can be encrypted (for a 2048-bit RSA key it is 245 bytes/characters). For this reason, public-key cryptography is often used to send messages, such as to share a symmetric encryption key. Then larger data can be exchanged using faster symmetric key algorithms, using a password which the sender and receiver both know.

Public-Key Cryptography is widely used as part of secure technologies for communicating online, including TLS/SSL, S/MIME, PGP, and RSA. They use public-keys to share a password key and then switch to symmetric encryption to communicate.


Public-Key Cryptography in PHP

Generate keys using PHP's OpenSSL functions

<?php
  // Create a private/public key pair
  $config = array(
      "digest_alg" => "sha512",
      "private_key_bits" => 2048,
      "private_key_type" => OPENSSL_KEYTYPE_RSA,
  );
  $resource = openssl_pkey_new($config);

  // Extract private key from the pair
  openssl_pkey_export($resource, $private_key);

  // Extract public key from the pair
  $key_details = openssl_pkey_get_details($resource);
  $public_key = $key_details["key"];

  $keys = array('private' => $private_key, 'public' => $public_key);
  
  echo $keys['public'];
  echo $keys['private'];
?>

Use PHP's OpenSSL functions to encrypt using the public key.

<?php
  $plaintext = "I have a secret to tell you.";

  openssl_public_encrypt($plaintext, $encrypted, $keys['public']));

  // Use base64_encode to make contents viewable/sharable
  $message = base64_encode($encrypted);

  echo $message;
?>

Use PHP's OpenSSL functions to decrypt using the private key.

<?php
  // Decode from base64 to get raw data
  $ciphertext = base64_decode($message);
  
  openssl_private_decrypt($ciphertext, $decrypted, $keys['private']);

  echo $decrypted;
?>

Sign and verify data with private keys in PHP

Use PHP's OpenSSL functions to sign the data with the private key.

<?php
  $data = "I can verify this message is from me.";

  openssl_sign($data, $raw_signature, $keys['private']);
  
  // Use base64_encode to make contents viewable/sharable
  $signature = base64_encode($raw_signature);
?>

Use PHP's OpenSSL functions to verify using the public key.

<?php
  $raw_signature = base64_decode($signature);
  $result = openssl_verify($data, $raw_signature, $keys['public']);
  echo $result;
  // returns 1 if data and signature match

  $modified_data = $data . "extra content";
  $result = openssl_verify($modified_data, $signature, $keys['public']);
  echo $result;
  // returns 0 if data and signature do not match
?>
Fork me on GitHub