Skip to content

Commit

Permalink
Set the micalg header parameter correctly when using SHA-256.
Browse files Browse the repository at this point in the history
This took me the better part of a day to research and figure out,
so would appreciate a second pair of eyes and/or some testing.

New-ish versions of openssl use SHA-256 as the message digest alg.
when smime signing while other versions use SHA-1. This causes some
clients to reject the signature, which I believe to  be the correct
behavior.

PHP's openssl_pkcs7_* methods don't allow setting or reading the md
method so we are left with either parsing the entire DER binary
stream using something like phpseclib and pulling out the digest
method, forgoing the openssl_* methods and call the openssl executable's
smime tool to directly to do the signature, or we can use openssl executable's
asn1parse command  and search for a known string indicating SHA-256 is being used.

The first option is overkill, the second option would defeat the
purpose of having the more efficient openssl_* methods and would
require writing out a copy of the private key to temporary storage, so
I went with the third option.
  • Loading branch information
mrubinsk committed Apr 27, 2017
1 parent 076b00c commit 76c0d9d
Showing 1 changed file with 17 additions and 1 deletion.
18 changes: 17 additions & 1 deletion framework/Crypt/lib/Horde/Crypt/Smime.php
Expand Up @@ -245,7 +245,23 @@ public function signMIMEPart($mime_part, $params)
'application/pkcs7-signature'
);
// Per RFC 5751 [3.4.3.2], 'sha1' has been deprecated for 'sha-1'.
$smime_part->setContentTypeParameter('micalg', 'sha-1');
$micalg = 'sha-1';

// Newer versions of openssl use SHA-256 as the message digest.
// Unfortunately, the openssl_pkcs7_* methods don't let us specify this,
// or even get the to-be-used md method. We *could* properly parse
// the entire binary DER data stream to pull it out, or we can just
// search for sha256 in a known location of asn1parse output.
if (!empty($params['sslpath'])) {
$sslpath = escapeshellcmd($params['sslpath']);
$temp_sig = $this->_createTempFile('horde-smime');
file_put_contents($temp_sig, $smime_sign->getContents());
$asn1 = explode("\n", shell_exec($sslpath . ' asn1parse -inform DER -in ' . $temp_sig));
if (strpos($asn1[7], 'sha256') !== false) {
$micalg = 'sha-256';
}
}
$smime_part->setContentTypeParameter('micalg', $micalg);
$smime_part->addPart($mime_part);
$smime_part->addPart($smime_sign);

Expand Down

0 comments on commit 76c0d9d

Please sign in to comment.