对接某平台时,要求使用RSA加密消息传输,提供的公钥如下:

MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDuduPhifW7Mp5K80tVHS-R-lOD_OO5u2ZVNRELJlfiwF8hdKr1zt5VJ_IfWdx990Qrln2InN_Aym0phg5SVw2hDrwMTeQBOPsFXv-Ts0tcbnr4UpCsBR37N4ZXfJrKXcNihWBYdfFGj0EchiMJmdQawIHf–d1HQxt2fSojoOARwIDAQAB

使用这个公钥加密之后报错了,返回

openssl_public_encrypt(): key parameter is not a valid public key

发现 openssl_pkey_get_public($publicKey); 返回 false。

注: 我已添加 :$public_key = “-----BEGIN PUBLIC KEY-----\n” . $public_key . “\n-----END PUBLIC KEY-----”;

搜了一天的资料,也没有找到这种问题的相关内容。

之后对方提供了JAVA的示例代码,在查询代码时发现有一处

> String publicKeyStr = Base64.encodeBase64URLSafeString(publicKey.getEncoded());

查阅资料发现这个encodeBase64URLSafeString是为了防止在url传输base64的时候不能正确传递base64所作出的转义。

转义代码如下:

public static function url_safe_decode($string)
    $data = str_replace(['-','_'], ['+','/'], $string);
    $mod4 = strlen($data) % 4;
    if ($mod4)
        $data .= substr('====', $mod4);
    return $data;
public static function url_safe_encode($string)
    return str_replace(['+','/','='], ['-','_',''], $string);

到这终于知道了,原来对方给的公钥是经过转义之后的公钥,对方也没说明公钥被他转义过了,我找过去的时候还说公钥没有问题,在这上面耗费了挺长时间的。

$str = '123456';
$public_key = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDuduPhifW7Mp5K80tVHS-R-lOD_OO5u2ZVNRELJlfiwF8hdKr1zt5VJ_IfWdx990Qrln2InN_Aym0phg5SVw2hDrwMTeQBOPsFXv-Ts0tcbnr4UpCsBR37N4ZXfJrKXcNihWBYdfFGj0EchiMJmdQawIHf--d1HQxt2fSojoOARwIDAQAB';
$public_key = RsaUtil::url_safe_decode($public_key);
$public_key = "-----BEGIN PUBLIC KEY-----\n" . $public_key . "\n-----END PUBLIC KEY-----";
$encrypted = RsaUtil::publicEncrypt($str, $public_key);

下面贴出完整RsaUtil代码:

namespace App\Helpers; class RsaUtil private static function getPublicKey($publicKey) return openssl_pkey_get_public($publicKey); private static function getPrivateKey($privateKey) return openssl_pkey_get_private($privateKey); public static function publicEncrypt($data, $publicKey) if (!is_string($data)) { return null; return openssl_public_encrypt($data, $encrypted, self::getPublicKey($publicKey)) ? base64_encode($encrypted) : null; public static function publicDecrypt($encrypted, $publicKey) if (!is_string($encrypted)) { return null; return (openssl_public_decrypt(base64_decode($encrypted), $decrypted, self::getPublicKey($publicKey))) ? $decrypted : null; public static function privateEncrypt($data, $privateKey) if(!is_string($data)){ return null; return openssl_private_encrypt($data, $encrypted, self::getPrivateKey($privateKey)) ? base64_encode($encrypted) : null; public static function privateDecrypt($encrypted, $privateKey) if(!is_string($encrypted)){ return null; return (openssl_private_decrypt(base64_decode($encrypted), $decrypted, self::getPrivateKey($privateKey)))? $decrypted : null; * @param $string * @return string|string[] * url安全解码 public static function url_safe_decode($string) $data = str_replace(['-','_'], ['+','/'], $string); $mod4 = strlen($data) % 4; if ($mod4) $data .= substr('====', $mod4); return $data; * @param $string * @return string|string[] * url安全转码 public static function url_safe_encode($string) return str_replace(['+','/','='], ['-','_',''], $string); 记一次RSA公钥加密失败的问题情景再现对接某平台时,要求使用RSA加密消息传输,提供的公钥如下:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDuduPhifW7Mp5K80tVHS-R-lOD_OO5u2ZVNRELJlfiwF8hdKr1zt5VJ_IfWdx990Qrln2InN_Aym0phg5SVw2hDrwMTeQBOPsFXv-Ts0tcbnr4... 警告:使用风险自负。 未经广泛测试或审查。 可能包含严重的错误。 另请参阅: 。 为rust-openssl编写的示例代码: let mut shared_e = vec! [ 0 ; rsa. size () as usize ]; let mut token_e = vec! [ 0 ; rsa. size () as usize ]; rsa. public_encrypt ( & shared, & mut shared_e, Padding :: PKCS1)?; rsa. public_encrypt ( & packet.verify_token.da
本地PHP 7.0.8,一下代码运行OK function getAuthorizedUrl($base_url, $encrypted_params, $non_encrypted_params = []) $appId = '1111'; $pid = '111111'; $public_key = "-----BEGIN PUBLIC KEY-----\nMy p...
以下是使用OpenSSLRSA_public_encrypt函数进行分段加密的一个示例代码:#include <openssl/rsa.h> #include <openssl/bio.h> #include <openssl/pem.h> #include <assert.h>// 加密函数,用公钥加密 int public_encrypt(unsigned char* data, int data_len, unsigned char* key, unsigned char* encrypted) // 公钥 RSA * rsa = createRSA(key, 1); // 加密后的长度 int length = RSA_size(rsa); // 分段加密 int offset = 0; int inputLen = data_len; while (inputLen > 0) // 计算本次加密长度 int encryptLen = inputLen > length - 11 ? length - 11 : inputLen; int ret = RSA_public_encrypt(encryptLen, data + offset, encrypted + offset, rsa, RSA_PKCS1_PADDING); // 加密出错 if (ret < 0) return ret; offset += ret; inputLen -= encryptLen; return offset; }// 生成RSA公钥 RSA * createRSA(unsigned char* key, int isPublic) // 将公钥文本转换为BIO类型 BIO* bio = BIO_new_mem_buf(key, -1); // 从BIO类型中读取公钥 RSA* rsa = NULL; if(isPublic) rsa = PEM_read_bio_RSA_PUBKEY(bio, &rsa, NULL, NULL); rsa = PEM_read_bio_RSAPrivateKey(bio, &rsa, NULL, NULL); // 释放BIO类型 BIO_free_all(bio); return rsa;