技术程序员支付

第三篇:从支付宝SDK的支付流程理解什么是公钥和私钥,什么是加密

2018-05-14  本文已影响2913人  意一ineyee

warning:涉及到支付宝SDK的内容,均摘自支付宝开放平台。
warning:同时因为支付宝SDK使用的是RSA加密算法来加密和生成数字签名,因此本文中所涉及到的概念也都是针对于RSA非对称加密算法。所以可以和后面第四篇结合起来看。

目录

一、名词解释
 1、什么是公钥和私钥?
 2、什么是加密和数字签名,加密和数字签名的联系与区别

(注意,数字签名其实是独立于哈希算法、AES对称加密、RSA非对称加密的,或者说数字签名是它们三者的一种应用,不要以为数字签名就是专属于RSA非对称加密的。)

二、支付宝支付流程解释
 1、一些关键词
 2、支付宝支付流程
 3、服务端对订单信息加签和对支付结果验签的简单演示
三、微信支付流程与支付宝支付流程的区别

一、名词解释


1、什么是公钥和私钥?

首先要明白公钥和私钥只是一个相对概念,就是说我们不能单纯的去称呼一对密钥中的一个为公钥,另一个为私钥,它们的公私性总是相对于生成者来说的。一对密钥生成后,保存在生成者手里的就是生成者私钥,生成者发布出去的就是生成者公钥,可以看到我们在称呼它们的时候前面带上了生成者,这样可以便于我们理解,避免混淆概念。一对儿公私钥,不能由其中的一个导出另一个。

可以暂时这么理解:
一对密钥在刚生成的时候是没有公私之分的,但是生成者会保留一个在自己手里,发布一个给别人用,正是这个“保留与发布”的操作才使得这对密钥有了公私之分,那么对于生成者来说,保留在自己手里的密钥就被称作生成者私钥,发布给别人用的那个密钥就被称作生成者公钥,注意这里的称呼带上了生成者,就是为了表明一对密钥的公私性总是相对于它们的生成者来说的。(实际中私钥和公钥在生成的时候已经具备了公私性,因为公钥和私钥是不同的生成机理,但这样理解也是没有错的,有助于帮助我们理清后面的关系)

比如:
我们使用支付宝SDK的时候,我们商户端会生成一对密钥A和B,支付宝也会生成一对密钥C和D。
那么如果我们商户端保存了A,而把B发布给了支付宝,A就被称作商户端私钥,B就被称作商户端公钥。(注意称呼公私钥的时候带上生成者的名字,这样可以便于我们理解,避免混淆概念)
当然我们也可以保存B,而把A发布给支付宝,这样B就被称作商户端私钥,A就被称作商户端公钥。(实际中不会这么做,因为公私钥已经提前确定好了,它们的生成机理不同但这样理解也是没有错的,有助于帮助我们理清后面的关系)
同样,假设支付宝保存了C,而把D发布给了我们,那么C就被称作支付宝私钥,D就被称作支付宝公钥,反之同理。

2、什么是加密和数字签名,加密和数字签名的联系与区别

(1)什么是加密?

接下来,我们就着知道了加密这个概念,先看一下支付宝的加密过程,再引出数字签名这个概念。

当我们商户端和支付宝互相发布了公钥之后,我们商户端手里就有商户端私钥支付宝公钥两个密钥,支付宝手里也有商户端公钥支付宝私钥两个密钥。现在假设我们商户端要给支付宝传递订单信息,那么为了保证传递订单信息时数据的安全性(注意这个加密的目的,听起来好像很合理,但其实我们商户端给支付宝传递订单信息是明文传输的,只不过有数字签名来保证数据没被篡改而已,后面会说到,现在先按着这个错误的目的往下看,自然引出下面的反驳),针对我们商户端手里拥有的密钥,可以有两套加密方案,分别是:

