You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于BouncyCastle正确实现DefaultTlsServer的getRSASignerCredentials()方法

问题:BouncyCastle TLS Server重写getRSASignerCredentials()方法报错处理

我使用bctls-jdk18on-1.72.jar实现TLS Server,编写了继承DefaultTlsServer的DefaultTlsServerImpl类,并重写getRSASignerCredentials()方法,代码如下:

class DefaultTlsServerImpl extends DefaultTlsServer {
    ...
    @Override
    protected TlsCredentialedSigner getRSASignerCredentials() throws IOException {
        TlsCryptoParameters cryptoParams = new TlsCryptoParameters(context);
        SignatureAndHashAlgorithm signatureAndHashAlgorithm = null;
        if (TlsUtils.isSignatureAlgorithmsExtensionAllowed(context.getServerVersion())) {
            signatureAndHashAlgorithm = new SignatureAndHashAlgorithm(HashAlgorithm.sha256, SignatureAlgorithm.rsa);
        }
        return new BcDefaultTlsCredentialedSigner(cryptoParams, BC_TLS_CRYPTO, PRIVATE_KEY, CERTIFICATE, signatureAndHashAlgorithm);
    }
    ...
}

调用该方法后抛出如下异常:

org.bouncycastle.tls.TlsFatalAlert: internal_error(80)
    at org.bouncycastle.tls.DTLSServerProtocol.accept(Unknown Source)
    at org.bouncycastle.tls.DTLSServerProtocol.accept(Unknown Source)
    ...
Caused by: java.lang.IllegalStateException: Invalid algorithm: {sha256(4),rsa(1)}
    at org.bouncycastle.tls.crypto.impl.bc.BcTlsDSSSigner.generateRawSignature(Unknown Source)
    at org.bouncycastle.tls.DefaultTlsCredentialedSigner.generateRawSignature(DefaultTlsCredentialedSigner.java:53)
    at org.bouncycastle.tls.TlsUtils.generateServerKeyExchangeSignature(TlsUtils.java:2602)
    at org.bouncycastle.tls.TlsECDHEKeyExchange.generateServerKeyExchange(TlsECDHEKeyExchange.java:79)
    at org.bouncycastle.tls.DTLSServerProtocol.serverHandshake(Unknown Source)
    ... 16 more

尝试改为使用与SHA256withECDSA证书对应的代码:

new SignatureAndHashAlgorithm( HashAlgorithm.sha256, SignatureAlgorithm.ecdsa );

则会抛出异常org.bouncycastle.tls.TlsFatalAlert: illegal_parameter(47)。请问该如何正确实现getRSASignerCredentials()方法?


核心问题分析

  1. 第一个异常原因:指定的{sha256(4),rsa(1)}签名算法与实际使用的私钥/证书类型不匹配。异常栈中的BcTlsDSSSigner说明代码在尝试用DSS/DSA签名器处理RSA算法,证明PRIVATE_KEY或CERTIFICATE是DSA类型,而非RSA类型,导致算法兼容失败。
  2. 第二个异常原因:换成ECDSA算法后抛出illegal_parameter,是因为getRSASignerCredentials()方法专门用于返回RSA类型的签名凭据,返回ECDSA类型凭据违反了方法的设计意图,TLS协议层判定参数非法。

正确实现方案

方案1:使用RSA类型的证书/私钥

确保PRIVATE_KEY和CERTIFICATE是RSA算法生成的,按以下方式实现方法:

@Override
protected TlsCredentialedSigner getRSASignerCredentials() throws IOException {
    TlsCryptoParameters cryptoParams = new TlsCryptoParameters(context);
    SignatureAndHashAlgorithm signatureAndHashAlgorithm = null;
    
    // 仅当TLS版本支持签名算法扩展时指定
    if (TlsUtils.isSignatureAlgorithmsExtensionAllowed(context.getServerVersion())) {
        // RSA常规证书使用RSASSA-PKCS1-v1_5,对应SignatureAlgorithm.rsa_pkcs1
        signatureAndHashAlgorithm = new SignatureAndHashAlgorithm(HashAlgorithm.sha256, SignatureAlgorithm.rsa_pkcs1);
    }
    
    return new BcDefaultTlsCredentialedSigner(cryptoParams, BC_TLS_CRYPTO, PRIVATE_KEY, CERTIFICATE, signatureAndHashAlgorithm);
}

注意:BouncyCastle中SignatureAlgorithm.rsa对应RSASSA-PSS算法,常规RSA证书需使用rsa_pkcs1。

方案2:若使用ECDSA/DSA证书,重写对应方法

如果证书是ECDSA类型,不要重写getRSASignerCredentials(),而是重写getECDSASignerCredentials():

@Override
protected TlsCredentialedSigner getECDSASignerCredentials() throws IOException {
    TlsCryptoParameters cryptoParams = new TlsCryptoParameters(context);
    SignatureAndHashAlgorithm signatureAndHashAlgorithm = null;
    
    if (TlsUtils.isSignatureAlgorithmsExtensionAllowed(context.getServerVersion())) {
        signatureAndHashAlgorithm = new SignatureAndHashAlgorithm(HashAlgorithm.sha256, SignatureAlgorithm.ecdsa);
    }
    
    return new BcDefaultTlsCredentialedSigner(cryptoParams, BC_TLS_CRYPTO, PRIVATE_KEY, CERTIFICATE, signatureAndHashAlgorithm);
}

同理,DSA证书需重写getDSSSignerCredentials()方法。

额外注意点

  • 证书与私钥算法必须一致:RSA证书对应RSA私钥,ECDSA证书对应ECDSA私钥,否则会触发算法不兼容错误。
  • 检查TLS版本兼容性:确保使用的TLS版本(如TLS 1.2及以上)支持指定的签名算法扩展。

内容的提问来源于stack exchange,提问作者Horcrux7

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 06:37:47