1. 程式人生 > >工作中加密演算法實踐

工作中加密演算法實踐

遊戲中需要對接銀聯渠道

對方需求是需要使用非對稱加密演算法

簽名機制:

對於報文的簽名處理機制如下:首先,對報文中出現簽名域(sign)之外的所有資料元採用key=value的形式按照名稱排序,然後以&作為連線符拼接成待簽名串。其次,對待簽名串使用SHA-1演算法做摘要,再使用接入方的簽名私鑰證書中的私鑰對摘要做簽名操作(簽名時演算法選擇SHA-1)。最後,對簽名做Base64編碼,將編碼後的簽名串放在簽名(sign)表單域裡和其他表單域一起通過HTTPPost的方式傳輸給佰付美服務端

程式碼如下:

第一步:得到驗籤簽名

$signStr = $this-> makeSig
( $orderReq, $onlineConfig[ 'private_key']);


第二步:生成驗籤的方法

public function makeSig( $params, $prikey) { $mk = self:: makeSource( $params); DI()-> logger-> info( "makeSig引數陣列sha1結果為:" . __CLASS__ , $mk
);
$my_sign = $this-> sign( $mk, $prikey); DI()-> logger-> info( "makeSig生成的簽名為:" . __CLASS__, $my_sign); return $my_sign; }


第三步:將引數陣列按鍵升序,然後按鍵值&key=value形式拼接


public function
makeSource( $params) { DI()-> logger-> info( "makeSource引數陣列為:" . __CLASS__, json_encode( $params)); ksort( $params); $query_string = array(); foreach ( $params as $key => $val ) { array_push( $query_string, $key . '=' . $val); } $query_string = join( '&', $query_string); DI()-> logger-> info( "排序陣列拼接字串為:" . __CLASS__, $query_string); return $query_string; }


第四步:將演算法簽名做sha1資訊摘要,然後做base64_encode加密。返回呼叫處。

/**RSA簽名 * $data待簽名資料 * $priKey商戶私鑰 * 簽名用商戶私鑰 * 使用MD5摘要演算法 * 最後的簽名,需要用base64編碼 * return Sign簽名 */ public function sign( $data, $priKey) { //$priKey = file_get_contents(__DIR__ . "/CHL20103/private_key.pem");
//轉換為openssl金鑰 $res = openssl_get_privatekey( $priKey);
//呼叫openssl內建簽名方法,生成簽名$sign openssl_sign( $data, $sign, $res, OPENSSL_ALGO_SHA1);
//釋放資源 openssl_free_key( $res); //base64編碼 $sign = base64_encode( $sign); return $sign; }


驗籤:收到渠道回撥的時候需要驗證對方的簽名。

第一步:將對方的簽名引數和生成簽名的引數規則一樣,轉化成key=value形式

$mk = $this-> makeSource( $notifyData); $bool = $this-> verify( $mk, $sign, $pubKey);

第二步:將mk,sign,公鑰值傳遞給驗籤方法,獲得驗籤後的bool值。

/**RSA驗籤 * $data待簽名資料 * $sign需要驗籤的簽名 * $pubKey銀聯公鑰 * 驗籤用銀聯公鑰,摘要演算法為MD5 * return 驗籤是否通過 bool值 */ function verify( $data, $sign, $pubKey) { //$pubKey = file_get_contents(__DIR__."\CHL20103\public_key.pem"); //轉換為openssl格式金鑰 $res = openssl_get_publickey( $pubKey);
//呼叫openssl內建方法驗籤,返回bool值 $result = ( bool) openssl_verify( $data, base64_decode( $sign), $res, OPENSSL_ALGO_SHA1); //釋放資源 openssl_free_key( $res);
//返回資源是否成功 return $result; }