今天在使用easywechat對接企業打款到銀行卡時,遇到了兩個錯誤
error:0906D064:PEM routines:PEM_read_bio:bad base64 decode 和 error:0906D06C:PEM routines:PEM_read_bio:no start line 。
這是因為想要正確的使用密鑰,需要滿足以下三個條件。
- 公共密鑰的開頭需要加上"-----BEGIN RSA PUBLIC KEY-----\n",結尾需要加上"\n-----BEGIN RSA PUBLIC KEY-----\n"。不然會報 error:0906D06C:PEM routines:PEM_read_bio:no start line 。
- 公鑰字符串每隔64隔字符需要加一個換行,負責會報 error:0906D06C:PEM routines:PEM_read_bio:no start line 。
- 以上2步應該可以滿足有些語言的需求,但php不行,還需要講以上PKCS#1 格式密鑰轉換成PKCS#8 格式密鑰。
下面看下具體操作。按照文檔使用如下命令:
./vendor/bin/easywechat payment:rsa_public_key \ --mch_id=14339221228 \ --api_key=36YTbDmLgyQ52noqdxgwGiYy \ --cert_path=/Users/overtrue/www/demo/apiclient_cert.pem \ --key_path=/Users/overtrue/www/demo/apiclient_key.pem
將會在當前目錄生成一個 ./public-14339221228.pem
文件。
如果直接使用這個public key文件,會報一個非法的key錯誤,然后可以發現easywechat有這樣一段源碼。
function rsa_public_encrypt($content, $publicKey) { $encrypted = ''; openssl_public_encrypt($content, $encrypted, openssl_pkey_get_public($publicKey), OPENSSL_PKCS1_OAEP_PADDING); return base64_encode($encrypted); }
報非法key是因為 openssl_pkey_get_public($publicKey) 返回的是false,這時,你可以加一行代碼。
function rsa_public_encrypt($content, $publicKey) { $encrypted = ''; openssl_public_encrypt($content, $encrypted, openssl_pkey_get_public($publicKey), OPENSSL_PKCS1_OAEP_PADDING); var_dump(openssl_error_string()); return base64_encode($encrypted); }
這是會看到以下錯誤。
error:0906D06C:PEM routines:PEM_read_bio:no start line
這是因為easywechat直接生成的 public-14339221228.pem 文件中,key的格式是這樣的。
-----BEGIN RSA PUBLIC KEY-----MIIBCgKCAQEAuVvw3DeWx4wdDl2/I0aAMma2bH3hhU89rqMhJWvQ41uRbatxZxMZ13iEMXg8UfTBR+UGl+NCzpkkTjjcVm/2TcIdWgZCLr3Rzo4XD5hRLs8ExI+uzKnmar......CmtgTKWkqkhCnLwr7bRRzBUi3po7UDLWPePrH1ICd83/wIDAQAB-----END RSA PUBLIC KEY-----
這種格式是錯誤的,無法直接放到函數 openssl_pkey_get_public 中使用。需要對他進行格式化成如下形式。
-----BEGIN RSA PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuVvw3DeWx4wdDl2/I0aA Mma2bH3hhU89rqMhJWvQ41uRbatxZxMZ13iEMXg8UfTBR+UGl+NCzpkkTjjcVm/2 ...... ...... EXFyDtEykuiMuhn3A7WWNkc3voHML9C4kDWdJrX3wjQrwZbW3p3F1O/9pGHLNzn9 p3la2C9/Ve3jLdG8lEzvkCmtgTKWkqkhCnLwr7bRRzBUi3po7UDLWPePrH1ICd83 /wIDAQAB -----END RSA PUBLIC KEY-----
第一行是 -----BEGIN RSA PUBLIC KEY----- ,最后一行是 -----END RSA PUBLIC KEY----- ,然后中間的key每64個字符一行,可以用php的
wordwrap($key, 64, "\n", true)
函數處理。但這種是PKCS#1 格式密鑰。php是函數 openssl_pkey_get_public 也無法使用。需要將其轉換成PKCS#8 格式密鑰。可以用如下命令
openssl rsa -RSAPublicKey_in -in public-14339221228.pem -out public.pem
這種就是在當前目錄得到一個 public.pem 文件。里面存放的是PKCS#8 格式密鑰。這種密鑰格式是php可以使用的。密鑰如下:
-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuVvw3DeWx4wdDl2/I0aA Mma2bH3hhU89rqMhJWvQ41uRbatxZxMZ13iEMXg8UfTBR+UGl+NCzpkkTjjcVm/2 ...... ...... EXFyDtEykuiMuhn3A7WWNkc3voHML9C4kDWdJrX3wjQrwZbW3p3F1O/9pGHLNzn9 p3la2C9/Ve3jLdG8lEzvkCmtgTKWkqkhCnLwr7bRRzBUi3po7UDLWPePrH1ICd83 /wIDAQAB -----END PUBLIC KEY-----