Java安全加密API报错:无效密钥条目密码、最终块填充不正确
问题根源与解决方案
核心报错原因
- 密码不匹配:你存储密钥条目时用的保护密码是固定字符串
"XXXXX"转的字符数组,但读取时用的是传入的keypassbyte转十六进制字符串后得到的字符数组,两者完全不一致,导致密钥解密失败抛出填充错误。 - 密钥库类型不匹配:你要实现的keytool命令指定了
-storetype JCEKS,如果代码初始化KeyStore时没有明确指定JCEKS类型,默认的JKS类型不支持存储对称密钥,也会引发异常。 - 冗余操作:try-with-resources语法会自动关闭流,你额外调用
fos.close()属于冗余代码,但不属于本次报错的核心原因。
修复方案
存储代码修正
首先明确两个密码的对应关系:storepass是整个密钥库的存储密码,keypass是单个密钥条目的加密密码,两者可以独立设置,但读写逻辑必须完全一致。
key=get128MD5(strToHash); System.out.println(String.format("Hashing value : '%s' ", Hex.toHexString(key))); try { // 明确指定JCEKS类型,和keytool命令对应 KeyStore ks = KeyStore.getInstance("JCEKS"); ks.load(null, null); // 初始化空密钥库,必填 // 如果要使用keypassbyte作为密钥条目密码,存储和读取的转换逻辑必须完全统一 char[] entryPass = Hex.toHexString(keypassbyte).toCharArray(); KeyStore.ProtectionParameter protParam = new KeyStore.PasswordProtection(entryPass); SecretKey mySecretKey = new SecretKeySpec(key,"AES"); KeyStore.SecretKeyEntry skEntry = new KeyStore.SecretKeyEntry(mySecretKey); ks.setEntry(alias, skEntry, protParam); // 密钥库存储密码,和后续加载密钥库时用的密码保持一致 char[] storePass = "some_pwd".toCharArray(); try (FileOutputStream fos = new FileOutputStream("filename")) { ks.store(fos, storePass); // 无需手动关闭流,try-with-resources自动处理 } catch (FileNotFoundException e1) { e1.printStackTrace(); } } catch (KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException e1) { e1.printStackTrace(); }
读取代码修正
要先完成密钥库的加载,再读取密钥条目:
// 新增密钥库加载逻辑,必须先执行加载再读取密钥 public static void loadKeyStore(String filePath, char[] storePass) throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException { ks = KeyStore.getInstance("JCEKS"); try(FileInputStream fis = new FileInputStream(filePath)) { ks.load(fis, storePass); } } public static Key getKey(String keyalias,byte[] keypassbyte) throws KeyStoreException { Key key = null; try{ if(ks!=null){ log.info("Getting key from Keystore."); // 密码转换逻辑和存储时完全一致 char[] entryPass = Hex.toHexString(keypassbyte).toCharArray(); key = ks.getKey(keyalias, entryPass); } if(key==null){ throw new KeyStoreException("Failed to get secret key entry."); } }catch (NoSuchAlgorithmException nsae) { throw new KeyStoreException("Algorithm for recovering the secret key cannot be found." + nsae.getMessage()); }catch (UnrecoverableEntryException uee) { throw new KeyStoreException("Invalid entry password to recover secret." + uee.getMessage()); }catch (KeyStoreException kse) { throw new KeyStoreException("Failed to get secret key entry." + kse.getMessage()); }catch(NullPointerException ex) { throw new NullPointerException("NullPointerException " + ex.getMessage()); } catch (RuntimeException e) { throw new RuntimeException("Failed to get secret key."+ e.getMessage()); } return key; }
内容的提问来源于stack exchange,提问作者user17239580
相关产品推荐
相关产品推荐

