golang 对接第三方接口 RSA 做签(加密) 验签(解密)

一、过程

1.调用第三方接口前,一般需要按规则将参数按key1=value1&key2=value2 阿斯克码排序,sign参数不参与加密

2.将排序并连接好的参数字符串通过我方的私钥证书(.pem)进行加密得到加密串,当然加密得到的是 []byte 字节流,需要将字节流转换成base64字符串

3.将加密字符串赋值给sign参数,并与其他加密参数一起通过post (application/x-www-form-urlencoded )请求第三方接口。 当然,第三方与我方对接的时,会要求我方提供公约证书给到他们,用以拿到我方请求后,对我方请求参数进行延签。

4.同理,我方请求第三方后,会返回数据给到我方以及第三方会请求我们的回调接口,那么就需要对第三方返回的参数进行验签,而验签同理需要将加密参数提取出来,并进行排序,需要明白的是,此时解签我们需要用到 第三方的公钥 进行验签,

5.其中需要注意的是:我所了解的目前golang 加密和解密一般都是用的pem证书,而大部分第三方提供的证书是 .pfx  .cer ,所以我需要在win上安装openssl工具,然后将 .pfx .cer转成 .pem证书

证书转换方式如下:

1. 下载Win64OpenSSL-3_1_2.exe 并安装(下载:https://slproweb.com/products/Win32OpenSSL.html)
2. 环境变量 Path  加入 D:\OpenSSL-Win64\bin
3. amd 下命令: openssl version   验证是否安装成功4. 通过命令解析生成 公私钥 uat.pfx openssl pkcs12 -in xxxx.pfx -nodes -out server.pem  #生成为原生格式pem 私钥 ******openssl rsa -in server.pem -out server.key          #生成为rsa格式私钥文件openssl x509 -in server.pem  -out server.crtopenssl pkcs12 -in xxxx.pfx -clcerts -nokeys -out key.certopenssl x509 -inform der -in xxx.cer -out xxx.pem    #公钥pem *******

二、加密和解密要用到的方法(供参考)

1.参数进行排序并连接成 key1=value1&key2=value2 字符串并将sign参数排除在外

func GetSignStr(maps map[string]string) string {signData := make(map[string]string, 0)for k, v := range maps {if k != "sign" {signData[k] = v}}var dataParams stringvar keys []stringfor k := range signData {keys = append(keys, k)}sort.Strings(keys)for _, k := range keys {dataParams = dataParams + k + "=" + signData[k] + "&"}ff := dataParams[0 : len(dataParams)-1]return ff
}

2.将排序好的参数字符串进行证书私钥加密并将加密串base64转换

// 将排序好的参数进行加密签名并转成base64字符串返回 signData:参数字符串 pemPath :私钥路径./aaa/bbb/private.pem
func PrivateSha1SignData(signData, pemPath string) (string, error) {h := crypto.Hash.New(crypto.SHA1)h.Write([]byte(signData))hashed := h.Sum(nil)_, private, err := LoadPrivateKey(pemPath)if err != nil {return "", err}signer, err := rsa.SignPKCS1v15(rand.Reader, private, crypto.SHA1, hashed)if err != nil {fmt.Println("PrivateSha1SignData Error  from signing: %s\n", err)return "", err}return Base64Encode(signer), nil
}// 根据路径加载证书文件
func LoadPrivateKey(pemPath string) (string, *rsa.PrivateKey, error) {key, err := ioutil.ReadFile(pemPath)if err != nil {return "", nil, err}block, _ := pem.Decode(key)if block == nil {return "", nil, errors.New("pem.Decode err")}p, err := x509.ParsePKCS8PrivateKey(block.Bytes)if err != nil {return "", nil, err} else {pk := p.(*rsa.PrivateKey)return "", pk, nil}
}// base64 加密
func Base64Encode(data []byte) string {return base64.StdEncoding.EncodeToString(data)
}// base64 解密
func Base64Decode(data string) ([]byte, error) {return base64.StdEncoding.DecodeString(data)
}

3.将sign和加密参数转成map post方式请求第三方接口,而此处需要注意接口返回的参数,返回的参数sign值中是带有+ 和 / 符号的,按正常情况 用 url.QueryUnescape(string(body[:]))转换是安全的,但奇怪的是本人遇到过用此方法反而字符串中出现了空格,所以用string(body[:])就OK了

func PayPost(requrl string, request map[string]string, publicPemPath string) (respData string, err error) {http := TimeoutClient()resp, err := http.Post(requrl, "application/x-www-form-urlencoded", strings.NewReader(HttpBuildQuery(request)))if err != nil {return respData, errors.New("paypost err1:" + err.Error())}if resp.StatusCode != 200 {return respData, fmt.Errorf("http request response StatusCode:%v", resp.StatusCode)}defer resp.Body.Close()data, err := ioutil.ReadAll(resp.Body)if err != nil {return respData, errors.New("paypost err2:" + err.Error())}dataString := string(data[:])//dataString, err := url.QueryUnescape(string(data[:]))//if err != nil {//	return respData, errors.New("paypost err3:" + err.Error())//}return respData, err
}

4. 对方回调我们方接口接收参数 

//获取参数字节码body, err := ioutil.ReadAll(c.Request.Body)info := ""if err != nil {//返回错误return}//参数转成字符串dataString, err := url.QueryUnescape(string(body[:]))if err != nil {//返回错误return}

5.解密

// signStr:参数字符k=v&k=v
// signature:加密串base64需要转换
// PublicPemPath:第三方公约路径 ./aaa/bbb/public.pem
// 解密      
func YSCallbackVerify(signStr,signature, PublicPemPath string) (bool, error) {hash := crypto.Hash.New(crypto.SHA1)hash.Write([]byte(str))hashed := hash.Sum(nil)var inSign []byteinSign, err := Base64Decode(signature)if err != nil {return false, errors.New("解析signature失败:" + err.Error())}publicPem, err := LoadPublicKey(PublicPemPath)if err != nil {return false, errors.New("获取公钥失败:" + err.Error())}err = rsa.VerifyPKCS1v15(publicPem, crypto.SHA1, hashed, inSign)if err != nil {return false, errors.New("PublicSha1Verify Error from signing:" + err.Error())}return true, nil
}//加载公约证书
func LoadPublicKey(pemPath string) (*rsa.PublicKey, error) {key, err := ioutil.ReadFile(pemPath)if err != nil {return nil, errors.New("加载公钥错误1:" + err.Error())}block, _ := pem.Decode(key)if block == nil {return nil, errors.New("加载公钥错误2:" + err.Error())}certBody, err := x509.ParseCertificate(block.Bytes)if err != nil {return nil, errors.New("加载公钥错误3:" + err.Error())}pb := certBody.PublicKey.(*rsa.PublicKey)return pb, nil
}

6.说明:请求第三方接口,一般参数会有两层或更多层,那么我们获取到参数而第二层原本是json字符串,那么就需要注意,我们golang定义的结构体struct各字段就需要跟它对应,以免参数书序不对造成解密失败。当然,如上方法都是用的map接收参数当中需要将struct转成map 将map转成struct则需要根据需要来灵活转换。

  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/766914.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

变量赋值篇

文章目录 变量赋值增量赋值多重赋值多元赋值合法的标识符 变量赋值 在Python中,变量赋值是一个简单的操作,你可以使用等号()来将一个值赋给一个变量。以下是一些基本的变量赋值示例: # 整数赋值 x 10# 浮点数赋值 y…

Excel文件导入导出,SpringBoot整合EasyExcel批量导入导出,采用的JDBC+EasyExcel(附带整个Demo)

目录 0.为什么mybatis的foreach比JDBC的addBatch慢 1.引入依赖 2.Controller层 3.Service层 4.Utils工具类 5.自定义监听器 6.实体类 7Mapper层 不用Mybatis的原因就是因为在大量数据插入的时候jdbc性能比mybatis好1. 首先分批读取Excel中的数据 这一点EasyExcel有自己…

看完就等于拿捏浮点数在内存中的储存了

诸君又该学习了,今天我们继续来一睹浮点数的奥妙真容。 经过前面文章对整形提升相关的解释,我们都对整形和字符在内存空间上的储存已经有了大概的认知,那么现在我们就来好好讲讲浮点数在内存中的储存规则。 目录 浮点数与整形储存的不同 …

41-Vue-webpack基础

webpack基础 前言什么是webpackwebpack的基本使用指定webpack的entry和output 前言 本篇开始来学习下webpack的使用 什么是webpack webpack: 是前端项目工程化的具体解决方案。 主要功能:它提供了友好的前端模块化开发支持,以及代码压缩混淆、处理浏览…

自定义序列化

3.2.2.自定义序列化 RedisTemplate可以接收任意Object作为值写入Redis: 只不过写入前会把Object序列化为字节形式,默认是采用JDK序列化,得到的结果是这样的: 缺点: 可读性差内存占用较大 我们可以自定义RedisTempla…

NASA数据集——2015 年30 米分辨率的地衣地面覆盖率模型估计值

cABoVE: Lichen Forage Cover over Fortymile Caribou Range, Alaska and Yukon, 2000-2015 文件修订日期:2021-07-21 数据集版本: 1 摘要 本数据集提供了美国阿拉斯加东部内陆和加拿大育空地区 Fortymile 研究区 2015 标称年 30 米分辨率的地衣地面覆盖率模型估…

modbus代码思路整理

void main() { eMBinit(); eMBEnable();/*1.eRcvState = STATE_RX_INIT 2.USART:USART_RX->Enable & USART_TX->Disable 3.打开TIM(5ms):Enable 4.eMBState = STATE_ENABLE*/ while(1) {…

YOLOv8-ROS-noetic+USB-CAM目标检测

环境介绍 Ubuntu20.04 Ros1-noetic Anaconda-yolov8虚拟环境 本文假设ROS和anaconda虚拟环境都已经配备,如果不知道怎么配备可以参考: https://blog.csdn.net/weixin_45231460/article/details/132906916 创建工作空间 mkdir -p ~/catkin_ws/srccd ~/ca…

SQL注入四-PHP应用SQL二次注入堆叠执行DNS带外功能点黑白盒条件

演示案例: PHP-MYSQL-二次注入-DEMO&74CMSPHP-MYSQL-堆叠注入-DEMO&CTF强网PHP-MYSQL-带外注入-DEMO&DNSLOG #PHP-MYSQL-二次注入-DEMO&74CMS 1、DEMO-用户注册登录修改密码 2、CMS-74CMS个人中心简历功能 黑盒思路:分析功能有添加后对数…

dom元素+CSS实现阶梯动画效果

1.效果 2.代码实现 <template><div class"container"><div class"Box"><div class"box" style"background-color: red;"></div><div class"box" style"background-color: orange;&q…

湖北专升本报名照片需要<40kb怎么解决

湖北专升本报名照片需要<40kb怎么解决

vue 修改element-plus主题色

一、安装SCSS npm install sass --save-dev npm install sass-loader --save-dev npm install node-sass --save-dev npm install vue-style-loader --sava-dev 二、添加主题文件theme.scss forward "element-plus/theme-chalk/src/common/var.scss" with ($col…

特种兵旅游-扬州、南京

一、扬州 Day01 西安咸阳机场->扬州泰州机场&#xff08;扬州地界但是离泰州也嘎嘎近&#xff09;->大运河博物馆&#xff08;需要提前预约&#xff01;&#xff09;&#xff08;超级震撼&#xff09; Day02 瘦西湖&#xff08;门票有点贵&#xff0c;但是蛮值得&#x…

kubernetes负载均衡-service

一、service的概念 1、什么是service 在Kubernetes中&#xff0c;pod是应用程序的载体&#xff0c;当我们需要访问这个应用时&#xff0c;可以通过Pod的IP进行访问&#xff0c;但是这里有两个问题:1、Pod的IP地址不固定&#xff0c;一旦Pod异常退出、节点故障&#xff0c;则会…

量子计算与大模型融合的潜力与挑战探索

量子计算与大模型融合的潜力与挑战探索 1. 背景介绍 随着人工智能技术的飞速发展&#xff0c;大模型在自然语言处理、计算机视觉等领域取得了显著的成果。然而&#xff0c;大模型训练需要大量的计算资源&#xff0c;导致训练时间长、能耗高。量子计算作为一种新型计算方式&am…

【STM32】读写BKP备份寄存器RTC实时时钟

目录 BKP BKP简介 BKP基本结构 BKP测试代码 RTC RTC简介 RTC框图 RTC基本结构 硬件电路 RTC操作注意事项 接线图 初始化 使用BKP解决只初始化一次时间 初始化参考代码 RTC设置时间 RTC读取时间 完整代码 MyRTC.c MyRTC.h main.c BKP BKP简介 BKP&#xff0…

渗透测试-ssh私钥泄露知识记录

1 ssh私钥泄露 1.1 信息探测 渗透其实是针对服务的漏洞探测&#xff0c;然后进行数据包的发送&#xff0c;获取机器的最高权限。 nmap –sV 192.168.0.1常用端口0-1023端口&#xff0c;在扫描结果中查找特殊端口&#xff0c;针对特殊端口进行探测&#xff0c;尤其是对开放大端…

pytorch中tensor类型转换的几个函数

目录 IntTensor转FloatTensor FloatTensor转IntTensor Tensor类型变为python的常规类型 IntTensor转FloatTensor .float函数&#xff1a; FloatTensor转IntTensor .int函数 Tensor类型变为python的常规类型 item函数

阿里云部署MySQL、Redis、RocketMQ、Nacos集群

文章目录 &#x1f50a;博主介绍&#x1f964;本文内容MySQL集群配置云服务器选购CPU选择内存选择云盘选择ESSD AutoPL云盘块存储性能&#xff08;ESSD&#xff09; 镜像选择带宽选择密码配置注意事项 安装docker和docker-compose部署MySQL三主六从半同步集群一主二从同步集群规…

perl:获取同花顺数据--业绩预告

perldoc LWP::UserAgent 如果没有安装&#xff0c;则安装模块&#xff0c;运行 cpanm LWP::UserAgent 。 编写 get_yjyg_10jqka.pl 如下 #!/usr/bin/perl # perl 获取同花顺数据--业绩预告 use LWP::UserAgent; use Encode qw(decode encode); use POSIX; use Data::Dump…