微信js支付-签名

384 阅读24分钟

微信js支付里的签名

我们直接基于实际的应用场景讲签名,比如现在这个微信js支付,在支付的时候,微信会返回预支付id,然后会唤起密码框,用户输入密码真正支付。

怎么唤起密码框?说白了,就是调用微信接口,具体来说就是调用微信js接口。

微信接口文档:pay.weixin.qq.com/wiki/doc/ap…

重点来了,接口的入参是啥?

1.  预支付id

唯一标记刚刚支付的时候创建的订单。

2.  签名

为什么要签名?签名是为了安全,具体来说,是为了确保客户端的入参和服务器收到的入参一致,即在中间传输过程当中没有被中间人修改。核心和本质就是为了解决这个问题,如果不考虑安全问题,根本不需要搞什么签名。下面再详细讲为什么要签名的细节问题。

为什么要签名?

商户调用微信接口:

1.  入参

明文

2.  签名

一般情况下,只需要使用消息摘要算法即可。目的是为了解决,微信收到入参之后怎么知道入参是否被中间人修改,怎么解决?就是基于消息摘要,其实就是拿客户端的签名值(入参计算得到签名值)和微信服务器端的签名值(接收到入参之后也是基于明文计算得到签名值)比较签名值是否一样,如果一样,表示入参没有被修改,如果不一样,表示入参被修改。

说白了,就是比较客户端和服务器的明文数据是否被修改。

只要入参没有被修改,微信才敢继续使用这个入参做接下来的工作。

为什么要加密?

本来消息摘要算法是不可逆的,所以专门用来解决入参是否被中间人修改。

但是呢,为了更加安全起见,微信做了两个优化:

1.  消息摘要算法md5改为sha

为什么要改为sha?因为sha更安全,更不容易被破解。

2.  并且加密

消息摘要本来就是不可逆,本来就很安全,为什么还要加密?因为md5已经被破解,sha目前没有被破解但是理论上也可以被破解,所以为了更加安全,就使用了加密。

具体来说,是使用了非对称加密(两个秘钥:公钥和私钥),即商户使用商户私钥加密,微信使用商户公钥解密。

注意,微信解密加密签名字段之后得到的是签名,而不是明文入参,明文入参是其他的字段,其他字段本来就是明文的,不需要加密,也不需要解密。

同步返回数据

一般情况下,客户端调用服务器和服务器同步返回客户端,都需要签名。因为只要是通信,无论数据的流向是正向还是反向,就都需要签名,来确保没有被中间人篡改。

但是呢,微信有点特殊,客户端调用服务器,有签名。但是服务器同步返回数据,没有签名。

而,支付宝,则都有签名。

微信

同步返回数据的时候,没有签名,只有一个字段:预支付id。

支付宝

预支付的时候,支付宝同步返回数据:

1.  订单号

作用和微信返回的预支付id类似。细节的话有一点区别,微信的预支付id和微信订单号是不同字段,预支付id专门用于唤起密码框。而支付宝相当于拿订单号同时作为预支付id使用。

2.  签名

比微信多了一个签名字段。

支付宝文档: opendocs.alipay.com/open/f72f07…

返回数据怎么签名?

流程是一样的。

只不过呢,唯一的不同是,支付宝使用支付宝私钥加密,商户收到返回数据之后使用支付宝公钥解密。

但是相同点都是使用自己的私钥加密,然后接收方使用对方的公钥来解密。

也就是说,总共有两对四个秘钥,一对是商户的公钥和私钥,一对是支付宝的公钥和私钥。

总结

微信js支付,返回的时候虽然没有签名,但是其他业务(比如微信反扫)也是有签名的。

微信反扫文档 pay.weixin.qq.com/wiki/doc/ap…

另外,微信/支付宝主动通知调用商户接口的时候(目的是告诉商户支付成功),也是有签名。

网上资料:

1、商户的公钥与私钥,用于发起支付

