用如下方法加载私钥时,可能会抛出java.security.InvalidKeyException: IOException : Short read of DER length:

public static PrivateKey getPrivateKeyFromBytes(String crtBase64, String type) throws Exception {
		try {
			byte[] baKey = Base64.decode(crtBase64);
			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
			PrivateKey prvkey = keyFactory.generatePrivate(
					type.equals("PKCS") ? new PKCS8EncodedKeySpec(baKey) : new X509EncodedKeySpec(baKey));
			return prvkey;
		} catch (Exception e) {
			throw new Exception("读取私钥失败" + e.getMessage());
		}
	}

异常详情类似如下:

Caused by: java.security.InvalidKeyException: IOException : Short read of DER length
        at sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:351)
        at sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:356)
        at sun.security.rsa.RSAPrivateCrtKeyImpl.<init>(RSAPrivateCrtKeyImpl.java:91)
        at sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(RSAPrivateCrtKeyImpl.java:75)
        at sun.security.rsa.RSAKeyFactory.generatePrivate(RSAKeyFactory.java:316)
        at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:213)
		at com.alipay.api.internal.util.AlipaySignature.rsa256Sign(AlipaySignature.java:141)
        at com.alipay.api.internal.util.AlipaySignature.rsaSign(AlipaySignature.java:102)
        at com.alipay.api.DefaultAlipayClient.getRequestHolderWithSign(DefaultAlipayClient.java:323)
        at com.alipay.api.DefaultAlipayClient.doPost(DefaultAlipayClient.java:452)
        at com.alipay.api.DefaultAlipayClient._execute(DefaultAlipayClient.java:403)
        at com.alipay.api.DefaultAlipayClient.execute(DefaultAlipayClient.java:130)
        at com.alipay.api.DefaultAlipayClient.execute(DefaultAlipayClient.java:117)
        at com.alipay.api.DefaultAlipayClient.execute(DefaultAlipayClient.java:111)
        at sun.reflect.GeneratedMethodAccessor164.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
        at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133)
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)

导致异常的原因通常有两种:第一,JDK加密算法问题,第二,秘钥内容自身问题。

JDK jar包问题

因为某些国家的进口管制限制,Java发布的运行环境包中的加解密有一定的限制。比如默认不允许256位密钥的AES加解密,解决方法就是修改策略文件。

下载与JDK或JRE对应版本的jce文件包,如jdk为1.8,所以下载 jce_policy-8.zip,官网下载地址:https://www.oracle.com/java/technologies/javase-jce8-downloads.html

下载解压后,把jar文件上传到需要安装jce机器上JDK或JRE的security目录下,覆盖源文件即可。

JDK:将两个jar文件放到%JDK_HOME%\jre\lib\security下
JRE:将两个jar文件放到%JRE_HOME%\lib\security下
覆盖之前,记得备份源文件,以防万一。

加载秘钥java.security.InvalidKeyException: IOException : Short read of DER length异常处理插图

秘钥问题

秘钥自身问题就比较多,比如秘钥是否处理注释部分。或者秘钥存储是否完整等等。

个人遇到的一种情况是:秘钥存储在数据库中,数据库的字段长度设置的过短,导致秘钥在存储时被截取了,抛出上述异常。



加载秘钥java.security.InvalidKeyException: IOException : Short read of DER length异常处理插图1

关注公众号:程序新视界,一个让你软实力、硬技术同步提升的平台

除非注明,否则均为程序新视界原创文章,转载必须以链接形式标明本文链接

本文链接:http://choupangxia.com/2022/01/25/java-security-invalidkeyexception/