貌似两种加密方案都能达到对订单信息加密传输的效果,那为什么我们看到支付宝开发平台让我们采用的是方案一而不是方案二呢?细想一下,采用方案二,我们商户端甚至只需要存储支付宝公钥这一个密钥,都不用我们去申请一对商户端的公私钥来维护,支付宝也不用保存我们一堆商户那么多的商户端公钥了呀,这不是更简单吗,那真得为什么支付宝不让我们用方案二呢?下面来回答一下:

首先,支付宝开放平台说明:当我们采用RSA(1024位密钥)来加密的时候,支付宝分配给所有商户的支付宝公钥都是一样的,即支付宝针对那么多的商户只负责维护一对支付宝公私钥;而当我们采用RSA2(2048位密钥)来加密的时候,支付宝会分配给每个商户单独的一个支付宝公钥,即支付宝为每一个的商户单独的维护一对独立的支付宝公私钥,当然一个商户下的多个App的支付宝公钥是一样的。RSA是早就支持的,RSA2是最近才支持的。见此篇

好,知道了上面这段话,那现在假设我们使用的是方案二(这样我们商户端就省去商户端申请商户端公私钥的这一过程,而只保留支付宝公钥),并且采用RSA加密,业务逻辑将会是下面这样:


方案二:订单信息加密传输,并且是采用RSA加密

这就出问题了呀:notify_url很容易被窃取,一旦窃取后,坏蛋就可以做和商户一样的操作来发起支付请求,因为采用RSA加密的话坏蛋同样可以获取到支付宝公钥,这样就会一直给小明充钱。

因此,支付宝就需要确认支付请求确实是商户发给他们的,而不是坏蛋发给他们的,这样才能避免坏蛋恶意模拟商户发起支付请求而给商户造成损失。那如何才能达到这个验证的效果呢?这就用到了数字签名,那么我们会通过方案一的实现流程来引出数字签名的具体概念。如果使用方案一的,我们商户手里是需要存着商户端私钥和支付宝公钥,而支付宝是需要存着商户端公钥和支付宝私钥的,这样方案一的业务流程如下:

方案一:对订单信息添加数字签名(简称加签)来传输

这样就可以确保数据交易的安全性了,我们也可以看出使用支付宝SDK确保交易安全注重的其实不是订单信息是否加密传输,而是如何确保商户端和支付宝能够互相确认身份(形成数字签名才是加密的真正目的,而不是加密传输,这里就反驳了上面的目的),我们还可以看出:

(2)数字签名是什么?

说到这里,我们再回想一下上面提到的RSA2加密,支付宝会分配给每个商户单独的一个支付宝公钥,即支付宝为所有的商户维护一对独立的支付宝公私钥,这样的话,采用方案二也能完成数字签名了呀,好像真得不需要我们商户去申请商户端公钥和私钥了,只不过现在需要兼容之前的RSA加密,所以依旧采用了方案一来做数字签名。可见数字签名并不一定非得用RSA加密来生成,MD5、SHA-1、AES等加密算法都可以用来生成数字签名,只不过实际开发要根据实际情况来选择适当的加密算法来生成数字签名。通常我们会选择RSA加密来生成数字签名(如支付宝支付就是这样)或者MD5加密来生成数字签名(如微信支付就是这样)。

(3)加密和数字签名的联系与区别

二、支付宝支付流程解释


由第一部分我们可以知道为了确保商户和支付宝交易的安全性,约定采用的是给订单信息加数字签名传输的方式。

那么,支付宝也为我们提供了一键生成RSA密钥的工具,可以帮助我们很快的生成一对商户端公私钥一键生成RSA密钥工具的下载地址

以下会对支付宝的支付流程做个大概的解释,并点出实际开发中我们使用支付宝SDK时应该注意的地方:

1、一些关键词
2、支付宝支付流程
支付宝支付流程时序图
3、服务端对订单信息加签和对支付结果验签的简单演示

上面已经说过了:订单信息的加签和支付结果的验签是一定要在服务端做的,绝对不能在客户端做。