商户使用的openssl工具在本地生成的公钥和私钥,然后将生成的公钥上传到支付宝商家后台,支付时,我们使用该私钥对订单信息加密,支付宝服务端收到该加密信息后会拿商户后台上传的公钥对该信息进行解密。

2、支付宝的公钥与私钥,用于返回数据或者回调

支付宝有个公开的公钥,所有的商户使用的支付宝公钥都是同一个。支付成功或失败后,支付宝服务端要回调告诉我们支付结果,会拿私钥对该回调信息进行加密,我们收到该信息要拿支付宝的公钥进行解密。

www.jianshu.com/p/34721826c…

什么应用场景使用私钥加密公钥解密?什么应用场景使用公钥加密私钥解密?

一般情况,都是公钥加密,私钥解密。

比如,敏感数据(银行卡号,身份证号,手机号等),在客户端和服务器通信的时候,不管是客户端调用服务器,还是服务器返回数据给客户端,都要加密传输。注意,这里也一样,也是有两对秘钥。

具体来说,商户调用微信,使用微信公钥加密,微信收到入参之后使用微信私钥解密得到明文入参。而微信返回数据的时候,则使用商户公钥加密数据,商户收到返回数据之后使用商户私钥解密来得到明文返回数据。

总结来说,就是使用对方的公钥去加密数据,然后才敢在网络上传输数据,但是因为是加密数据,所以中间人在通信过程当中就算截获了数据也没什么卵用,因为是加密的,你没有私钥就无法解密数据得到明文。

比如,微信的敏感数据通信,就是使用公钥加密,私钥解密:

敏感信息加解密

为了保证通信过程中敏感信息字段(如用户的住址、银行卡号、手机号码等)的机密性,微信支付API v3要求商户对上送的敏感信息字段进行加密。与之相对应,微信支付会对下行的敏感信息字段进行加密,商户需解密后方能得到原文。下面详细介绍加解密的方式,以及如何进行相应的计算。

pay.weixin.qq.com/wiki/doc/ap…


那为什么隐私敏感数据就是使用公钥加密私钥解密?而签名就是使用私钥加密公钥解密呢?

核心的区别在于,敏感数据核心的问题在于加密,防止中间人截获数据看到明文数据。所以,加密之后,中间人就算截获了数据,因为没有私钥所以解密不了加密数据。这是加密的作用的本质。

但是,签名的本质不是为了加密,因为入参数据包含:入参(明文) + 签名。入参本来就是明文,所以被中间人截获的时候是可以看到明文的,这个是没有关系的。那为什么要签名呢?签名的作用是什么呢?签名的目的是确保客户端和服务器两边的数据一致,即没有被中间人篡改。想要实现这一点,就需要使用签名,本质是基于消息摘要算法去实现签名功能。签名功能本身是不需要加密的,只不过呢,为了更安全起见,才额外加了加密功能。那为什么签名功能的加密就要使用私钥去加密呢?重点来了,如果是使用公钥加密,那么谁都都可以使用公钥加密,也就是说,谁都可以伪造签名。这是不允许的,刚才说了,签名的核心作用是避免篡改数据,然后还有另外一点,必须是合法主体才能计算签名,但是公钥是公开的,所以不能使用公钥去计算签名,那么剩下的就是只能使用私钥去计算签名,这就是原因所在。

问了下chatgpt,大概回答了这个问题:

签名为什么不使用公钥加密私钥解密?

签名使用私钥加密、公钥解密的过程,而不是使用公钥加密私钥解密,是因为签名的目的和加密的目的有本质的区别。

1. 目的不同:

签名的主要目的是为了确保数据的完整性和认证数据的来源。发送者使用自己的私钥对数据进行签名,这样接收者可以使用发送者的公钥来验证签名,从而确认数据确实来自于特定的发送者且在传输过程中未被篡改。

2. 防止篡改:

