PEM证书内容格式处理问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/H_233/article/details/87729294

在做微信商户报备(小微商户)的业务时,要对接小微商户接口,接口中要求对一些敏感信息需要加密,这种加密放式不同于微信支付报文的加密,它们的采用密钥时不同的。小微接口加密使用公钥,这种公钥来自服务商相关的一种PEM格式的证书,证书的明文内容就是公钥,如下图所示:

所以想着将内容直接取出配到配置文件中(相当于一个字符串常量)

-----BEGIN CERTIFICATE-----MIID8TCCAtmgAwIBAgIUQhaIYV4wMcoF78FUAPpwC9lGZGswDQYJKoZIhvcNAQEL-----END CERTIFICATE-----

然后用来加密,加密使用的是X509的api,PublicKeyBytes为证书内容的字节数组

 public static String rsaEncrypt(String Content) throws Exception {  
         X509Certificate certificate = X509Certificate.getInstance(PublicKeyBytes); 
         PublicKey publicKey = certificate.getPublicKey(); 
         return encodeBase64(encryptPkcs1padding(publicKey,                                     
         Content.getBytes(CHAR_ENCODING))); 
 } 

结果发现报错,报错信息如下所示。

java.security.cert.CertificateException: Could not parse certificate: java.io.IOException: Incomplete data at sun.security.provider.X509Factory.engineGenerateCertificate(X509Factory.java:104) at java.security.cert.CertificateFactory.generateCertificate(CertificateFactory.java:339) ...

首先知道证书内容是没问题,证书字符串已经包括开始和结束。在我看来, 这是很完整的

于是找原因发现了相同的问题,并且已经有了解决,然后验证发下确实是这个原因。

相同问题的链接:http://www.doublecloud.org/2014/03/reading-x-509-certificate-in-java-how-to-handle-format-issue/

报错原因是因为PEM证书规范除了开始(-----BEGIN CERTIFICATE-----)和结束(-----END CERTIFICATE-----),中间每一行都是有CR(回车)或者LF(换行)的,而我的配置文件中配置的是没有的,只是一个简单的字符串,并不包含回车和换行。所以api在解析时就会报错,不满足规范。

下面时api解析的部分源码(完整的源代码:https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/classes/sun/security/provider/X509Factory.java)

            // Read BASE64 encoded data, might skip info at the beginning
            char[] data = new char[2048];
            int pos = 0;
 
            // Step 1: Read until header is found
            int hyphen = (c=='-') ? 1: 0; // count of consequent hyphens
            int last = (c=='-') ? -1: c; // the char before hyphen
            while (true) {
                int next = is.read();
                if (next == -1) {
                    // We accept useless data after the last block,
                    // say, empty lines.
                    return null;
                }
                if (next == '-') {
                    hyphen++;
                } else {
                    hyphen = 0;
                    last = next;
                }
                if (hyphen == 5 && (last==-1 || last=='\r' || last=='\n')) {
                    break;
                }
            }
 
            // Step 2: Read the rest of header, determine the line end
            int end;
            StringBuffer header = new StringBuffer("-----");
            while (true) {
                int next = is.read();
                if (next == -1) {
                    throw new IOException("Incomplete data");
            }

不难发现,api会对回车换行校验。

解决方法:

第一种:在字符串需要换行或回车的地方加入'\r\n'

第二种:保留证书内容原格式报错到文本文件中,然后代码中先读取该文本文件即可(推荐这一种,简单)

 总结:PEM格式证书规范包含开始和结束标识,同时还包含回车或换行。

猜你喜欢

转载自blog.csdn.net/H_233/article/details/87729294