龙空技术网

使用GO代码实现 百度联盟媒体平台的DSA签名

蜜蜂大虾 88

前言:

眼前朋友们对“dsa算法实现”可能比较讲究,兄弟们都需要学习一些“dsa算法实现”的相关文章。那么小编也在网上搜集了一些有关“dsa算法实现””的相关知识,希望看官们能喜欢,小伙伴们一起来学习一下吧!

1. AccessKey

百度百度联盟将为每一个会员账号分配一个16 位字母数字组成的字符串,作为账号的

唯一标识。由百度联盟商务合作经理于线下发给会员。

2. IP 白名单

百度联盟会员需要线下向百度百度联盟平台提供欲访问API 的 IP 地址列表。目前不支

持 IP 段。

3. DSA 私钥公钥对

会员需要自己生成 PEM 格式的 DSA 私钥公钥对,并妥善保管好私钥,同时将公钥

线下提供给百度百度联盟平台。

生成方法:1. 生成随机参数openssl dsaparam -out dsaparam.pem 10242. 生成 DSA 私钥 privkey.pemopenssl gendsa -out privkey.pem dsaparam.pem3. 生成公钥 pubkey.pemopenssl dsa -in privkey.pem -pubout -out pubkey.pem
4. API 的 HTTP 请求头

为了验证平台身份,需要在HTTP Header 中额外增加以下两项内容:

4.1. x-ub-authorization: 用户信息+请求信息的签名(签名算法见下一小结),

格式为:${AccessKey}: ${Signature}。

4.2. x-ub-date: 请求的时间,格式为Unix-Time 时间戳。

5. 签名算法

需要将以下内容用“\n”连接起来,作为待签名的数据。然后将待签名的数据用DSA

私钥通过SHA1 算法加密编码,加密后的结果(字节数组)使用BASE64 进行编码,

作为签名使用。

1. 用户的AccessKey2. HTTP Method(GET、POST、PUT 等),见接口定义中的HTTP 方法3. 请求的资源的url及query参数(不包含协议及Host 部分),见接口定义中的URL4. x-ub-date 时间戳例如:11. GET 请求// 用户的Access Key 为 ABCDEFGHIJKLMN12// 当前的 unix 时间为 1387106898// GET /union/11.0/apps?page=1&count=10==== 待签名的内容,不包含本行内容 ===="ABCDEFGHIJKLMN12\n"+ "GET\n"+ "/ssp/1/sspservice/app/app-report/get-app-report?begindate=20190901&enddate=20190902\n"+ "1387106898\n"+ "\n"+ ""

私钥文件:

