How to Timestamp Files in PHP

Qualified Timestamping in PHP

Learn how to request and verify qualified RFC 3161 timestamps in PHP using cURL and OpenSSL functions.

Prerequisites:

  • PHP 7.4+ or PHP 8.x installed.
  • curl and openssl PHP extensions enabled.
  • TSA Certificate Chain (for offline verification): Download TSAChain.zip.

Step 1: Request a Timestamp Token (.tsr)

Generate an RFC 3161 request query using OpenSSL CLI via exec() or send a pre-constructed request binary through cURL:

<?php
function requestTimestamp($filePath, $outputTsrPath, $tsaUrl) {
    $tsqPath = $filePath . ".tsq";

    // 1. Generate RFC 3161 timestamp query using OpenSSL
    $cmd = "openssl ts -query -data " . escapeshellarg($filePath) . " -sha256 -cert -out " . escapeshellarg($tsqPath);
    exec($cmd, $output, $returnCode);

    if ($returnCode !== 0) {
        throw new Exception("Failed to generate OpenSSL timestamp query.");
    }

    // 2. Send binary query via cURL
    $tsqData = file_get_contents($tsqPath);
    $ch = curl_init($tsaUrl);
    
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $tsqData);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        "Content-Type: application/timestamp-query"
    ]);

    $tsrData = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    // Clean up temporary query file
    unlink($tsqPath);

    if ($httpCode === 200 && $tsrData) {
        file_put_contents($outputTsrPath, $tsrData);
        echo "[SUCCESS] Timestamp response saved to: {$outputTsrPath}\n";
        return true;
    }

    throw new Exception("TSA Server responded with HTTP code: {$httpCode}");
}

Step 2: Verify the Timestamp Token (.tsr)

Verify the received .tsr token against the original document using OpenSSL verification:

function verifyTimestamp($filePath, $tsrPath, $caChainPath) {
    $cmd = "openssl ts -verify -data " . escapeshellarg($filePath) .
           " -in " . escapeshellarg($tsrPath) .
           " -CAfile " . escapeshellarg($caChainPath);

    exec($cmd, $output, $returnCode);

    if ($returnCode === 0) {
        echo "[SUCCESS] Timestamp is valid!\n";
        return true;
    }

    echo "[ERROR] Verification failed!\n";
    return false;
}

Execution Example

Run the script directly in your PHP backend application:

$fileToSign = "document.pdf";
$tsrOutput  = "document.pdf.tsr";
$tsaUrl     = "https://tsaexample.com/myserver.aspx";
$caChain    = "TSAChain.pem";

// 1. Request Timestamp
requestTimestamp($fileToSign, $tsrOutput, $tsaUrl);

// 2. Verify Timestamp
verifyTimestamp($fileToSign, $tsrOutput, $caChain);