【问题标题】:Sending Encrypted Email S/MIME with PHP使用 PHP 发送加密电子邮件 S/MIME
【发布时间】:2017-08-07 09:20:58
【问题描述】:

我在网上找了很多,但没有找到答案,是否可以使用 PHP 发送加密电子邮件 S/MIME?如果是,如何? (我使用的是 cakephp 2.x)

非常感谢您

【问题讨论】:

  • 你可以查看 CakePHP 2 的插件 github.com/LubosRemplik/CakePHP-Encrypt-Plugin
  • 谢谢,但这仅适用于 pgp。
  • M A SIDDIQUI 这样的答案不是很有帮助....
  • 当你问是/否问题时,你会得到这样的结果,总会有人从字面上理解它 :) 如果你指出你遇到的特定编程相关问题,你通常会得到更好的答案面对。

标签: php cakephp encryption digital-certificate smime


【解决方案1】:

我设法使用 PHPMailer 找到了解决方案,它也适用于常规 PHP。它将对电子邮件进行签名和加密,我找不到使用 PHPMailer(签名和加密)仅签名的方法,所以我在 class.phpmailer.php 中添加了一些代码。它仍然需要在加密错误的情况下添加一些错误处理,但到目前为止效果很好。

对于 CakePHP 2.x:

下载 PHPMailer 并将其添加到您的 Vendors 文件夹 (project_name/app/vendor)

在函数的开头添加这一行:

App::import('Vendor','PHPMailer/PHPMailerAutoload');

从这里它对于 PHP 或 CakePHP 是一样的:

 $mail = new PHPMailer(); 
 $mail->setFrom('from_who@email', 'Intranet');
 //Set who the message is to be sent to 
 $mail->addAddress('to_who@email', 'Ricardo V'); 
 //Set the subject line 
 $mail->Subject = 'PHPMailer signing test';
 //Replace the plain text body with one created manually 
 $mail->Body = "some encrypted text...";
 //Attach an image file 
 $mail->addAttachment('D:/path_to_file/test.pdf'); 
 $mail->sign( 
     'app/webroot/cert/cert.crt', //The location of your certificate file 
     'app/webroot/cert/private.key', //The location of your private key
 file 
     'password', //The password you protected your private key with (not 
    //the Import Password! may be empty but parameter must not be omitted!) 
     'app/webroot/cert/certchain.pem', //the certificate chain.
     '1', //Encrypt the email as well, (1 = encrypt, 0 = dont encrypt)
     'app/webroot/cert/rvarilias.crt'//The location of public certificate 
   //to encrypt the email with.
 ); 
 if (!$mail->send()) { 
     echo "Mailer Error: " . $mail->ErrorInfo; 
 } else { 
     echo "Message sent!"; 
 } 

然后我们需要对class.phpmailer.php进行一些修改

将 2368 到 2390 的行替换为:

$sign = @openssl_pkcs7_sign(
                    $file,
                    $signed,
                    'file://' . realpath($this->sign_cert_file),
                    array('file://' . realpath($this->sign_key_file), 
$this->sign_key_pass),
                    null,
                    PKCS7_DETACHED,
                    $this->sign_extracerts_file
                );
                if ($this->encrypt_file == 1) {
                    $encrypted = tempnam(sys_get_temp_dir(), 'encrypted');
                    $encrypt = @openssl_pkcs7_encrypt(
                    $signed,
                    $encrypted,
                    file_get_contents($this->encrypt_cert_file),
                    null,
                    0,
                    1
                );
                if ($encrypted) {
                    @unlink($file);
                    $body = file_get_contents($encrypted);
                    @unlink($signed);
                    @unlink($encrypted);
                    //The message returned by openssl contains both headers
and body, so need to split them up
                    $parts = explode("\n\n", $body, 2);
                    $this->MIMEHeader .= $parts[0] . $this->LE . $this->LE;
                    $body = $parts[1];
                } else {
                    @unlink($file);
                    @unlink($signed);
                    @unlink($encrypted);
                    throw new phpmailerException($this->lang('signing') .
openssl_error_string());
                }
                } else {

                if ($signed) {
                    @unlink($file);
                    $body = file_get_contents($signed);
                    @unlink($signed);
                    //The message returned by openssl contains both headers
 and body, so need to split them up
                    $parts = explode("\n\n", $body, 2);
                    $this->MIMEHeader .= $parts[0] . $this->LE . $this->LE;
                    $body = $parts[1];
            } else {
                    @unlink($file);
                    @unlink($signed);
                    throw new phpmailerException($this->lang('signing') .  
 openssl_error_string());
            }

                   } 

            }

然后寻找:

public function sign($cert_filename, $key_filename, $key_pass,   
$extracerts_filename = '')
{
    $this->sign_cert_file = $cert_filename;
    $this->sign_key_file = $key_filename;
    $this->sign_key_pass = $key_pass;
    $this->sign_extracerts_file = $extracerts_filename;
}

并将其更改为:

public function sign($cert_filename, $key_filename, $key_pass,
$extracerts_filename = '', $and_encrypt ='0', $encrypt_cert = '')
    {
        $this->sign_cert_file = $cert_filename;
        $this->sign_key_file = $key_filename;
        $this->sign_key_pass = $key_pass;
        $this->sign_extracerts_file = $extracerts_filename;
        $this->encrypt_file = $and_encrypt;
        $this->encrypt_cert_file = $encrypt_cert;
    }

寻找:

protected $sign_extracerts_file = '';

并在其后添加以下行:

protected $encrypt_cert = '';
protected $and_encrypt = '';

通过对 phpmailer 的这些更改,您可以发送签名的电子邮件或签名和加密的电子邮件。它也适用于附件。

我希望它对某人有所帮助。

*对于普通的 php,只是不要添加该行:

App::import('Vendor','PHPMailer/PHPMailerAutoload');

【讨论】:

  • 我如何生成公共证书(您的最后一个参数 [rvarilias.crt' - 用于加密电子邮件的公共证书的位置。])以使用 export.pfx 加密电子邮件(证书生成自comodo 通过 Internet Explorer 浏览器)
猜你喜欢
  • 2018-08-08
  • 2012-02-18
  • 2013-02-10
  • 2018-09-09
  • 2010-10-30
  • 2019-09-03
  • 2016-12-22
  • 2011-01-08
  • 2012-03-20
相关资源
最近更新 更多