使用私钥进行签名是为了保证签名的可靠性,因为私钥只有发送者自己知道,其他人无法伪造签名。如果使用公钥加密私钥解密的方式进行签名,那么任何人都可以使用公钥对数据进行加密(即签名),这样就无法确认数据的真实来源,因为任何人都可以拥有相同的公钥。

3. 非对称加密原理:

签名是基于非对称加密的原理,非对称加密算法包含了一对密钥:公钥和私钥。公钥用于加密,私钥用于解密。私钥的所有者可以用其私钥对数据进行签名,公钥的所有者可以使用其公钥验证签名。这种设计确保了数据的完整性和认证的过程。


总结

签名使用私钥加密、公钥解密的方式是为了满足签名的安全需求:确保数据来源可信,数据在传输过程中没有被篡改。公钥加密私钥解密适用于加密过程,确保数据在传输和存储过程中的机密性和隐私。因此,签名和加密在应用上有着不同的目的和原理,不能互相替代。

微信公钥/私钥都是一样的吗?

每个商户的商户公钥/私钥,肯定是不一样的。

那,每个商户的微信公钥/私钥都是一样的吗?也不一样。


微信支付文档

回答也是不一样:kf.qq.com/faq/220314v…


问一下chatgpt:

非对称加密,同一个私钥可以解密不同的公钥吗

非对称加密是一种加密算法,其中使用一对密钥:公钥和私钥。公钥用于加密数据,而私钥用于解密数据。与对称加密不同,非对称加密使用不同的密钥进行加密和解密,且私钥不能用于解密其他公钥加密的数据。

简而言之,不同的私钥只能解密对应的公钥加密的数据,而不能解密其他公钥加密的数据。所以,同一个私钥不可能用于解密不同的公钥加密数据。每对非对称密钥都是唯一配对的,并且在加密过程中它们彼此独立运作,提供了更高的安全性和灵活性。


咨询了一下微信:微信公钥私钥,也是每个商户都是独立的,非共用

image.png


咨询了一下支付宝的技术支持:也是不一样。

产品名称 : 支付转账类问题
请选择产品 : ["其它"]
问题描述 : 你好,每个商户各自用自己的公钥私钥,支付宝公钥和私钥是所有商户共用吗?

支付宝技术支持
支付宝公钥是商户上传应用公钥生成的

支付宝技术支持
比如您的公钥是A,上传之后变成支付宝公钥是A1,我的应用公钥是B,上传之后变成支付宝公钥是B1

我:支付宝的公钥和私钥,每个商户都不一样是吗?
每个商户的公钥私钥不一样,但是支付宝的公钥私钥是不是每个商户也不一样?还是说支付宝就一对公钥私钥,所有商户共用这个一对?

支付宝技术支持
支付宝私钥是支付宝的隐私,支付宝公钥每个商户都不同的

支付宝技术支持
每个商户的公钥私钥不一样,对应的支付宝公钥也不同

支付宝技术支持
你们用不到支付宝私钥哈

支付宝技术支持
一共是三个密钥,应用私钥+应用公钥+支付宝公钥

我:我知道支付宝私钥是支付宝自己存储,商户用不到,那支付宝私钥是只有一个吗?还是每个商户不一样?

支付宝技术支持
支付宝私钥是固定的

支付宝技术支持
但是商户不知道

支付宝技术支持
是支付宝自己保存的

支付宝技术支持
商户用不到的

支付宝技术支持
代码中用的就是商户的应用私钥+支付宝公钥

我:支付宝同一个私钥,可以解密不同的支付宝公钥?
公钥和私钥不是唯一配对吗

支付宝技术支持
不是,支付宝公钥是根据商户的应用公钥来的

支付宝技术支持
每个pid下的支付宝公钥相同

聊了半天,没get到我问题,后面小哥直接打电话过来了,但是小哥也不确定支付宝私钥到底是不是共用一个,然后他问了一下同事,最后确认支付宝私钥确实是独立的,即每个商家都不一样。说白了,就是每个商家都对应两对秘钥,一对是商家的公钥私钥,一对是支付宝的公钥私钥,这两对秘钥都是独立的,每个商家都不一样。


