curl擴充
curl_setopt($ch, CURLOPT_SSLCERT, getcwd().'/cert/mycert.pem');
在做微信支付介面雙向驗證的時候,需要pem證照檔案,然而在Mac上做本地測試的時候一直返回curl 58錯誤,經過一番查閱,發現,php的curl擴充在Mac和linux上是不大一樣的兩者的協議棧不一樣
Mac下的協議棧是
Secure Transport
而ubuntu下的協議棧是openssl
(據說centos也有這個問題)
openssl函式
在獲取到微信返回的rsa公鑰字串後,需要通過
php
的openssl_public_encrypt()
函式對資料進行公鑰加密,然而拿到的rsa公鑰字串卻無法直接用openssl_get_publickey()
來獲取其中的公鑰,我第一反應以為是格式(空格換行符)等原因造成的,調了一下午之後終於發現了端倪,仔細看這個獲取公鑰的函式,官方是這麼介紹的
an X.509 certificate resource
a string having the format file://path/to/file.pem. The named file must contain a PEM encoded certificate/public key (it may contain both).
A PEM formatted public key.
複製程式碼
注意一下這個
X.509
,這個函式是以這個風格載入public key的,而微信給我們的是公鑰是PKCS#1 RSA public key
,因此不能直接載入,總是返回false
而評論區告訴了我們思路與具體實現
思路如下
If you are trying to read a PKCS#1 RSA public key you run into trouble, because openssl wants the public key in X.509 style.
The PKCS#1 RSA public key
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAgYxTW5Yj+5QiQtlPMnS9kqQ/HVp+T2KtmvShe68cm8luR7Dampmb
[...]
cbn6n2FsV91BlEnrAKq65PGJxcwcH5+aJwIDAQAB
-----END RSA PUBLIC KEY-----
.. is not readable while the X.509 style public key
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgYxTW5Yj+5QiQtlPMnS9
[..]
JwIDAQAB
-----END PUBLIC KEY-----
is. You can use an easy (and dirty) work around to read the PKCS#1 RSA anyway. The first few bytes of the X.509 style public key contain header information and can shamelessly be copied.
In other words: Delete everything after the first 32 bytes from the above X.509 key (starting behind Q8A) and attach your PKCS#1 data, reformat to 64 bytes length and use it with openssl.
Please note: The above example only works for 2048 bit length.
Like I said - it's kind of dirty - but hey - if you're as desperate as I was.
Michaela
複製程式碼
具體實現如下
// Michaela code retranscription can be :
$key = str_replace([
'-----BEGIN RSA PUBLIC KEY-----',
'-----END RSA PUBLIC KEY-----',
"\r\n",
"\n",
], [
'',
'',
"\n",
''
], $key);
$key = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A' . trim($key);
$key = "-----BEGIN PUBLIC KEY-----\n" . wordwrap($key, 64, "\n", true) . "\n-----END PUBLIC KEY-----";
複製程式碼
當然了,如果你想像微信官方介紹的那樣,讓檔案落地,一勞永逸,可以用
openssl rsa -RSAPublicKey_in -in <filename> -pubout
將PKCS#1標準的RSA公鑰pem檔案轉換為PKCS#8標準的檔案,道理是一樣的