运行我的 keycloak 应用程序时,出现以下错误:
java.security.NoSuchAlgorithmException: ECDSA KeyFactory not available
at java.base/java.security.KeyFactory.<init>(KeyFactory.java:138) ~[na:na]
at java.base/java.security.KeyFactory.getInstance(KeyFactory.java:183) ~[na:na]
at org.keycloak.jose.jwk.JWKParser.createECPublicKey(JWKParser.java:107) ~[keycloak-core-15.0.2.jar:15.0.2]
... 61 common frames omitted
经过一番挖掘,发现 KeyFactory 无法将“ECDSA”确定为算法,因此我应该使用“EC”算法来生成公钥。
但是如果 KeyFactory 不支持“ECDSA”作为算法,为什么 Keycloak-15.0.2 JWKParser 类的 createECPublicKey 函数仍然尝试使用 ECDSA 生成公钥?
try {
ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec(name);
ECNamedCurveSpec params = new ECNamedCurveSpec("prime256v1", spec.getCurve(), spec.getG(), spec.getN());
ECPoint point = new ECPoint(x, y);
ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(point, params);
KeyFactory kf = KeyFactory.getInstance("ECDSA");
return kf.generatePublic(pubKeySpec);
} catch (Exception e) {
throw new RuntimeException(e);
}
这是一个错误吗?还是我完全错过了一些东西?
您的主要问题是您忘记告诉
KeyFactory.getInstance
ECDSA
来自 BouncyCastle 提供商。
你添加这个,
KeyFactory.getInstance("ECDSA");
就会起作用:
public static final Provider BC = new BouncyCastleProvider();
...
public static void myMethod() {
...
KeyFactory kf = KeyFactory.getInstance("ECDSA", BC);
}
或者,您可以将 BouncyCastleProvider 添加到您的提供商列表中:
Security.addProvider(new BouncyCastleProvider());
如果有人在完成建议的答案后仍然遇到困难:
即使在执行“Security.addProvider(new BouncyCastleProvider());”时,我在 docker 容器和 osgi BundleActivator 中运行此代码时也遇到同样的问题。就我而言,出现问题是因为我在 Bundleactivator 中添加了 Provider,如下所示:
Security.addProvider(new BouncyCastleProvider());
但是在构建我的项目后,它尝试再次执行addProvider,但它没有执行任何操作,因为从docker启动捆绑激活中已经存在一个Provider,但旧的Provider似乎已经过时了。对此进行调试,我发现“无法加载类 'org.bouncycastle.jcajce.provider.ametry.ec.KeyFactorySpi$ECDSA',因为 myBundle 的捆绑连接不再有效。”调用 KeyFactory.getInstance("ECDSA", BouncyCastleProvider.PROVIDER_NAME) 后。
所以这种情况下的解决方案就是删除并重新添加它:
public void start(final BundleContext bundleContext) throws Exception {
// removing the initial BouncyCastleProvider to cleanly re-add it avoids the "ECDSA Keyfactory not available" error
if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) != null) {
Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
}
// add BouncyCastle as security provider, since it is required by the keycloak filter adapter
Security.addProvider(new BouncyCastleProvider());
}