Can't get DomainKeys to work with PHP mail(), bad sig?

Discussions of secure PHP coding. Security in software is important, so don't be afraid to ask. And when answering: be anal. Nitpick. No security vulnerability is too small.

Moderator: General Moderators

Post Reply
User avatar
Apollo
Forum Regular
Posts: 794
Joined: Wed Apr 30, 2008 2:34 am

Can't get DomainKeys to work with PHP mail(), bad sig?

Post by Apollo »

In order to send authenticated mail from my website using the default mail() function, I plucked some info about DomainKeys from http://domainkeys.sourceforge.net/ and in particular RFC4870.

Here's my code:

Code: Select all

<?php
 
// initialize key
$privatePem = "-----BEGIN RSA PRIVATE KEY-----
MIII5RV/0k9USo...etc...hXF2Vh7T4yfT5QN
-----END RSA PRIVATE KEY-----";
 
$encKey = @openssl_pkey_get_private( $privatePem );
if (!$encKey) die("Unable to extract encryption key");
 
// setup email message
$to        = "example@gmail.com"; // random gmail or yahoo test account
$myAddress = "myname@mydomain.com";
$subject   = "Hello";
$body      = "Hi, this is a test message";
 
$fromHeader = "From: $myAddress";
 
// create canonicalizated message (using 'simple' convention)
$canonLines = array();
$canonLines[] = $fromHeader;
$canonLines[] = ""; // the empty line between headers and body
$canonLines[] = $body; // body just consists of one line here (with no line-ending)
 
$crlf = "\r\n";
$canonTxt = implode($crlf,$canonLines).$crlf;
 
// create checksum
$hexHash = sha1($canonTxt); // this is for php4 compatibility,
$rawHash = pack('H*',$hexHash); // with php5 we can simply do sha1($txt,true) to get binary result
 
// encrypt + encode
if (!@openssl_private_encrypt( $rawHash, $encryptedHash, $encKey )) die("Unable to encrypt hash");
$dkey = base64_encode($encryptedHash);
 
// setup custom headers
$headers = "DomainKey-Signature: a=rsa-sha1; s=mail; d=mydomain.com; h=From; q=dns; c=simple; b=$dkey;\n";
$headers .= "$fromHeader\n";
 
// send mail
$success = mail( $to , $subject , $body , $headers );
die( $success ? "mail sent" : "mail NOT sent" );
 
?>
I have setup the appropriate public RSA key in my domain's DNS settings (policy and selector TXT records for domainkey.mydomain.com and mail._domainkey.mydomain.com), and verified them with these two thingies. Policy is "o=~; t=y;"

Unfortunately, when I send a mail like this, both gmail and yahoo report domainkeys = bad or fail (bad sig).

Note that I included the h=From in the signature on purpose. Since PHP mail() and my provider's SMTP server will both add additional headers (which I can't take along in my signature checksum) I want to explicitly use only a header I can calculate. So in the end, the complete mail will look something like this:
(...some headers...)
DomainKey-Signature: blablabla
From: my@address
(...some more headers...)

Body consisting of one line
and by using only the From: header I can make sure in advance what the canonicalizated message (on which the DomainKeys signature is calced) needs to be.

If anybody knows how DomainKeys works and can see what I'm doing wrong, you'd definitely make my day! :mrgreen:
User avatar
Apollo
Forum Regular
Posts: 794
Joined: Wed Apr 30, 2008 2:34 am

Re: Can't get DomainKeys to work with PHP mail(), bad sig?

Post by Apollo »

In addition, here's an email as I received it on gmail (in "show original" format, replaced my name + domain)

Code: Select all

Delivered-To: myname@gmail.com
Received: by 10.141.69.10 with SMTP id w1030rcs82vk;
        Wed, 30 Apr 2008 01:18:01 -0700 (PDT)
Received: by 10.210.144.13 with SMTP id r1934mr0375ebd.60.1209543479454;
        Wed, 30 Apr 2008 01:17:59 -0700 (PDT)
Return-Path: <nobody@degas.hmdnsgroup.com>
Received: from degas.hmdnsgroup.com (degas.hmdnsgroup.com [63.247.142.207])
        by mx.google.com with ESMTP id j170s43064muh.2.2008.04.30.01.17.56;
        Wed, 30 Apr 2008 01:17:59 -0700 (PDT)
Received-SPF: pass (google.com: best guess record for domain of nobody@degas.hmdnsgroup.com designates 63.247.142.207 as permitted sender) client-ip=63.247.142.207;
DomainKey-Status: bad
Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of nobody@degas.hmdnsgroup.com designates 63.247.142.207 as permitted sender) smtp.mail=nobody@degas.hmdnsgroup.com; domainkeys=hardfail header.From=myname@mydomain.com
Received: from nobody by degas.hmdnsgroup.com with local (Exim 4.68)
    (envelope-from <nobody@degas.hmdnsgroup.com>)
    id 1Pd4CK-0006FD-MW
    for myname@gmail.com; Wed, 30 Apr 2008 04:17:39 -0400
To: myname@gmail.com
Subject: Hello
DomainKey-Signature: a=rsa-sha1; s=mail; d=mydomain.com; h=From; q=dns; c=simple; b=ZfETIOjUZDJU9GJWqKpFdk2ui/UdxRyr/8FkYNPNbyUDcxHGE7wJdV8t6YUXyp8MdHQqnd902QtKgu65nQU5eClLdwdeK9jKZIDL6F6fl7uwbdkXTChmLC3yAJ9jFhXp8XI3HVDig5NeRS6W9krPDuYRvn3Y45laInOtffrbp/Y;
From: myname@mydomain.com
Message-Id: <1Pd4CK-0006FD-MW@degas.hmdnsgroup.com>
Date: Wed, 30 Apr 2008 04:17:39 -0400
X-HMDNSGroup-MailScanner-Information: Please contact the ISP for more information
X-MailScanner-ID: 1Pd4CK-0006FD-MW
X-HMDNSGroup-MailScanner-SpamCheck: 
X-HMDNSGroup-MailScanner-From: nobody@degas.hmdnsgroup.com
X-AntiAbuse: This header was added to track abuse, please include it with any abuse report
X-AntiAbuse: Primary Hostname - degas.hmdnsgroup.com
X-AntiAbuse: Original Domain - gmail.com
X-AntiAbuse: Originator/Caller UID/GID - [99 99] / [47 12]
X-AntiAbuse: Sender Address Domain - degas.hmdnsgroup.com
 
Hi, this is another test message
All those X-etc headers are added by the SMTP server of my provider (Hosting Matters).
Post Reply