4

我正在向我的 J2EE 应用程序添加对 FIDO U2F 的支持(这基本上是使用硬件令牌保护登录)。我正在使用来自 yubico 的库 u2flib-server-core,它使用 BouncyCastleCrypto 处理协议中的加密操作。但是,在从持久存储中解码公钥时,我不断收到消息异常

“无法识别关键规格”

我已将问题从库中缩小到此功能

public PublicKey decodePublicKey(byte[] encodedPublicKey) throws U2fBadInputException {
        try {
            X9ECParameters curve = SECNamedCurves.getByName("secp256r1");
            ECPoint point;
            try {
                point = curve.getCurve().decodePoint(encodedPublicKey);
            } catch (RuntimeException e) {
                throw new U2fBadInputException("Could not parse user public key", e);
            }

            return KeyFactory.getInstance("ECDSA").generatePublic(
                    new ECPublicKeySpec(point,
                            new ECParameterSpec(
                                    curve.getCurve(),
                                    curve.getG(),
                                    curve.getN(),
                                    curve.getH()
                            )
                    )
            );
        } catch (GeneralSecurityException e) { //This should not happen
            throw new RuntimeException(e);
        }
    }

方法 generatePublic 抛出异常,该异常被捕获并作为 RuntimeException 重新抛出。

我已验证 KeyFactory.getInstance 从 BC 提供商返回 KeyFactory。在 Wildfly 之外运行此代码可以完美运行。(我不得不将 bcprov-ext-jdk15on-154.jar 放入 java 的 /lib/ext 中)。

我已经尝试为 bouncycastle 更新 Wildfly 的模块,目前我已经添加了在http://www.bouncycastle.org/latest_releases.html上发布的所有 6 个 jars

堆栈跟踪中有趣的部分是

java.security.spec.InvalidKeySpecException: key spec not recognised
    at org.bouncycastle.jcajce.provider.asymmetric.util.BaseKeyFactorySpi.engineGeneratePublic(Unknown Source)
    at org.bouncycastle.jcajce.provider.asymmetric.ec.KeyFactorySpi.engineGeneratePublic(Unknown Source)
    at java.security.KeyFactory.generatePublic(KeyFactory.java:334)
    at com.yubico.u2f.crypto.BouncyCastleCrypto.decodePublicKey(BouncyCastleCrypto.java:60)
    at com.yubico.u2f.data.messages.key.RawAuthenticateResponse.checkSignature(RawAuthenticateResponse.java:64)
    at com.yubico.u2f.U2fPrimitives.finishAuthentication(U2fPrimitives.java:153)
    at com.yubico.u2f.U2F.finishAuthentication(U2F.java:116)
    at com.yubico.u2f.U2F.finishAuthentication(U2F.java:90)

希望有人可以帮助我:-)在此先感谢

编辑:我已经尝试过使用其他模式的代码,并且看起来没有单个事件被识别。使用 EC 例外是不同的,因为它使用了其他提供者,但是配置提供者列表 BC 位于顶部会产生与我提到的相同的例外。

编辑我认为这可能是某种类加载问题,所以我打开了详细日志记录,这里是有趣的日志

[Loaded org.bouncycastle.jcajce.provider.asymmetric.ec.KeyFactorySpi$ECDSA from file:/home/martin/java/jdk1.8.0_45/jre/lib/ext/bcprov-jdk15on-154.jar]
[Loaded org.bouncycastle.jce.spec.ECKeySpec from jar:file:/opt/wildfly-10.0.0.Final/modules/system/layers/base/org/bouncycastle/main/bcprov-jdk15on-1.52.jar!/]

KeyFactorySpi 和 ECKeySpec 来自两个不同的 jar(类加载器?),因此 KeyFactory 中使用的 instanceof 失败

4

1 回答 1

6

终于找到问题了:-)

当我打开类加载器的详细日志记录时,我发现 KeySpec 来自不同的类加载器,因为 KeyFactorySpi 检查了该 KeySpec 的实例。这是我在解决此问题时引起的问题。由于 Wildfly 10 附带了 RestEasy 所依赖的 BouncyCastle 模块,因此它会被加载。我使用的 Hovever 库也提供了一些 BouncyCastle 类。

我所要做的就是创建具有以下内容的 jboss-deployment-structure.xml

<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.1">
    <deployment>
        <dependencies>
            <module name="org.bouncycastle" />
        </dependencies>
    </deployment>
</jboss-deployment-structure>

这让我可以将 Wildfly 的模块用于 BouncyCastle。然而,当我这样做时,我已经尝试将 BouncyCastle 放在我用来运行服务器的 JRE 的 lib/ext/ 中。这导致与另一个原因完全相同的错误:-)

综上所述,当使用带有 Wildfly 10 的 BouncyCastle 时,您必须确保以下几点:

  1. 创建 jboss-deployment-structure.xml 并依赖 Wildfly 的模块}或者,您可以使用 MANIFEST.mf 来执行此操作|
  2. 确保您正在使用的 JRE 的 lib/ext/ 中没有 BouncyCastle 提供程序
  3. 如果您动态添加 BouncyCastle JCE 提供者,您还必须使用 JCE Unlimited 策略文件(当然,如果您合法地可以)

希望这对将来的某人有所帮助:-)

于 2016-03-28T12:25:18.530 回答