杉哥的个人博客

RSA公私钥的理解和示例说明与php中的使用

先放重点:公钥和私钥是成对的,它们互相解密。

公钥加密,私钥解密。

私钥数字签名,公钥验证。

加密、解密:举例, A、B之间相互传东西,A拥有A的私钥、B的公钥;B拥有B的私钥、A的公钥;这样当A给B传信息的时候,用B的公钥加密,这样只有B才能解密,保证了信息的安全。同理,B给A传信息是一样的。

签名、验签:主要是完成不可抵赖的作用。例如,A用私钥签名,然后用签名结果和A的公钥,就可以验证信息肯定是A发送的,而不是其他人发送的。

1、生成公钥和私钥

要应用RSA算法,必须先生成公钥和私钥,公钥和私钥的生成可以借助OpenSSL工具。

OpenSSL, Linux 上自带,常用命令如下:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
-- 生成 RSA 私钥(传统格式的)
$ openssl genrsa -out rsa_private_key.pem 1024
-- 将传统格式的私钥转换成 PKCS#8 格式的(JAVA需要使用的私钥需要经过PKCS#8编码)
$ openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt
-- 生成 RSA 公钥
$ openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
-- 生成 RSA 私钥(传统格式的) $ openssl genrsa -out rsa_private_key.pem 1024 -- 将传统格式的私钥转换成 PKCS#8 格式的(JAVA需要使用的私钥需要经过PKCS#8编码) $ openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt -- 生成 RSA 公钥 $ openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
-- 生成 RSA 私钥(传统格式的)
$ openssl genrsa -out rsa_private_key.pem 1024
-- 将传统格式的私钥转换成 PKCS#8 格式的(JAVA需要使用的私钥需要经过PKCS#8编码)
$ openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt
-- 生成 RSA 公钥
$ openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

 

一点小坑:直接将密钥复制进文件中可能导致格式不对,可以这样处理

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$priKey='你的密钥';
$res = "-----BEGIN RSA PRIVATE KEY-----\n" .
wordwrap($priKey, 64, "\n", true) .
"\n-----END RSA PRIVATE KEY-----";
$priKey='你的密钥'; $res = "-----BEGIN RSA PRIVATE KEY-----\n" . wordwrap($priKey, 64, "\n", true) . "\n-----END RSA PRIVATE KEY-----";
$priKey='你的密钥';
$res = "-----BEGIN RSA PRIVATE KEY-----\n" .
wordwrap($priKey, 64, "\n", true) .
"\n-----END RSA PRIVATE KEY-----";

在天机、融360中的使用:

使用场景有:加密、解密、签名、验签这几种,业务场景属于后两种情形业务方 向 融360 发送支付请求,将sign参数通过自己的私钥加密过后发送到融360的接口; (业务方签名sign 属于第二种情形:签名.)

融360 向 业务方 发送支付回调结果,将sign参数通过自己的私钥加密过后发送到业务方的notify接口;(解密融360回调sign验签 属于第二种情形:解密 可俗称验签.)

注:融360使用的加密函数是openssl_sign,之后的校验可以使用openssl_verify函数进行校验。


Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
if( !openssl_verify($this->data, base64_decode($input['sign']), $orgPublicKey))
if( !openssl_verify($this->data, base64_decode($input['sign']), $orgPublicKey))
if( !openssl_verify($this->data, base64_decode($input['sign']), $orgPublicKey))
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
protected function sign($data)
{
$priKey=$this->Config[$this->_action]['private_key'];
$res = "-----BEGIN RSA PRIVATE KEY-----\n" .
wordwrap($priKey, 64, "\n", true) .
"\n-----END RSA PRIVATE KEY-----";
openssl_sign($data, $sign,$res );
trace('ssl_error:'.openssl_error_string(), $this->_action);
$sign = base64_encode($sign);
return $sign;
}
protected function sign($data) { $priKey=$this->Config[$this->_action]['private_key']; $res = "-----BEGIN RSA PRIVATE KEY-----\n" . wordwrap($priKey, 64, "\n", true) . "\n-----END RSA PRIVATE KEY-----"; openssl_sign($data, $sign,$res ); trace('ssl_error:'.openssl_error_string(), $this->_action); $sign = base64_encode($sign); return $sign; }
protected function sign($data) 
    {
        $priKey=$this->Config[$this->_action]['private_key'];
        $res = "-----BEGIN RSA PRIVATE KEY-----\n" .
                wordwrap($priKey, 64, "\n", true) .
                "\n-----END RSA PRIVATE KEY-----";
        openssl_sign($data, $sign,$res );
        trace('ssl_error:'.openssl_error_string(), $this->_action);
        
        $sign = base64_encode($sign);
        return $sign;
    }