DEV Community

Shingai Zivuku
Shingai Zivuku

Posted on

Secure PHP APIs with Signature Verification Using OpenSSL

Application Programming Interfaces (APIs) are essential in web development. To ensure the security of API requests, it is often necessary to verify the authenticity of these requests. This article will discuss how to design a set of API signature verification programs in PHP, and provide specific design steps and code samples.

Overview: Signature Verification Process With OpenSSL

The API signature verification process is a way to ensure that API requests have not been tampered with or come from an unauthorized source. It works by using a digital signature to bind the request data to the identity of the sender.

The signature verification process typically includes the following steps:

  1. The client signs the request data by encrypting it with their private key. The signature is included in the request parameters.
  2. The server extracts the signature from the request parameters.
  3. The server reproduces the signature by encrypting the request data with the same private key and algorithm.
  4. The server compares the original and reproduced signatures. If they match, the request is authenticated. Otherwise, verification fails.

Implementation Guide

This section provides a step-by-step guide to implementing API signature verification with OpenSSL.

Generate Key Pair

First, generate a pair of public and private keys for encryption and decryption. You can use the openssl extension to generate a key pair. The specific code is as follows:

// Configuration for key generation
$config = array(
  "private_key_bits" => 2048, // Key size: 2048 bits 
  "private_key_type" => OPENSSL_KEYTYPE_RSA, // RSA algorithm
);

// Generate new private and public keys 
$res = openssl_pkey_new($config);

// Extract the generated private key 
openssl_pkey_export($res, $private_key); 

// Extract the public key component
$public_key = openssl_pkey_get_details($res);
$public_key = $public_key["key"]; 

// Save keys to files
file_put_contents('private.key', $private_key);
file_put_contents('public.key', $public_key);
Enter fullscreen mode Exit fullscreen mode

The above code will generate a private key and save it to private.key file, and save the public key to a public.key file.

Implementing Signature Functions

This section covers implementing the core signature functions.

Loading Keys

Before signature generation and verification, you need to load the private and public keys. You can create a Signature class and load the private and public keys in the constructor like this:

class Signature {
    private $private_key;
    private $public_key;

    public function __construct() {
        $this->private_key = openssl_pkey_get_private(file_get_contents('private.key'));
        $this->public_key = openssl_pkey_get_public(file_get_contents('public.key'));
    }

    // Other methods and code will be introduced later
}
Enter fullscreen mode Exit fullscreen mode

Generate Signature

To generate a signature, you need a method that accepts the request parameters and returns the signature. You can use OpenSSL's openssl_sign() function:

public function generateSignature($params) {

  // Convert the request parameters array to a string.
  $data = http_build_query($params);

  // Sign the data with the private key.
  openssl_sign($data, $signature, $this->private_key);

  // Encode the signature result in Base64.
  $signature = base64_encode($signature);

  // Return the signature.
  return $signature;

}
Enter fullscreen mode Exit fullscreen mode

Verify Signature

public function verifySignature($params, $clientSignature) {

  // Convert request params array to string
  $data = http_build_query($params);

  // Base64 decode client's signature
  $clientSignature = base64_decode($clientSignature);

  // Verify signature using public key
  $result = openssl_verify($data, $clientSignature, $this->public_key);

  // Return true if signatures match
  return $result === 1;

}
Enter fullscreen mode Exit fullscreen mode

Use an SDK to call APIs

To make it easier for clients to call an API and perform signature verification, you can create a simple SDK. The SDK will provide encapsulated methods that you can use to easily call APIs and perform signature verification.

Here is the code for a simple SDK:

class APIClient {

  private $apiURL;
  private $signature;

  public function __construct($apiURL, $privateKeyPath, $publicKeyPath) {

    $this->apiURL = $apiURL;

    // Initialize signature validator
    $this->signature = new Signature($privateKeyPath, $publicKeyPath);

  }

  public function callAPI($params) {

    // Generate signature
    $signature = $this->signature->generateSignature($params);

    // Add signature to request parameters
    $params['signature'] = $signature;

    // Send API request
    $response = $this->sendRequest($params);

    // Verify signature
    $isValid = $this->signature->verifySignature($params, $response['signature']);

    // If verification succeeds, return API response data
    if ($isValid) {
      return $response['data'];
    } else {
      throw new Exception("Invalid signature");
    }

  }

  private function sendRequest($params) {

    // Use cURL library to send HTTP request
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $this->apiURL);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params)); 
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $response = curl_exec($ch);
    curl_close($ch);

    // Parse API response data
    return json_decode($response, true);

  }

}
Enter fullscreen mode Exit fullscreen mode

SDK usage example:


$apiURL = 'http://xyz.com/api.php';
$privateKeyPath = '/path/to/private.key'; 
$publicKeyPath = '/path/to/public.key';

// Create APIClient instance  
$client = new APIClient($apiURL, $privateKeyPath, $publicKeyPath);

// Prepare API request parameters
$params = array(
  'param1' => 'value1',
  'param2' => 'value2', 
);

try {

  // Call API and get response  
  $result = $client->callAPI($params);

  // Handle API response data
  // ...

} catch (Exception $e) {

  // Handle exception
  // ...

}
Enter fullscreen mode Exit fullscreen mode

Conclusion

This article demonstrated implementing API signature verification in PHP by generating a key pair with OpenSSL, creating signature functions with openssl_sign and openssl_verify, and building an SDK to simplify usage. Applying these cryptographic techniques secures API communications by allowing clients to digitally sign requests which can be validated by the server, preventing tampering and ensuring integrity.

The signature binding provides non-repudiation and protects against unauthorized access. While further enhancements are possible, the methods covered provide a solid foundation for applying signatures to safeguard APIs.

Top comments (0)