(1)服务端对订单信息加签的简单演示

下面是在客户端对订单信息加签的过程,仅仅是为了模拟服务端来表明订单信息是如何通过加签最终转变为orderString的,千万不要觉得订单信息的加签过程也可以放在客户端完成

//将商品信息赋予AlixPayOrder的成员变量
Order* order = [Order new];

// NOTE: app_id设置
order.app_id = appID;

// NOTE: 支付接口名称
order.method = @"alipay.trade.app.pay";

// NOTE: 参数编码格式
order.charset = @"utf-8";

// NOTE: 当前时间点
NSDateFormatter* formatter = [NSDateFormatter new];
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
order.timestamp = [formatter stringFromDate:[NSDate date]];

// NOTE: 支付版本
order.version = @"1.0";

// NOTE: sign_type设置
order.sign_type = @"RSA";

// NOTE: 商品数据
order.biz_content = [BizContent new];
order.biz_content.body = @"我是测试数据";
order.biz_content.subject = @"1";
order.biz_content.out_trade_no = [self generateTradeNO]; //订单ID(由商家自行制定)
order.biz_content.timeout_express = @"30m"; //超时时间设置
order.biz_content.total_amount = [NSString stringWithFormat:@"%.2f", 0.01]; //商品价格

app_id=2015052600090779&biz_content={"timeout_express":"30m","seller_id":"","product_code":"QUICK_MSECURITY_PAY","total_amount":"0.02","subject":"1","body":"我是测试数据","out_trade_no":"ZQLM3O56MJD4SK3"}&charset=utf-8&method=alipay.trade.app.pay&sign_type=RSA2&timestamp=2016-07-28 20:36:11&version=1.0

GsSZgPloF1vn52XAItRAldwQAbzIgkDyByCxMfTZG%2FMapRoyrNIJo4U1LUGjHp6gdBZ7U8jA1kljLPqkeGv8MZigd3kH25V0UK3Jc3C94Ngxm5S%2Fz5QsNr6wnqNY9sx%2Bw6DqNdEQnnks7PKvvU0zgsynip50lAhJmflmfHvp%2Bgk%3D

app_id=2015052600090779&biz_content={"timeout_express":"30m","seller_id":"","product_code":"QUICK_MSECURITY_PAY","total_amount":"0.02","subject":"1","body":"我是测试数据","out_trade_no":"ZQLM3O56MJD4SK3"}&charset=utf-8&method=alipay.trade.app.pay&sign_type=RSA2&timestamp=2016-07-28 20:36:11&version=1.0&sign=GsSZgPloF1vn52XAItRAldwQAbzIgkDyByCxMfTZG%2FMapRoyrNIJo4U1LUGjHp6gdBZ7U8jA1kljLPqkeGv8MZigd3kH25V0UK3Jc3C94Ngxm5S%2Fz5QsNr6wnqNY9sx%2Bw6DqNdEQnnks7PKvvU0zgsynip50lAhJmflmfHvp%2Bgk%3D

(2)对支付结果验签的简单演示

假设我们服务端收到了来自支付宝服务端的支付结果,即:支付结果+数字签名

那么我们服务端就会对支付结果进行验签,怎么个验法呢?

三、微信支付流程与支付宝支付流程的区别


微信支付的流程大体上和支付宝是一样的,两者最关键的区别就是:

那么在第二节,我们已经演示了支付宝的加验签大概流程,这里针对上面第一个区别,介绍一下微信支付数字签名的生成的加验签流程:

可见,这里通过MD5加密也达到了加签验签的效果,验签的关键参数就是该应用的Api密钥,这个东西是在我们申请微信支付功能的时候,在平台上自己填写的一个32为的字符串,因此只有我们商户端和微信两者知道的,这样就用一个Api密钥达到了类似支付宝验签那样公钥私钥的效果。

上一篇 下一篇

猜你喜欢

热点阅读