如何通过编程从Elytron BCFIPS凭证存储中读取密码?
问题描述
我用Bouncy Castle提供程序创建了符合FIPS 140-2标准的凭证存储,操作步骤如下:
- 生成密钥:
keytool -genseckey -alias key -keyalg AES -keysize 256 -keystore keystore.bcfks -storetype BCFKS -storepass myPass -keypass myPass - 通过Elytron子系统创建凭证存储:
/subsystem=elytron/credential-store=myCredentialstore:add(relative-to=jboss.server.config.dir, credential-reference={clear-text=”${ENC::myResolver:myEncodedExpression}”}, implementation-properties={keyAlias=key, external=true, externalPath=credentialStore.bcfks, keyStoreType=BCFKS}, create=true, path=keystore.bcfks, modifiable=true)
当前凭证存储可正常使用,但编程读取密码时遇到问题,尝试了两种方案均失败:
方案1:使用KeyStoreCredentialStore类
能读取凭证存储中的别名,但无法获取密码,不清楚retrieve()方法的正确参数配置,代码如下:
public static Password getpassword() throws CredentialStoreException { Password storePassword = ClearPassword.createRaw(ClearPassword.ALGORITHM_CLEAR, MY_CLEAR_PASSWORD.toCharArray()); ProtectionParameter protectionParameter = new CredentialSourceProtectionParameter(IdentityCredentials.NONE.withCredential(new PasswordCredential(storePassword))); Provider bcProvider = new BouncyCastleFipsProvider(); Security.addProvider(bcProvider); KeyStoreCredentialStore keyStoreCredentialStore = new KeyStoreCredentialStore(); Map<String, String> kscsConfiguration = new HashMap<>(); String keystorePath = "myPath/keystore.bcfks"; String externalPath = "myPath/credentialStore.bcfks"; kscsConfiguration.put("location", keystorePath); kscsConfiguration.put("modifiable", "true"); kscsConfiguration.put("keyStoreType", "BCFKS"); kscsConfiguration.put("keyAlias", "key"); kscsConfiguration.put("external", "true"); kscsConfiguration.put("externalPath", externalPath); Provider[] providers = { bcProvider }; keyStoreCredentialStore.initialize(kscsConfiguration, protectionParameter, providers); PasswordCredential passwordVredential = keyStoreCredentialStore.retrieve(WEBUSER_PASSWORD_ALIAS, PasswordCredential.class, KeyStoreCredentialStore.KEY_STORE_CREDENTIAL_STORE, null, protectionParameter); return passwordVredential.getPassword(); }
方案2:使用ServiceContainer
调用CurrentServiceContainer.getServiceContainer()返回null,代码如下:
public static String getClientSecret(String credentialStore, String secretAlias) { final ServiceName SERVICE_NAME_CRED_STORE = ServiceName.of("org", "wildfly", "security", "credential-store"); final ServiceName sn = ServiceName.of(SERVICE_NAME_CRED_STORE, credentialStore); final ServiceRegistry registry = CurrentServiceContainer.getServiceContainer(); final ServiceController<?> credStoreService = registry.getService(sn); final CredentialStore cs = (CredentialStore) credStoreService.getValue(); if (!cs.exists(secretAlias, PasswordCredential.class)) { throw new CredentialStoreException("Alias " + secretAlias + " not found in credential store."); } final Password password; try { password = cs.retrieve(secretAlias, PasswordCredential.class).getPassword(); } catch (CredentialStoreException e) { e.printStackTrace(); return null; } if (!(password instanceof ClearPassword)) { throw new ClassCastException("Password is not of type ClearPassword"); } return new String(((ClearPassword) password).getPassword()); }
请问如何解决上述问题,成功从该凭证存储中读取密码?
解决方案
针对方案1的修复
你的retrieve()方法参数配置有误,需调整以下几点:
- 简化参数:
retrieve()第三个参数不需要传入KeyStoreCredentialStore.KEY_STORE_CREDENTIAL_STORE,改为null即可(表示使用默认凭证类型)。 - 验证密码一致性:确保
protectionParameter使用的是创建凭证存储时的storepass(即代码中的MY_CLEAR_PASSWORD)。 - 确认别名准确性:检查
WEBUSER_PASSWORD_ALIAS是否为凭证存储中实际存在的别名。
修改后的retrieve()调用代码:
PasswordCredential passwordCredential = keyStoreCredentialStore.retrieve( WEBUSER_PASSWORD_ALIAS, PasswordCredential.class, null, null, protectionParameter );
额外注意事项:
- 确认
externalPath指向的credentialStore.bcfks路径正确。 - 保证Bouncy Castle FIPS Provider版本与WildFly Elytron版本兼容,避免版本冲突导致密钥读取失败。
针对方案2的修复
CurrentServiceContainer.getServiceContainer()返回null,是因为代码未运行在WildFly容器上下文内:
- 运行环境限制:该方法仅在WildFly服务器内部部署的代码(如EJB、Servlet、WildFly模块)中有效,独立Java应用无法直接获取容器服务。
- 适配方案:
- 若为独立应用,建议采用方案1的修复版本。
- 若为WildFly内部应用,需将代码部署为WildFly模块或应用,并添加依赖:
在MANIFEST.MF中添加:
或在Dependencies: org.wildfly.security.elytronjboss-deployment-structure.xml中配置:<jboss-deployment-structure> <deployment> <dependencies> <module name="org.wildfly.security.elytron" /> </dependencies> </deployment> </jboss-deployment-structure>
额外验证步骤
- 用Elytron CLI命令确认目标别名存在:
/subsystem=elytron/credential-store=myCredentialstore:read-aliases() - 核对密钥库密码和密钥别名:确保
keyAlias与生成密钥时指定的key一致,密码与storepass匹配。
内容的提问来源于stack exchange,提问作者Timea
相关产品推荐
相关产品推荐

