再谈RSA-客户端与服务器互通

独奏

学习思考|2015-5-16|最后更新: 2023-2-23|
type
status
date
slug
summary
tags
category
icon
password
曾经写过一篇 RSA 加密的文章,没想到今天使用 RSA 加密的时候还是会面临这么多问题,这里就再整理一下。
现在的项目是在接口部分使用 RSA 加密了一个时间戳用作验证字段,防止接口攻击。由于服务器是 JAVA 的,最开始由服务器生成的私钥和公钥,公钥给的 der 文件,但是在 iOS 上面测试发现使用系统 API 无法设置公钥,后来在一个三方库的代码里发现在验证 der 文件的时候有如下一段代码
因此就很好奇这个0x30开头是个什么东西,结果就引出了以下问题。。。

DER 编码规则

这个文章说明了 DER 文件的相关编码规则,从中得知,DER 文件的二进制开头必然是0x30,但是看了下服务器那边给的 DER 文件,好像不对。跟服务器沟通后,决定由我们生成公私钥,再把私钥发给服务器。

生成公私钥和DER证书

最开始只是从网上找了一段代码生成公私钥
这个命令可以在 osx 系统上直接生成 PEM 的私钥和 DER 的公钥,后来发现这个代码生成的私钥是经过 DES 加密后的私钥。所以只能一步一步来了。
其实上面那个命令包含了多个步骤。下面是一步一步拆解:
1)创建私钥
这里私钥可以指定位数,通常使用1024位的
2)生成公钥
RSA加密浅析我们可以知道公私钥是一一对应的,所以生成公钥需要指定一个私钥。
3)创建证书请求
这里是生成了一个 csr 文件,这个 csr 文件其实跟我们在 osx 系统的钥匙串的证书助理里面从证书颁发机构请求证书后生成的certSigningRequest文件是一样的,csr 其实就是certSigningRequest的缩写。
4)自签署生成公钥证书
经过上一步之后我们就可以拿着 csr 文件去生成一个 DER 证书文件了
这个命令需要指定公钥证书标准为x509,因为 iOS 的 API 只支持这种标准的证书。 同时还要指定证书的有效期,由于我是用于客户端和服务器通信的,所以有效期设置了一个很大的值,3650天(10年)。
5)公钥转成 PKCS#8 格式
如果你的服务器端是 PHP 的话,那么这一步就不是必须的了,第一步生成的私钥直接丢给你的服务器开发人员就可以使用了。
但是如果你的服务器是 java 或者 .NET 的,那么他们对公钥的格式还有进一步的要求,必须是 PKCS#8 格式的公钥,所以你需要同过这个命令把私钥转成 PKCS#8格式的。

公私钥的使用

通过前面步骤我们会得到以下几个文件
  • rsa_private_key.pem: 私钥文件
  • pkcs8_rsa_private_key.pem: PKCS#8格式的私钥文件
  • rsa_public_key.pem: 公钥文件
  • cert.csr: 公钥的证书请求
  • rsa_public_key.der: 公钥的证书文件
在客户端与服务器的通信中 RSA通常有两个用途
  1. 用于数据加密(验证)
  1. 用于 https 协议的自签署证书
下面说一下服务器与客户端的配置问题:
1)服务器
如果你的服务器端是 PHP 的,那么直接使用rsa_private_key.pem私钥文件就可以了 如果你的服务器是 JAVA 或者.NET 的,那么你需要pkcs8_rsa_private_key.pem私钥文件
2)Android
Android 客户端直接使用rsa_public_key.pem就可以了
3)iOS
如果使用 RSA 只使用来做数据的验证或者加解密,那么 iOS 既可以使用rsa_public_key.pem公钥文件又可以使用rsa_public_key.der公钥证书。 如果你的网络通信是使用 https 协议自签署证书的话,那你就需要使用rsa_public_key.der公钥证书来进行网络连接了。

扩展阅读