Java 为什么SSL握手会给出';无法生成DH密钥对';例外?
当我与一些IRC服务器建立SSL连接时(但不是其他服务器-可能是由于服务器的首选加密方法),我会遇到以下异常:Java 为什么SSL握手会给出';无法生成DH密钥对';例外?,java,ssl,cryptography,diffie-hellman,Java,Ssl,Cryptography,Diffie Hellman,当我与一些IRC服务器建立SSL连接时(但不是其他服务器-可能是由于服务器的首选加密方法),我会遇到以下异常: Caused by: java.lang.RuntimeException: Could not generate DH keypair at com.sun.net.ssl.internal.ssl.DHCrypt.<init>(DHCrypt.java:106) at com.sun.net.ssl.internal.ssl.ClientHandshak
Caused by: java.lang.RuntimeException: Could not generate DH keypair
at com.sun.net.ssl.internal.ssl.DHCrypt.<init>(DHCrypt.java:106)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverKeyExchange(ClientHandshaker.java:556)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:183)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:593)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:529)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:893)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1165)
... 3 more
是最后一个StartAndShake引发了异常。是的,“信任证书”有一些神奇的作用;该代码强制SSL系统不验证证书。(所以……这不是一个确定的问题。)
很明显,一种可能是esper的服务器配置错误,但我搜索了一下,没有找到任何其他关于esper的SSL端口有问题的人的参考资料,“openssl”连接到它(见下文)。所以我想知道这是否是Java默认SSL支持的一个限制,或者其他什么。有什么建议吗
下面是我从命令行使用“openssl”连接到aperture.esper.net 6697时发生的情况:
~ $ openssl s_client -connect aperture.esper.net:6697
CONNECTED(00000003)
depth=0 /C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support@esper.net
verify error:num=18:self signed certificate
verify return:1
depth=0 /C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support@esper.net
verify return:1
---
Certificate chain
0 s:/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support@esper.net
i:/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support@esper.net
---
Server certificate
-----BEGIN CERTIFICATE-----
[There was a certificate here, but I deleted it to save space]
-----END CERTIFICATE-----
subject=/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support@esper.net
issuer=/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support@esper.net
---
No client certificate CA names sent
---
SSL handshake has read 2178 bytes and written 468 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : DHE-RSA-AES256-SHA
Session-ID: 51F1D40A1B044700365D3BD1C61ABC745FB0C347A334E1410946DCB5EFE37AFD
Session-ID-ctx:
Master-Key: DF8194F6A60B073E049C87284856B5561476315145B55E35811028C4D97F77696F676DB019BB6E271E9965F289A99083
Key-Arg : None
Start Time: 1311801833
Timeout : 300 (sec)
Verify return code: 18 (self signed certificate)
---
如前所述,在所有这些之后,它确实成功地连接了,这比我的Java应用程序要多得多
如果相关的话,我使用的是OS X 10.6.8,Java版本1.6.0_26。问题在于基本大小。Java接受的最大可接受大小为1024位。这是一个已知的问题(请参阅) 我链接到的bug报告提到了一个使用BouncyCastle的JCE实现的错误。希望这对你有用 更新 这被报告为错误,最近已修复
但是,请注意,限制仅提高到2048位。对于大于2048位的尺寸,有:;修复似乎是针对9的。上述答案是正确的,但就解决方法而言,我在将BouncyCastle实现设置为首选提供程序时遇到了问题:
java.lang.ArrayIndexOutOfBoundsException: 64
at com.sun.crypto.provider.TlsPrfGenerator.expand(DashoA13*..)
我发现的一个论坛帖子也讨论了这一点,但没有提到解决方案。
我找到了一个对我的案例有效的替代方案,尽管我对它一点也不满意。解决方案是将其设置为Diffie-Hellman算法根本不可用。然后,假设服务器支持另一种算法,它将在正常协商期间进行选择。显然,这样做的缺点是,如果有人设法找到一台仅支持1024位或更少的Diffie Hellman的服务器,那么这实际上意味着它将无法在以前工作的地方工作
以下是给定SSLSocket(在连接之前)的代码:
List limited=newlinkedlist();
对于(字符串套件:((SSLSocket)s).GetEnablediPhone套件()
{
如果(!suite.contains(“\u DHE”))
{
加(套房);;
}
}
((SSLSocket)s).可设置的iPhone套件(仅限于阵列)(
新字符串[limited.size()]);
讨厌。尝试从下载“Java加密扩展(JCE)无限强度权限策略文件”,并替换JRE中的文件
这对我很有效,我甚至不需要使用BouncyCastle——标准的Sun JCE能够连接到服务器
另外,在更改策略文件之前尝试使用BouncyCastle时,我遇到了相同的错误(ArrayIndexOutOfBoundsException:64),因此我们的情况似乎非常相似。如果您使用的是jdk1.7.0_04,请升级到jdk1.7.0_21。该问题已在该更新中得到修复。这是我的解决方案(java 1.6),我还想知道为什么我必须这样做: 我从javax.security.debug=ssl中注意到,有时使用的密码套件是TLS\u DHE\u。。。有时,这是一个很好的例子。。。。如果我添加BouncyCastle,则会出现后一种情况。如果选择了TLS_ECDHE_uu,则它大部分时间都有效,但并不总是有效,因此即使添加BouncyCastle提供程序也不可靠(每隔一段时间,由于同样的错误而失败)。我猜在Sun SSL实现中,有时它选择DHE,有时它选择ECDHE 因此,这里发布的解决方案依赖于完全删除TLS_DHE______密码。注意:解决方案不需要BouncyCastle 因此,通过以下方式创建服务器证书文件:
echo |openssl s_client -connect example.org:443 2>&1 |sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'
另存为稍后将引用它,这里是SSL http get的解决方案,不包括TLS_DHE_uuu密码套件
package org.example.security;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.Socket;
import java.net.URL;
import java.net.UnknownHostException;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import org.apache.log4j.Logger;
public class SSLExcludeCipherConnectionHelper {
private Logger logger = Logger.getLogger(SSLExcludeCipherConnectionHelper.class);
private String[] exludedCipherSuites = {"_DHE_","_DH_"};
private String trustCert = null;
private TrustManagerFactory tmf;
public void setExludedCipherSuites(String[] exludedCipherSuites) {
this.exludedCipherSuites = exludedCipherSuites;
}
public SSLExcludeCipherConnectionHelper(String trustCert) {
super();
this.trustCert = trustCert;
//Security.addProvider(new BouncyCastleProvider());
try {
this.initTrustManager();
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void initTrustManager() throws Exception {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = new BufferedInputStream(new FileInputStream(trustCert));
Certificate ca = null;
try {
ca = cf.generateCertificate(caInput);
logger.debug("ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
caInput.close();
}
// Create a KeyStore containing our trusted CAs
KeyStore keyStore = KeyStore.getInstance("jks");
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
}
public String get(URL url) throws Exception {
// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
SSLParameters params = context.getSupportedSSLParameters();
List<String> enabledCiphers = new ArrayList<String>();
for (String cipher : params.getCipherSuites()) {
boolean exclude = false;
if (exludedCipherSuites != null) {
for (int i=0; i<exludedCipherSuites.length && !exclude; i++) {
exclude = cipher.indexOf(exludedCipherSuites[i]) >= 0;
}
}
if (!exclude) {
enabledCiphers.add(cipher);
}
}
String[] cArray = new String[enabledCiphers.size()];
enabledCiphers.toArray(cArray);
// Tell the URLConnection to use a SocketFactory from our SSLContext
HttpsURLConnection urlConnection =
(HttpsURLConnection)url.openConnection();
SSLSocketFactory sf = context.getSocketFactory();
sf = new DOSSLSocketFactory(sf, cArray);
urlConnection.setSSLSocketFactory(sf);
BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
String inputLine;
StringBuffer buffer = new StringBuffer();
while ((inputLine = in.readLine()) != null)
buffer.append(inputLine);
in.close();
return buffer.toString();
}
private class DOSSLSocketFactory extends javax.net.ssl.SSLSocketFactory {
private SSLSocketFactory sf = null;
private String[] enabledCiphers = null;
private DOSSLSocketFactory(SSLSocketFactory sf, String[] enabledCiphers) {
super();
this.sf = sf;
this.enabledCiphers = enabledCiphers;
}
private Socket getSocketWithEnabledCiphers(Socket socket) {
if (enabledCiphers != null && socket != null && socket instanceof SSLSocket)
((SSLSocket)socket).setEnabledCipherSuites(enabledCiphers);
return socket;
}
@Override
public Socket createSocket(Socket s, String host, int port,
boolean autoClose) throws IOException {
return getSocketWithEnabledCiphers(sf.createSocket(s, host, port, autoClose));
}
@Override
public String[] getDefaultCipherSuites() {
return sf.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
if (enabledCiphers == null)
return sf.getSupportedCipherSuites();
else
return enabledCiphers;
}
@Override
public Socket createSocket(String host, int port) throws IOException,
UnknownHostException {
return getSocketWithEnabledCiphers(sf.createSocket(host, port));
}
@Override
public Socket createSocket(InetAddress address, int port)
throws IOException {
return getSocketWithEnabledCiphers(sf.createSocket(address, port));
}
@Override
public Socket createSocket(String host, int port, InetAddress localAddress,
int localPort) throws IOException, UnknownHostException {
return getSocketWithEnabledCiphers(sf.createSocket(host, port, localAddress, localPort));
}
@Override
public Socket createSocket(InetAddress address, int port,
InetAddress localaddress, int localport) throws IOException {
return getSocketWithEnabledCiphers(sf.createSocket(address, port, localaddress, localport));
}
}
}
这是一篇相当古老的文章,但是如果您使用apachehttpd,您可以限制DH的大小。 请参阅“Java加密扩展(JCE)无限强度管辖权策略文件”的答案对我来说不起作用,但BouncyCastle的JCE提供商建议起了作用 以下是我在Mac OSC 10.7.5上使用Java 1.6.0_65-b14-462所采取的步骤 1) 下载这些JAR:
使用JRE重新启动应用程序并尝试一下您可以动态安装提供程序: 1) 下载这些JAR:
bcprov-jdk15on-152.jar
bcprov-ext-jdk15on-152.jar
WEB-INF/lib
(或您的类路径)
3) 动态添加提供程序:
import org.bouncycastle.jce.provider.BouncyCastleProvider代码>
Security.addProvider(新的BouncyCastleProvider())代码>如果服务器支持不包含DH的密码,您可以强制客户端选择该密码并避免DH错误。例如:
String pickedCipher[] ={"TLS_RSA_WITH_AES_256_CBC_SHA"};
sslsocket.setEnabledCipherSuites(pickedCipher);
请记住,从长远来看,指定精确的密码很容易被破坏。您可以在jdk中完全禁用DHE,编辑jre/lib/security/java.security并确保禁用DHE,例如
jdk.tls.disabledAlgorithms=SSLv3,DHE
如果您仍然受到此问题的困扰,并且使用的是Apache httpd v>2.4.7,请尝试以下操作:
从url复制的:
从版本2.4.7开始,mod_ssl将使用DH参数,其中包括长度超过1024位的素数。然而,Java7和更早版本将对DH素数大小的支持限制为最多1024位
如果你的Ja
echo |openssl s_client -connect example.org:443 2>&1 |sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'
package org.example.security;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.Socket;
import java.net.URL;
import java.net.UnknownHostException;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import org.apache.log4j.Logger;
public class SSLExcludeCipherConnectionHelper {
private Logger logger = Logger.getLogger(SSLExcludeCipherConnectionHelper.class);
private String[] exludedCipherSuites = {"_DHE_","_DH_"};
private String trustCert = null;
private TrustManagerFactory tmf;
public void setExludedCipherSuites(String[] exludedCipherSuites) {
this.exludedCipherSuites = exludedCipherSuites;
}
public SSLExcludeCipherConnectionHelper(String trustCert) {
super();
this.trustCert = trustCert;
//Security.addProvider(new BouncyCastleProvider());
try {
this.initTrustManager();
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void initTrustManager() throws Exception {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = new BufferedInputStream(new FileInputStream(trustCert));
Certificate ca = null;
try {
ca = cf.generateCertificate(caInput);
logger.debug("ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
caInput.close();
}
// Create a KeyStore containing our trusted CAs
KeyStore keyStore = KeyStore.getInstance("jks");
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
}
public String get(URL url) throws Exception {
// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
SSLParameters params = context.getSupportedSSLParameters();
List<String> enabledCiphers = new ArrayList<String>();
for (String cipher : params.getCipherSuites()) {
boolean exclude = false;
if (exludedCipherSuites != null) {
for (int i=0; i<exludedCipherSuites.length && !exclude; i++) {
exclude = cipher.indexOf(exludedCipherSuites[i]) >= 0;
}
}
if (!exclude) {
enabledCiphers.add(cipher);
}
}
String[] cArray = new String[enabledCiphers.size()];
enabledCiphers.toArray(cArray);
// Tell the URLConnection to use a SocketFactory from our SSLContext
HttpsURLConnection urlConnection =
(HttpsURLConnection)url.openConnection();
SSLSocketFactory sf = context.getSocketFactory();
sf = new DOSSLSocketFactory(sf, cArray);
urlConnection.setSSLSocketFactory(sf);
BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
String inputLine;
StringBuffer buffer = new StringBuffer();
while ((inputLine = in.readLine()) != null)
buffer.append(inputLine);
in.close();
return buffer.toString();
}
private class DOSSLSocketFactory extends javax.net.ssl.SSLSocketFactory {
private SSLSocketFactory sf = null;
private String[] enabledCiphers = null;
private DOSSLSocketFactory(SSLSocketFactory sf, String[] enabledCiphers) {
super();
this.sf = sf;
this.enabledCiphers = enabledCiphers;
}
private Socket getSocketWithEnabledCiphers(Socket socket) {
if (enabledCiphers != null && socket != null && socket instanceof SSLSocket)
((SSLSocket)socket).setEnabledCipherSuites(enabledCiphers);
return socket;
}
@Override
public Socket createSocket(Socket s, String host, int port,
boolean autoClose) throws IOException {
return getSocketWithEnabledCiphers(sf.createSocket(s, host, port, autoClose));
}
@Override
public String[] getDefaultCipherSuites() {
return sf.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
if (enabledCiphers == null)
return sf.getSupportedCipherSuites();
else
return enabledCiphers;
}
@Override
public Socket createSocket(String host, int port) throws IOException,
UnknownHostException {
return getSocketWithEnabledCiphers(sf.createSocket(host, port));
}
@Override
public Socket createSocket(InetAddress address, int port)
throws IOException {
return getSocketWithEnabledCiphers(sf.createSocket(address, port));
}
@Override
public Socket createSocket(String host, int port, InetAddress localAddress,
int localPort) throws IOException, UnknownHostException {
return getSocketWithEnabledCiphers(sf.createSocket(host, port, localAddress, localPort));
}
@Override
public Socket createSocket(InetAddress address, int port,
InetAddress localaddress, int localport) throws IOException {
return getSocketWithEnabledCiphers(sf.createSocket(address, port, localaddress, localport));
}
}
}
try {
URL url = new URL("https://www.example.org?q=somedata");
SSLExcludeCipherConnectionHelper sslExclHelper = new SSLExcludeCipherConnectionHelper(certFilePath);
logger.debug(
sslExclHelper.get(url)
);
} catch (Exception ex) {
ex.printStackTrace();
}
String pickedCipher[] ={"TLS_RSA_WITH_AES_256_CBC_SHA"};
sslsocket.setEnabledCipherSuites(pickedCipher);
-----BEGIN DH PARAMETERS-----
MIGHAoGBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR
Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL
/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7OZTgf//////////AgEC
-----END DH PARAMETERS-----
javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
Could not generate DH keypair
public class MapService {
static {
Security.addProvider(new BouncyCastleProvider());
}
public GeocodeResult geocode() {
}
}
openssl dhparam 1024
-----BEGIN DH PARAMETERS-----
MIGHfoGBALxpfMrDpImEuPlhopxYX4L2CFqQov+FomjKyHJrzj/EkTP0T3oAkjnS
oCGh6p07kwSLS8WCtYJn1GzItiZ05LoAzPs7T3ST2dWrEYFg/dldt+arifj6oWo+
vctDyDqIjlevUE+vyR9MF6B+Rfm4Zs8VGkxmsgXuz0gp/9lmftY7AgEC
-----END DH PARAMETERS-----
<CFHTTP URL="https://www.onlineumfragen.com" METHOD="get" ></CFHTTP>
<CFDUMP VAR="#CFHTTP#">
java SSLPoke www.onlineumfragen.com 443
javax.net.ssl.SSLException: java.lang.RuntimeException: Could not generate DH keypair
Caused by: java.security.InvalidAlgorithmParameterException: Prime size must be
multiple of 64, and can only range from 512 to 1024 (inclusive)
at com.sun.crypto.provider.DHKeyPairGenerator.initialize(DashoA13*..)
at java.security.KeyPairGenerator$Delegate.initialize(KeyPairGenerator.java:627)
at com.sun.net.ssl.internal.ssl.DHCrypt.<init>(DHCrypt.java:107)
... 10 more
bcprov-ext-jdk15on-156.jar
#
# List of providers and their preference orders (see above):
#
security.provider.1=org.bouncycastle.jce.provider.BouncyCastleProvider
security.provider.2=sun.security.provider.Sun
security.provider.3=sun.security.rsa.SunRsaSign
security.provider.4=com.sun.net.ssl.internal.ssl.Provider
security.provider.5=com.sun.crypto.provider.SunJCE
security.provider.6=sun.security.jgss.SunProvider
security.provider.7=com.sun.security.sasl.Provider
security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI
security.provider.9=sun.security.smartcardio.SunPCSC
security.provider.10=sun.security.mscapi.SunMSCAPI
java SSLPoke www.onlineumfragen.com 443 (or of course your url!)
.../java/jre/lib/security/java.security:
jdk.tls.disabledAlgorithms=SSL_DHE_RSA_WITH_AES_256_CBC_SHA
wget -O /root/jdk-7u79-linux-x64.rpm --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; o raclelicense=accept-securebackup-cookie" "http://download.oracle.com/otn-pub/java/jdk/7u79-b15/jdk-7u79-linux-x64.rpm"
rpm -ivh jdk-7u79-linux-x64.rpm
Preparing... ########################################### [100%]
file /etc/init.d/jexec from install of jdk-2000:1.7.0_79-fcs.x86_64 conflicts with file from package jdk-2000:1.6.0_43-fcs.x86_64
rpm -Uvh jdk-7u79-linux-x64.rpm
Preparing... ########################################### [100%]
1:jdk ########################################### [100%]
Unpacking JAR files...
rt.jar...
jsse.jar...
charsets.jar...
tools.jar...
localedata.jar...
jfxrt.jar...
java -version
java version "1.7.0_79"
Java(TM) SE Runtime Environment (build 1.7.0_79-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.79-b02, mixed mode)
bcprov-jdk14, bcpkix-jdk14, bcmail-jdk14
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcmail-jdk15on</artifactId>
<version>1.59</version>
</dependency>
<dependency>
<groupId>com.lowagie</groupId>
<artifactId>itext</artifactId>
<version>2.1.7</version>
<exclusions>
<exclusion>
<groupId>org.bouncycastle</groupId>
<artifactId>bctsp-jdk14</artifactId>
</exclusion>
<exclusion>
<groupId>bouncycastle</groupId>
<artifactId>bcprov-jdk14</artifactId>
</exclusion>
<exclusion>
<groupId>bouncycastle</groupId>
<artifactId>bcmail-jdk14</artifactId>
</exclusion>
</exclusions>
</dependency>