结论

公钥和私钥唯一配对,不可能一个私钥解密多个公钥,不可能一个私钥对应多个公钥。

公钥和私钥怎么存储?

存储在哪里?文件?证书文件?

为什么要放在外部文件,而不是项目代码里的配置文件配置一下就可以了?

为什么要使用证书?

证书到底是啥?作用是为了解决什么问题?

问题有点多,下面一一回答。

存储在哪里?

公钥存储在证书文件。

私钥存储在私钥文件。

公私钥都被加密和编码之后再存储,而且是存储到证书文件,因为要确保公钥和私钥本身的安全。

证书文件除了包含公钥信息,还包含签名等字段。


微信文档:

什么是商户证书?什么是平台证书?

● “商户证书”是指由商户申请的,包含商户的商户号、公司名称、公钥信息的证书。

● “平台证书”是指由微信支付负责申请的,包含微信支付平台标识、公钥信息的证书。

商户在调用 API 时用自身的私钥签名,微信支付使用商户证书中的公钥来验签。微信支付在响应的报文中使用自身的私钥签名,商户使用平台证书中的公钥来验签。

pay.weixin.qq.com/wiki/doc/ap…


支付宝

秘钥的界面大概长这个样子,主要包含:

1.  商户公钥

2.  支付宝公钥

image.png

blog.csdn.net/qq_42785280…

注:商户私钥,商户自己保存。支付宝私钥,支付宝自己保存。

什么是证书?

在计算机和网络领域,"证书"(Certificate)是一种数字证明文件,用于验证特定实体的身份,例如网站、个人或组织。证书通过加密技术确保了信息的机密性和完整性,从而提供安全性。

主要的证书类型是 SSL(Secure Socket Layer)/TLS(Transport Layer Security)证书,用于保护网络通信的安全。当您访问一个使用HTTPS协议的网站时,您的浏览器会从该网站的服务器请求其证书,并用于验证网站的身份。证书中包含了网站的公钥、数字签名以及一些其他信息。这个数字签名是由证书颁发机构(Certificate Authority,简称CA)签署的,CA 是一个受信任的第三方实体,用于确认该证书的合法性。

安全性的保证是通过以下过程实现的:

1. 身份验证:证书确保了网站或服务的身份,防止恶意实体冒充合法的网站。

2. 数据加密:证书中的公钥用于加密传输数据,这样只有拥有相应私钥的目标服务器才能解密数据,从而防止中间人窃听。

3. 数据完整性:通过数字签名,证书保证数据在传输过程中没有被篡改,因为任何修改都会导致数字签名验证失败。

总体而言,证书在互联网通信中起到了非常重要的作用,它们确保了我们能够安全地浏览网站、进行在线交易以及传输敏感信息,同时抵御了许多网络攻击。


pem文件是什么

PEM (Privacy Enhanced Mail) 文件是一种常见的文件格式,通常用于存储加密证书、私钥和其他加密相关的数据。PEM 格式最初是为了加密电子邮件而开发的,但后来广泛用于其他安全领域,如 SSL/TLS 证书、数字证书、公钥、私钥等。

PEM 文件使用 Base64 编码,以 ASCII 文本的形式存储加密数据,这使得它们在跨平台和网络传输时更易于处理。PEM 文件通常以 ".pem" 或 ".crt" 为后缀,也可以使用其他后缀,如 ".key"。

PEM 文件可以包含以下类型的数据:

1. 证书(Certificate):用于验证实体身份的数字证书,如 SSL/TLS 证书。证书文件通常具有 ".crt" 或 ".pem" 后缀。

2. 私钥(Private Key):用于解密加密数据的私钥。私钥文件通常具有 ".key" 或 ".pem" 后缀。

