問題描述
因?qū)拥谌街Ц肚澜涌谟露猓瑢Ψ絻H提供了java版本demo,未提供php版本士鸥,故只能根據(jù)java版本轉(zhuǎn)成php闲孤,
一開始看到對方提供的代碼一臉懵逼⊙﹏⊙‖∣
先看java版本核心代碼
//簽名
public String sign(String content, String privateKey) {
try {
PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(
Base64.decode(privateKey));
KeyFactory keyf = KeyFactory.getInstance("RSA");
PrivateKey priKey = keyf.generatePrivate(priPKCS8);
java.security.Signature signature = java.security.Signature
.getInstance("SHA1WithRSA");
signature.initSign(priKey);
signature.update(content.getBytes());
byte[] signed = signature.sign();
return Base64.encode(signed);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//校驗
public boolean doCheck(String content, String sign, String publicKey) {
try {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] encodedKey = Base64.decode(publicKey);
PublicKey pubKey = keyFactory
.generatePublic(new X509EncodedKeySpec(encodedKey));
java.security.Signature signature = java.security.Signature
.getInstance("SHA1WithRSA");
signature.initVerify(pubKey);
signature.update(content.getBytes());
boolean bverify = signature.verify(Base64.decode(sign));
return bverify;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
看到RSA、SHA1WithRSA烤礁、Base64讼积、PKCS8EncodedKeySpec、X509EncodedKeySpec這些名詞后脚仔,內(nèi)心是沮喪的勤众,直接翻譯是行不通的,只能祭出Google大殺器來鲤脏。
經(jīng)過幾個關(guān)鍵詞組合嘗試后们颜,終于在gist上找到眉目,直達連接 事例代碼用的bin2hex凑兰、hex2bin掌桩,我們直接替換為base64_encode、base64_decode試試看姑食,竟然一次通過,和java版本的加密解密結(jié)果是一致的
解決方案
生成ssl證書
openssl genrsa -out key.pem 1024 openssl rsa -in key.pem -pubout -outform PEM -out pubkey.pem openssl rsa -in key.pem -pubout -outform DER -out pubkey.der
代碼實現(xiàn)
//簽名 function buildSign($content) { $signature = null; $pri_key = file_get_contents('key.pem'); $pri_key_id = openssl_get_privatekey($pri_key); openssl_sign($content, $signature, $pri_key_id); openssl_free_key($pri_key_id); return base64_encode($signature); } //校驗 function verifySign($sign, $toSign) { $signed_data = base64_decode($sign); $pub_key = file_get_contents('pubkey.pem'); $pub_key_id = openssl_get_publickey($pub_key); $ret = openssl_verify($toSign, $signed_data, $pub_key_id); return $ret; }
openssl_sign和openssl_verify默認(rèn)算法都是SHA1茅坛,如果是其他請在第4個參數(shù)中傳入音半,請參考如下
define ('OPENSSL_ALGO_SHA1', 1);
define ('OPENSSL_ALGO_MD5', 2);
define ('OPENSSL_ALGO_MD4', 3);
define ('OPENSSL_ALGO_MD2', 4);
define ('OPENSSL_ALGO_DSS1', 5);
define ('OPENSSL_ALGO_SHA224', 6);
define ('OPENSSL_ALGO_SHA256', 7);
define ('OPENSSL_ALGO_SHA384', 8);
define ('OPENSSL_ALGO_SHA512', 9);
define ('OPENSSL_ALGO_RMD160', 10);