-----BEGIN DSA PRIVATE KEY-----MIIBvAIBAAKBgQD9f1OBHXUSKVLfSpwu7OTn9hG3UjzvRADDHj+123456789+1k9jVj6v8X1ujD2y5tVbNeBO4AdNG/123456789+gEexAiwk+7qdf+t8Yb+DtX58aophUPBPuD9tPFHsMCNVQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdgUI8VIwvMspK5gqLrhAvwWBz1AoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlXTAs9B4JnUVlXjrrUWU/mcQcQgYC0SRZxI+12345678991233333rh4rs6Z1kW6jfwv6ITVi8ftiegEkO8yk8b6oUZCJqIPf4VrlnwaSi2ZegHtVJWQBQQv+z0kqAoGBAMi2XZH2ebKSwLuRdWnWJYug/12345677898989/M+MhQLKV6+foRix6Z5nsYLZI0eLcTLEcE+kfiNuWegU7gca0chHM/Kc2TgO1U8HSsSsoFgtGCtN+66777899454545566565/dSKihFAhRHC4BI2244+aFh/123456789998878787==-----END DSA PRIVATE KEY-----
6.PHP生成签名方法:
<?phpclass UbapiClient {    private $host = ";;    private $private_key;    private $accessKey;    /**     * @param $privkeyPath 私钥的文件路径     * @param $accessKey access key     * @return UbapiClient     */    function __construct($privkeyPath, $accessKey) {        // 1. read private key        $fp = fopen($privkeyPath, "r");        $cert = fread($fp, 8192);        fclose($fp);        $this->private_key = openssl_get_privatekey($cert);        $this->accessKey = $accessKey;    }    /**     * 发起GET请求     * @param @uri 例如 /ssp/1/report?date=20151127     * @return (状态码,响应的body内容)     */    function doGet($uri) {        $method = "GET";        $contentType = "";        $bodyMd5 = "";        $timestamp = time();        $message = $this->accessKey . "\n" . $method . "\n" . $uri . "\n" . $timestamp . "\n" . $contentType . "\n" . $bodyMd5;        $binary_signature = "";        openssl_sign($message, $binary_signature, $this->private_key, OPENSSL_ALGO_DSS1);        $signature = base64_encode($binary_signature);        $headers = array(            $method . $uri . " HTTP/1.0",            "x-ub-date" . ": " .  $timestamp,             "x-ub-authorization" . ": " .  $this->accessKey . ":" . $signature,        );        $client = curl_init();        curl_setopt($client, CURLOPT_URL, $this->host . $uri);        curl_setopt($client, CURLOPT_HTTPHEADER, $headers);        curl_setopt($client, CURLOPT_RETURNTRANSFER, true);        $result = curl_exec($client);        $status= curl_getinfo($client, CURLINFO_HTTP_CODE);        curl_close($client);        return array($status, $result, );    }    /**     * 发起POST请求     * @param @uri 例如 /ssp/1/report?date=20151127     * @param $contentType 例如 application/json     * @param $body 请求的body内容     * @return (状态码,响应的body内容)     */    function doPost($uri, $contentType, $body) {        $method = "POST";        $bodyMd5 = md5($body);        $timestamp = time();        $message = $this->accessKey . "\n" . $method . "\n" . $uri . "\n" . $timestamp . "\n" . $contentType . "\n" . $bodyMd5;        $binary_signature = "";        openssl_sign($message, $binary_signature, $this->private_key, OPENSSL_ALGO_DSS1);        $signature = base64_encode($binary_signature);        $headers = array(            $method . $uri . " HTTP/1.0",            "Content-type: " . $contentType,            "Content-Length: " . strlen($body),            "x-ub-date" . ": " .  $timestamp,             "x-ub-authorization" . ": " .  $this->accessKey . ":" . $signature,        );        $client = curl_init();        curl_setopt($client, CURLOPT_URL, $this->host . $uri);        curl_setopt($client, CURLOPT_HTTPHEADER, $headers);        curl_setopt($client, CURLOPT_RETURNTRANSFER, true);        curl_setopt($client, CURLOPT_POST, 1);         curl_setopt($client, CURLOPT_POSTFIELDS, $body);         $result = curl_exec($client);        $status= curl_getinfo($client, CURLINFO_HTTP_CODE);        curl_close($client);        return array($status, $result, );    }}// init// 参数:private key + access token$client = new UbapiClient("privkey.pem", "12345678900FORTEST");// GET example$uri = "/ssp/1/sspservice/report/report/get-reports?dimensions=day,appId,appName&metrics=view,click,income&begin=20150810&end=20150820";$result = $client->doGet($uri);echo "\nGET\n";echo "status: $result[0]\n";echo "result: $result[1]\n";// POST example$uri = "/ssp/1/sspservice/adposition/app/adPositions/status";$body = '{"ids":[2076803,2076804], "status":"DELETED"}';$result = $client->doPost($uri, "application/json", $body);echo "\nPOST\n";echo "status: $result[0]\n";echo "result: $result[1]\n";?>
7.GO生成签名的方法
import (	"crypto/dsa"	"crypto/rand"	"crypto/sha1"	"encoding/asn1"	"encoding/base64"	"encoding/json"	"golang.org/x/crypto/ssh"	"io/ioutil"	"math/big"	"net/http"	"strconv"	"time")const BaiDuUrlPrefix = ";const BaiDuAccessKey = "123456789"const BaiduPrivKem = "-----BEGIN DSA PRIVATE KEY-----\nMIIBvAIBAAKBgQCo20fromvK7o+SF/123456789OK9Le0RJyieD\nWLsPPWJJ+QFyia90Uaj123456789zkuC+1lM\nwtX3lxnzjKpKlwlqhD/lkf8E3AdCZW/1234567\niOPepuvmWrFAGQlrX3EL636hAoGAb7XH6Yr/74+123456789\n9mQkT2b6wRix123456sOmxxriTjJZBrXVpXdpPrGX7/ggGR1nsg3C2f/K\n1wUPs8qqUqh412347FI0mN+U7CghJ//123456789\nQOZ0OvcCgYEAg6/yDeATH/123456789/4TGCFGMD\nCTPZ+123456789/FJ/voeEClNOPI48/dQ90coGTVfx8ci\nv6oJQ+u2VdaINgrk42UHRu6bYqqhSBFIl/12345678999\nA4Htul7UGu0/3qV8r75boQ==\n-----END DSA PRIVATE KEY-----"// 生成签名func GetSignature(x_ub_date int64, method string, query string) string {	//需要将以下内容用“\n”连接起来,作为待签名的数据。然后将待签名的数据用DSA 私钥通过SHA1 算法加密编码,加密后的结果(字节数组)使用BASE64 进行编码,	//作为签名使用。	//1. 用户的AccessKey	//2. HTTP Method(GET、POST、PUT 等),见接口定义中的HTTP 方法	//3. 请求的资源的url及query参数(不包含协议及Host 部分),见接口定义中的URL	//4. x-ub-date 时间戳	//	accessKey := BaiDuAccessKey    // int64转str	x_ub_date_str := strconv.FormatInt(x_ub_date, 10)	str := accessKey + "\n" + method + "\n" + query + "\n" +  x_ub_date_str + "\n" + "\n" + ""	sign, err := Sign(str, BaiduPrivKem)	if err != nil {		logx.Error("sign error:", err.Error())	}	logx.Info("sign:",sign)	return sign}type dsaSignature struct {	R *big.Int	S *big.Int}func Sign(originalData string, pemData string) (string, error) {	p, _ := ssh.ParseRawPrivateKey([]byte(pemData))	pp := p.(*dsa.PrivateKey)	h := sha1.New()	h.Write([]byte(originalData))	r, s, err := dsa.Sign(rand.Reader, pp, h.Sum(nil))	if err != nil {		logx.Error("ssss err:",err.Error())		return "", err	}	sig := dsaSignature{r, s}	b, err := asn1.Marshal(sig)	if err != nil {		logx.Error("aaaaa err:",err.Error())		return "", err	}	return base64.StdEncoding.EncodeToString(b), err}

标签: #dsa算法实现