刚刚的笔记没了,因为电脑蓝屏了,我又没保存。现在再补回。
一开始问题是出在没理解demo里面引用的pem文件。拿来测试)(在demo里先签名,然后紧接着就验签),结果发现,验签失败。
后面想想,私钥是银联自己的,而公钥则是对方提供给银联的。因此,用银联的私钥去签名,而用对方的公钥进行验签,验签当然会失败。
然后,就要想办法自己去生成公私钥的pem文件。一开始很排斥,不想自己去生成,感觉好麻烦,事实上,也花了好长时间去理解。
找了很久,找到了一篇生成pem文件的文章(找了很多篇,有些生成的pem文件不对,当时被误导了很久)。(前面也花了好一些时间,才意识到自己要百度的内容:openssl如何生成pem公私钥),文章连接为:https://blog.csdn.net/m0_38080126/article/details/77609304
一开始直接copy paste。
为了防止链接失败,就把文章内容拷下来了:
1、生成RSA密钥的方法
openssl genrsa -des3 -out privkey.pem 2048
这个命令会生成一个2048位的密钥,同时有一个des3方法加密的密码,如果你不想要每次都输入密码,可以改成:
openssl genrsa -out privkey.pem 2048
建议用2048位密钥,少于此可能会不安全或很快将不安全。
2、生成一个证书请求
openssl req -new -key privkey.pem -out cert.csr
这个命令将会生成一个证书请求,当然,用到了前面生成的密钥privkey.pem文件
这里将生成一个新的文件cert.csr,即一个证书请求文件,你可以拿着这个文件去数字证书颁发机构(即CA)申请一个数字证书。CA会给你一个新的文件cacert.pem,那才是你的数字证书。
如果是自己做测试,那么证书的申请机构和颁发机构都是自己。就可以用下面这个命令来生成证书:
openssl req -new -x509 -key privkey.pem -out cacert.pem -days 1095
这个命令将用上面生成的密钥privkey.pem生成一个数字证书cacert.pem
3、使用数字证书和密钥
有了privkey.pem和cacert.pem文件后就可以在自己的程序中使用了,比如做一个加密通讯的服务器
一开始直接copy生成私钥pem,然后走第二步,再走第三步。没去看文字,没去理解。
后来,理解了,第一步是生成pem文件,第二步是生成证书申请(用于向CA申请证书用的),第三步是通过私钥pem生成公钥pem。
也才明白,公钥pem是通过私钥pem生成的。
拿到两个pem文件就去测试了,结果出现了异常,在签名那里就死掉了。对比我自己创建的pem文件和demo里的pem文件,我发现,我的pem文件里面有多余的头和尾,如:
公钥pem的头和尾:
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
私钥pem的头和尾:
-----BEGIN RSA PRIVATE KEY-----
-----END RSA PRIVATE KEY-----
这里卡了很久。一直想不懂,为什么我的pem文件会有头和尾的部分,而demo的pem文件里面却没有。我在想是不是我生成pem的方式不对。去掉头和尾,运行程序,出错。吓得我赶紧回头,补上头和尾。
卡了很久,最后明白,原来没所谓,有头和尾没关系,在读取的时候,只要在代码中解析文件的时候跳过头和尾就可以了。我一开始以为直接修改文件会影响里面的内容。后来证实我是错的。可能我被那个异常信息吓到了。
只要在读取文件时,发现第一个符号是’-‘,就跳过这一行,就可以读取到正式的内容了。
对了,如果把头和尾都读进去,那么在签名那一步就会出错,错误信息忘了。如果把头尾去掉,那么还是会出现异常,出错的地方是在验签那里。
还有一个问题卡了我很久,Demo里是这样读取pem文件的:
//从私钥文件中读取私钥
File file = new File(System.getProperty("user.dir") + "\\src\\myPrivateKey.pem");
InputStreamReader read = new InputStreamReader(new FileInputStream(file), "UTF-8");//考虑到编码格式
BufferedReader bufferedReader = new BufferedReader(read);
String str = null;
while((str = bufferedReader.readLine()) != null) {
HttpServer.myPrivateKey += str + "\n";
}
read.close();
我在想,是不是错在换行这里???是不是不应该换行,直接拼接就好。我就改了(这是银联的人提供的demo,我竟然质疑他的),结果还是会出错。顿时没有了方向,到底问题是出在哪里。
百度的时候,有的人是通过key
文件来生成两个pem
文件。懵逼。。。
又看到有人说,通过openssl genrsa -out privkey.pem 2048
生成的私钥pem并不是能直接拿来用的,得把RSA私钥转换成PKCS8格式:
pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM –nocrypt
然后,控制台就输出了一个新的pem文件的内容,一看,发现,它的头尾是这样的:
-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----
这个才是对的把。我赶紧拷贝一份,作为新的pem文件,然后测试。
还是出错。然后百度继续查,最后查到一篇解决了这个问题的网址:
https://blog.csdn.net/weiyuefei/article/details/76269790
这篇生成两个pem文件的做法和开头提到的那个网址的做法不一样,这个才是有效的。
开头的网址生成的public.pem文件,头和尾专这样的:
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
而这篇文章生成的public.pem的头尾是这样的:
-----BEGIN PUBLIC KEY-----
-----END PUBLIC KEY-----
一看到这个,我想,这次应该对了!果然!
测试,输出:
验签结果:true
总算成功了。从上午10点多弄到下午5点。对pem文件,是第一次接触。对公私钥也是弄这项目才开始接触。努力吧!也算是学到了新东西啊。可能从文章上来看,好像没什么难度,但是事实上,就我而言,弄了很久。新东西,对背景什么的都不了解,所以说,以后在接触新东西之前,要理解好,理解好了再动手!!!
事实证明,银联提供的demo是没问题的,问题是出在我生成pem文件的生成。理解好公钥私钥,demo里的公钥私钥并不是一对的,demo是银联的,那么说明私钥是银联的,公钥是与银联交互的那一方的。理解这点很重要。
正确生成pem文件很重要,生成pem文件的操作为:
1、生成RSA密钥的方法
openssl genrsa -des3 -out privkey.pem 2048
这个命令会生成一个2048位的密钥,同时有一个des3方法加密的密码,如果你不想要每次都输入密码,可以改成:
openssl genrsa -out privkey.pem 2048
建议用2048位密钥,少于此可能会不安全或很快将不安全。
2、生成一个证书请求
openssl req -new -key privkey.pem -out cert.csr
这个命令将会生成一个证书请求,当然,用到了前面生成的密钥privkey.pem文件
这里将生成一个新的文件cert.csr,即一个证书请求文件,你可以拿着这个文件去数字证书颁发机构(即CA)申请一个数字证书。CA会给你一个新的文件cacert.pem,那才是你的数字证书。
如果是自己做测试,那么证书的申请机构和颁发机构都是自己。就可以用下面这个命令来生成证书:
openssl req -new -x509 -key privkey.pem -out cacert.pem -days 1095
这个命令将用上面生成的密钥privkey.pem生成一个数字证书cacert.pem
3、使用数字证书和密钥
有了privkey.pem和cacert.pem文件后就可以在自己的程序中使用了,比如做一个加密通讯的服务器