Hossein Shourabi
Hossein Shourabi

Reputation: 456

How to publish the key in PEM format and serve the key with the content-type "text/plain" using php?

"I'm working with Google AMP cache. First, I generate a pair key (private-key.pem/public-key.pub) using PHP. I've used the below code:

<?php 


$pkGenerate = openssl_pkey_new(array(
    'private_key_bits' => 2048,
    'private_key_type' => OPENSSL_KEYTYPE_RSA
));


openssl_pkey_export($pkGenerate,$pkGeneratePrivate); 


$pkGenerateDetails = openssl_pkey_get_details($pkGenerate);
$pkGeneratePublic = $pkGenerateDetails['key'];

openssl_pkey_free($pkGenerate);

$pkImport = openssl_pkey_get_private($pkGeneratePrivate); 

$pkImportDetails = openssl_pkey_get_details($pkImport); 
$pkImportPublic = $pkImportDetails['key'];

file_put_contents('private-key.pem', $pkGeneratePrivate); 
file_put_contents($_SERVER['DOCUMENT_ROOT'].'/.well-known/amphtml/apikey.pub', $pkImportPublic); 

then verify the signature and make AMP google cache URL with below code:

function urlsafe_b64encode($string) {
    return str_replace(array('+','/','='),array('-','_',''), base64_encode($string));
}

$timestamp=time();
$ampBaseUrl = "https://www-example-com.cdn.ampproject.org";
$signatureUrl = '/update-cache/c/s/example.com/google-seo-articles/ten-signs-your-seo-company-is-not-a-shark/?amp_action=flush&amp_ts='.$timestamp;

// opening the private key
$pkeyid = openssl_pkey_get_private("file://private-key.pem");
// generating the signature
openssl_sign($signatureUrl, $signature, $pkeyid, OPENSSL_ALGO_SHA256);
openssl_free_key($pkeyid);
// urlsafe base64 encoding
$signature = urlsafe_b64encode($signature);
// final url for updating
$ampUrl = $ampBaseUrl.$signatureUrl."&amp_url_signature=".$signature;
$ampUrl = str_replace("&", "&amp", $ampUrl);
echo $ampUrl."\n";

output :

https://www-example-com.cdn.ampproject.org/update-cache/c/s/example.com/google-seo-articles/ten-signs-your-seo-company-is-not-a-shark/?amp_action=flush&amp_ts=1564374402&amp_url_signature=Wtnae4vEz5cn0El8bKBh6xLSiqhy2YmMEwyp3tbR5OzD7Ym4-MCE926p1IuJBMSUjmoaRZpBHDvvG-sdgtTQijYpHJ9QiNRvR4w_b92ZeeInQ5qxVW93gZzVq6ODlwPP8aphkT6635ny9bgHWblQTz0Np0XA9my-roVaRqAPRH1NgBRyQFcJAoLNhBITy4ta94mn4qModJRVCwjPxich_N1ZLLXgPtp4KBZl2sYWTnROhJ-OujFDHA-2E7_DT-hMte7WjP_lBQLffkmwCTTTI2lrXaYwzSWx9MJYDqmnC1o0rGH3PW4y6R6xQ2jRVK9vaNSQTixVylBmMQFPbzVKVQ

When I checking the output with browser google return Error 403 and Invalid public key due to ingestion error: Invalid Content

I've researched about Error 403 and I think my issue with the content-type public key.

The Google AMP cache guideline wrote

You must publish the key in PEM format and serve the key with the content-type "text/plain". 

I've checked my content-type public key with below curl

curl -H 'Accept-Encoding: gzip' -i https://www.example.com/.well-known/amphtml/apikey.pub

Output:

HTTP/1.1 200 OK
Date: Mon, 29 Jul 2019 04:38:58 GMT
Content-Type: application/x-mspublisher
Content-Length: 451
Connection: keep-alive
Set-Cookie: __cfduid=dc3c0780a997f6ddf625019d3cf579a991564375138; expires=Tue, 28-Jul-20 04:38:58 GMT; path=/; domain=.example.com;HttpOnly
Last-Modified: Sun, 28 Jul 2019 17:48:39 GMT
Accept-Ranges: bytes
Vary: User-Agent
X-Turbo-Charged-By: LiteSpeed
Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Server: cloudflare
CF-RAY: 4fdc68069ff5e0fa-IAD

it shows Content-Type: application/x-mspublisher !

So, I want to change Content-Type: application/x-mspublisher to plain/text.

Please correct me if I am wrong.

thanks in advance.

Upvotes: 1

Views: 1294

Answers (1)

AltShiftZero
AltShiftZero

Reputation: 363

The extension you are using for your published apikey is '.pub' which is most probably linked to the mimetype application/x-mspublisher (MS Publisher). You could change the extension for your filename to .txt, which is the most easiest solution. You could also do the following:

  • Change the mimetype definition for .pem (or .pub) files within your webservers configuration. Depending on your OS (Linux/Windows/etc.) this may be done in /etc/mime.types or when using IIS on Windows using the IIS Management Console.

  • Change the mimetype of the file using a .htaccess (apache) or web.config (IIS).

When using .htaccess you can add the following rule in the file:

AddType text/plain pub 

When using IIS you can add the following lines in your Web.Config. Make sure you remove the previous declaration before adding the new one:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <staticContent>
            <remove fileExtension=".pub" />
            <mimeMap fileExtension=".pub" mimeType="text/plain" />
        </staticContent>
    </system.webServer>
</configuration>

Just as a tip: using this line file_put_contents('private-key.pem', $pkGeneratePrivate); depending on where your code is running in the webroot, you are probably storing the private key in a publicly accessable location. You might want to change that to a location outside your webroot.

Upvotes: 3

Related Questions