3. 公钥(Public Key):与私钥配对的公开可用的密钥。公钥文件通常具有 ".pub" 或 ".pem" 后缀。

PEM 文件的内容通常以 "-----BEGIN..." 和 "-----END..." 之间的标记开始和结束。例如:

----BEGIN CERTIFICATE-----
MIIGZjCCBU6gAwIBAgIQL9+89dHcNr5I5y2XfXJ6hjANBgkqhkiG9w0BAQsFADBs
...
3lt2Jea1oKprNJh5SsSMxw==
-----END CERTIFICATE-----

----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDBDhXgRxddBnMG
...
zHbMjw6ihYTkYDQ==
-----END PRIVATE KEY-----

由于 PEM 文件采用文本格式,可以使用任何文本编辑器来查看和编辑其内容。然而,确保私钥等敏感信息保持机密,并只在需要的时候与受信任的实体共享。

公钥为什么要放在证书文件里面?

将公钥放在证书文件中是为了确保公钥的真实性和完整性,并建立信任关系。这样做有以下几个重要的原因:

  1. 身份验证:证书是由受信任的证书颁发机构(CA)签署的,而 CA 在颁发证书之前会对证书持有者的身份进行验证。因此,证书中包含的公钥可以用于验证证书持有者的身份。客户端可以使用 CA 的公钥来验证证书的签名,确保证书是由受信任的 CA 颁发的,从而建立服务器身份的信任。

  2. 公钥分发:将公钥嵌入在证书中是一种方便的方法,使得客户端可以轻松地获取到服务器的公钥。当客户端连接到服务器时,服务器会将其证书发送给客户端。客户端从证书中提取公钥,然后可以使用这个公钥来加密敏感数据,确保在传输过程中的机密性。

  3. 证书链:证书文件中可能包含证书链,即一个或多个中间证书,用于构建信任链。这些中间证书颁发了服务器证书,而中间证书本身又是由更高级的 CA 颁发的。通过验证证书链,客户端可以确认服务器证书是否由受信任的根证书颁发机构签名,进一步增强了服务器身份的信任。

  4. 证书续期和更新:将公钥和证书绑定在一起,使得当服务器证书需要续期或更新时,新的证书可以包含相同的公钥。这样,客户端在更新后仍然可以使用相同的公钥进行安全通信,无需对公钥进行额外的更改或验证。

综上所述,将公钥放在证书文件中是一种安全且方便的做法,有助于确保服务器身份的真实性、建立信任关系,并保障通信的安全性。

支付系统 公钥为什么要放在证书文件里面?

在支付系统中,公钥同样被放置在证书文件中,以类似的原因来确保通信的安全性和建立信任关系。支付系统作为涉及敏感金融信息的关键组件,对安全性要求非常高,使用证书来管理和传输公钥是一个常见的做法。以下是支付系统中将公钥放置在证书文件中的重要原因:

  1. 身份验证:在支付系统中,公钥可以用于验证服务器的身份。支付服务提供商通常会使用 SSL/TLS 证书来保护客户与服务器之间的通信。客户端在与服务器建立连接时,会检查服务器的证书,并使用证书中的公钥来验证证书的签名。这样客户端就能够确认服务器的身份是否真实、是否由受信任的 CA 颁发的。

  2. 数据加密:公钥可以用于加密传输敏感数据。在支付系统中,客户端可能需要将信用卡信息等敏感数据发送给服务器进行支付处理。使用服务器的公钥对这些敏感数据进行加密,确保在传输过程中数据的机密性。

  3. 数字签名:在支付系统中,数字签名同样是非常重要的。数字签名可以用于验证交易的真实性和完整性。在支付交易中,服务器可以使用私钥对交易数据进行数字签名,客户端在收到响应后,使用服务器的公钥来验证数字签名的有效性,确保交易没有被篡改。

  4. 证书链:支付系统可能涉及多个服务端组件,每个组件都有其对应的证书。证书链的机制用于建立信任链,确保服务器证书是由受信任的 CA 签发的。在支付系统中,证书文件可能包含整个证书链,以保证所有组件都能被正确地信任。

