180 $this->_privateKey = $privateKey;
181 $this->_domainName = $domainName;
182 $this->_signerIdentity =
'@'.$domainName;
183 $this->_selector = $selector;
195 public static function newInstance($privateKey, $domainName, $selector)
197 return new static($privateKey, $domainName, $selector);
207 $this->_headerHash = null;
208 $this->_signedHeaders = array();
209 $this->_headerHashHandler = null;
210 $this->_bodyHash = null;
211 $this->_bodyHashHandler = null;
212 $this->_bodyCanonIgnoreStart = 2;
213 $this->_bodyCanonEmptyCounter = 0;
214 $this->_bodyCanonLastChar = null;
215 $this->_bodyCanonSpace =
false;
237 foreach ($this->_bound as $is) {
264 $this->_bound[] = $is;
280 foreach ($this->_bound as $k => $stream) {
281 if ($stream === $is) {
282 unset($this->_bound[$k]);
312 if ($hash ==
'rsa-sha1') {
313 $this->_hashAlgorithm =
'rsa-sha1';
315 $this->_hashAlgorithm =
'rsa-sha256';
330 if ($canon ==
'relaxed') {
331 $this->_bodyCanon =
'relaxed';
333 $this->_bodyCanon =
'simple';
348 if ($canon ==
'relaxed') {
349 $this->_headerCanon =
'relaxed';
351 $this->_headerCanon =
'simple';
366 $this->_signerIdentity = $identity;
381 $this->_showLen =
true;
382 $this->_maxLen = PHP_INT_MAX;
383 }
elseif ($len ===
false) {
384 $this->showLen =
false;
385 $this->_maxLen = PHP_INT_MAX;
387 $this->_showLen =
true;
388 $this->_maxLen = (int) $len;
403 $this->_signatureTimestamp = $time;
417 $this->_signatureExpiration = $time;
431 $this->_debugHeaders = (bool) $debug;
442 switch ($this->_hashAlgorithm) {
444 $this->_bodyHashHandler = hash_init(
'sha256');
447 $this->_bodyHashHandler = hash_init(
'sha1');
450 $this->_bodyCanonLine =
'';
468 if ($this->_debugHeaders) {
469 return array(
'DKIM-Signature',
'X-DebugHash');
471 return array(
'DKIM-Signature');
484 $this->_ignoredHeaders[strtolower($header_name)] =
true;
498 $this->_headerCanonData =
'';
500 $listHeaders = $headers->
listAll();
501 foreach ($listHeaders as $hName) {
503 if (!isset($this->_ignoredHeaders[strtolower($hName)])) {
504 if ($headers->
has($hName)) {
505 $tmp = $headers->
getAll($hName);
506 foreach ($tmp as $header) {
507 if ($header->getFieldBody() !=
'') {
509 $this->_signedHeaders[] = $header->getFieldName();
529 $params = array(
'v' =>
'1',
'a' => $this->_hashAlgorithm,
'bh' => base64_encode($this->_bodyHash),
'd' => $this->_domainName,
'h' => implode(
': ', $this->_signedHeaders),
'i' => $this->_signerIdentity,
's' => $this->_selector);
530 if ($this->_bodyCanon !=
'simple') {
532 }
elseif ($this->_headerCanon !=
'simple') {
535 if ($this->_showLen) {
538 if ($this->_signatureTimestamp ===
true) {
539 $params[
't'] = time();
540 if ($this->_signatureExpiration !==
false) {
544 if ($this->_signatureTimestamp !==
false) {
547 if ($this->_signatureExpiration !==
false) {
551 if ($this->_debugHeaders) {
552 $params[
'z'] = implode(
'|', $this->_debugHeadersData);
555 foreach ($params as $k => $v) {
556 $string .= $k.
'='.$v.
'; ';
558 $string = trim($string);
561 $tmp = $headers->
getAll(
'DKIM-Signature');
562 $this->_dkimHeader = end($tmp);
563 $this->
_addHeader(trim($this->_dkimHeader->toString()).
"\r\n b=",
true);
565 if ($this->_debugHeaders) {
566 $headers->
addTextHeader(
'X-DebugHash', base64_encode($this->_headerHash));
568 $this->_dkimHeader->setValue($string.
' b='.trim(chunk_split(base64_encode($this->
_getEncryptedHash()), 73,
' ')));
577 switch ($this->_headerCanon) {
580 $exploded = explode(
':', $header, 2);
581 $name = strtolower(trim($exploded[0]));
582 $value = str_replace(
"\r\n",
'', $exploded[1]);
583 $value = preg_replace(
"/[ \t][ \t]+/",
' ', $value);
584 $header = $name.
':'.trim($value).($is_sig ?
'' :
"\r\n");
598 $len = strlen($string);
600 $method = ($this->_bodyCanon ==
'relaxed');
601 for ($i = 0; $i < $len; ++$i) {
602 if ($this->_bodyCanonIgnoreStart > 0) {
606 switch ($string[$i]) {
608 $this->_bodyCanonLastChar =
"\r";
611 if ($this->_bodyCanonLastChar ==
"\r") {
613 $this->_bodyCanonSpace =
false;
615 if ($this->_bodyCanonLine ==
'') {
618 $this->_bodyCanonLine =
'';
629 $this->_bodyCanonSpace =
true;
633 if ($this->_bodyCanonEmptyCounter > 0) {
634 $canon .= str_repeat(
"\r\n", $this->_bodyCanonEmptyCounter);
635 $this->_bodyCanonEmptyCounter = 0;
637 if ($this->_bodyCanonSpace) {
638 $this->_bodyCanonLine .=
' ';
640 $this->_bodyCanonSpace =
false;
642 $this->_bodyCanonLine .= $string[$i];
643 $canon .= $string[$i];
652 if (strlen($this->_bodyCanonLine) > 0) {
655 $this->_bodyHash = hash_final($this->_bodyHashHandler,
true);
660 $len = strlen($string);
661 if ($len > ($new_len = ($this->_maxLen - $this->_bodyLen))) {
662 $string = substr($string, 0, $new_len);
665 hash_update($this->_bodyHashHandler, $string);
666 $this->_bodyLen += $len;
671 if ($this->_debugHeaders) {
672 $this->_debugHeadersData[] = trim($header);
674 $this->_headerCanonData .= $header;
685 switch ($this->_hashAlgorithm) {
687 $algorithm = OPENSSL_ALGO_SHA1;
690 $algorithm = OPENSSL_ALGO_SHA256;
693 $pkeyId = openssl_get_privatekey($this->_privateKey);
697 if (openssl_sign($this->_headerCanonData, $signature, $pkeyId, $algorithm)) {