我正在尝试通过 HTTPS 连接使用 itext tsaclient 进行时间戳记,当 tsaclient 尝试与服务器建立连接时,我在签名时遇到了连接问题。通过whireshark分析我收到的流量
"Received fatal alert: bad_certificate"
重点是我可以建立连接,但不能从 tsaclient,
//Preparing keystore with Private Key
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
KeyStore ks = KeyStore.getInstance("pkcs12", provider.getName());
ks.load(new FileInputStream(Constantes.CERT), Constantes.PASS_CERT.toCharArray());
String alias = (String)ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, Constantes.PASS_CERT.toCharArray());
Certificate[] chain = ks.getCertificateChain(alias);
//Adding Server public key to the keystore ks
FileInputStream is = new FileInputStream(new File(Constantes.SERVER_CERT_CER));
CertificateFactory cf = CertificateFactory.getInstance("X.509");
java.security.cert.X509Certificate cert = (X509Certificate) cf.generateCertificate(is);
ks.setCertificateEntry("alias", cert);
//Preparing SSL Context
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, "pass".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(kmf.getKeyManagers(),tmf.getTrustManagers(), new SecureRandom());
SSLSocketFactory sf = ctx.getSocketFactory();
URL url = new URL("https://...");
HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
conn.setSSLSocketFactory(sf);
conn.setConnectTimeout(0);
conn.connect();
//Until here the connection is OK, "Certificate Verify" say whireshark
//Preparing TSA Client and Sign
ExternalDigest digest = new BouncyCastleDigest();
TSAClient tsaClient = new TSAClientBouncyCastle("https://...");
ExternalSignature es = new PrivateKeySignature(pk,"SHA-1","BC");
MakeSignature.signDetached(appearance, digest, es, chain, null, null, tsaClient, 0, CryptoStandard.CMS);
在MakeSignature连接不上服务器的时候。
最佳答案
我没有准备好来自 TSAClient 的连接,现在我已经正确地实现了客户端。
//Preparing keystore with my Private Key and Server Certificate
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
ks = KeyStore.getInstance("pkcs12", provider.getName()); //public static KeyStore ks;
ks.load(new FileInputStream(Constantes.CERT), Constantes.PASS_CERT.toCharArray());
String alias = (String)ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, Constantes.PASS_CERT.toCharArray());
Certificate[] chain = ks.getCertificateChain(alias);
FileInputStream is = new FileInputStream(new File(Constantes.SERVER_CERT_CER));
CertificateFactory cf = CertificateFactory.getInstance("X.509");
java.security.cert.X509Certificate cert = (X509Certificate) cf.generateCertificate(is);
ks.setCertificateEntry("alias_server_cert", cert);
//Making TSA and Sign
ExternalDigest digest = new BouncyCastleDigest();
TSAClient tsaClient = new Sellado("https://url");
//Digital signature
ExternalSignature es = new PrivateKeySignature(pk,"SHA-1","BC");
MakeSignature.signDetached(appearance,digest,es,chain,null,null,tsaClient,0,CryptoStandard.CMS);
并且 TSAClient“Sellado”基于 TSAClientBouncycaSTLe,使用 SSL 上下文更改下一个类。
public class Sellado implements TSAClient{
//Code
protected byte[] getTSAResponse(byte[] requestBytes)
throws IOException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyStoreException, KeyManagementException
{
//Preparing SSL Context
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(EmpadronamientoI.ks, "pass".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(EmpadronamientoI.ks);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(kmf.getKeyManagers(),tmf.getTrustManagers(), new SecureRandom());
SSLSocketFactory sf = ctx.getSocketFactory();
URL url = new URL(this.tsaURL);
HttpsURLConnection tsaconn = (HttpsURLConnection)url.openConnection();
tsaconn.setSSLSocketFactory(sf);
tsaconn.setConnectTimeout(0);
tsaconn.setDoInput(true);
tsaconn.setDoOutput(true);
tsaconn.setUseCaches(false);
tsaconn.setRequestProperty("Content-Type", "application/timestamp-query");
tsaconn.setRequestProperty("Content-Transfer-Encoding", "binary");
try{
tsaconn.connect();
}
catch (IOException ioe)
{
throw new IOException(MessageLocalization.getComposedMessage("failed.to.get.tsa.response.from.1", new Object[] { this.tsaURL }));
}
OutputStream out = tsaconn.getOutputStream();
out.write(requestBytes);
out.close();
InputStream inp = tsaconn.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte['?'];
int bytesRead = 0;
while ((bytesRead = inp.read(buffer, 0, buffer.length)) >= 0) {
baos.write(buffer, 0, bytesRead);
}
byte[] respBytes = baos.toByteArray();
String encoding = tsaconn.getContentEncoding();
if ((encoding != null) && (encoding.equalsIgnoreCase("base64"))) {
respBytes = Base64.decode(new String(respBytes));
}
return respBytes;
}
//Code
}
关于ssl - 如何从 itext bouncycaSTLe tsaclient 建立 ssl 连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26523992/