通过将公钥放在证书文件中,支付系统可以确保通信的安全性,防止敏感信息泄漏、数据篡改和恶意攻击。这种安全机制对于支付系统的可信性和用户信任至关重要。

公钥是可以加密或者验证签名,为什么不放配置文件,而是放证书文件里面?

确实,公钥是可以用于加密数据或验证数字签名的。技术上,公钥可以作为配置文件的一部分进行传递,但在实际使用中,将公钥放在证书文件中更为常见,并且有一些优势:

  1. 数字证书的信任链:将公钥放在证书文件中是为了建立数字证书的信任链。证书文件中除了包含公钥外,还包含了相关的数字签名和证书链信息。这个证书链能够追溯到受信任的根证书,从而确保公钥是由受信任的证书颁发机构签发的。通过验证证书链,可以建立对服务器身份的信任,这在安全性要求较高的场景中非常重要,比如支付系统。

  2. 身份验证:证书中包含了服务器的身份信息,例如证书持有者的名称、组织、国家等。将公钥和身份信息一起打包在证书中,可以提供更丰富的服务器身份验证和认证机制。这对于支付系统等安全性要求高的场景尤为重要,以确保客户端连接的是合法和受信任的服务器。

  3. 数据加密和数字签名的完整性:在证书文件中,公钥与数字签名和其他元数据一起被签署和存储,确保了数据加密和数字签名的完整性。任何对证书的篡改都会导致数字签名验证失败或者无法正确解密数据,从而能够快速发现潜在的安全问题。

  4. 方便管理和分发:将公钥放在证书文件中,使得证书可以作为独立的实体在网络上分发和管理。证书文件通常使用 PEM 或 DER 等通用格式,易于存储、传输和导入到各种系统和设备中。

总的来说,将公钥放在证书文件中可以提供更强大的安全性和可信度保障,同时也更方便进行管理和分发。这种做法在实践中被广泛使用,特别是在需要保障数据安全和服务器身份认证的领域,如支付系统和其他涉及敏感信息的应用。

私钥就是个普通文件吗

私钥在本质上是一个包含了加密算法生成的随机二进制数据的文件。然而,它远非是普通文件,而是加密通信中最为敏感和重要的部分之一。私钥的保护和安全性对于确保通信的保密性和完整性至关重要。

以下是私钥的一些重要特点和注意事项:

  1. 敏感性:私钥是用于解密数据或生成数字签名的关键部分。任何拥有私钥的人或实体都能够在加密通信中解密加密数据或伪造数字签名。因此,私钥应该严格保密,只能由授权的个人或实体持有。

  2. 随机性:私钥是由加密算法生成的随机二进制数据,具有极高的随机性。这使得私钥在实践中无法通过简单的猜测或推导来获取。

  3. 存储和保护:由于私钥的敏感性,它应该以安全的方式存储和保护。通常,私钥应存储在安全的硬件设备(如硬件安全模块 HSM)中,或者使用密码保护和加密来存储在安全的计算机或服务器上。

  4. 私钥配对:私钥通常与一个相关的公钥配对使用。公钥用于加密数据或验证数字签名,而私钥用于解密数据或生成数字签名。这对密钥是通过加密算法生成的,但不能从公钥推导出私钥。

  5. 证书请求:私钥还用于生成证书请求(Certificate Signing Request,CSR),这是向证书颁发机构(CA)申请数字证书的一种格式。CSR 中包含公钥,并用私钥对其进行签名,以便 CA 在颁发证书时确认公钥的真实性。

总结而言,私钥是加密通信中的关键要素,其安全性至关重要。对私钥的保护和正确使用是确保通信安全的关键步骤。因此,私钥不是普通文件,而是需要特殊处理和保护的敏感数据。