需求:客户端是JavaWeb的应用程序,会接受页面参数组装成自定义的XML协议格式发送给后端服务程序。C++服务端解析XML并执行命令。传送XML过程中可能会包含一些隐私数据,需要用SSL加密。我负责Java客户端。
准备:
在网上找了若干资料,大多是Java服务器C++客户端的,无奈只有用英文搜索些国外站点的资料。
1.下载openssl,做测试(Linux版本的安装)。
安装openssl
下载:openssl-0.9.7m.tar.gz
解压:tar xzvf openssl-0.9.7m.tar.gz
cd openssl-0.9.7m/
默认配置:./config
重新建立依赖关系:make depend
测试:make test
安装:make install
安装完成后就可以用openssl自带的s_server和s_client做测试了,很方便。
2.下载bcprov-jdk15-143.jar,早知道有这个东西就省事了。(BouncyCastle.org出品的Java开源SSL工具包)
步骤:
一、跑通Java客户端与C++ openssl双向通讯。
1.建立证书(注:需要输入信息的时候需要与CA生成时统一,但不能完全一致,姓名可以不一)
新建目录:mkdir openssl_demo2
拷贝 openssl-0.9.7m/apps/ 下的CA.sh、openssl.cnf 到 openssl_demo2 下
cd openssl_demo2
2.新建CA公私钥
./CA.sh -newca
该命令的工作:
创建目录:demoCA/ 、 demoCA/private/ 、 demoCA/certs/ 、demoCA/private/ 、demoCA/newcerts/
文件:demoCA/serial(写入“01”) 、demoCA/index.txt
创建CA公私钥:demoCA/cacert.pem、demoCA/private/cakey.pem
3.新建服务器端私钥+公钥签名请求
openssl req -newkey rsa:1024 -out serverreq.pem -keyout sslserverkey.pem
4.用CA私钥为服务端请求签名生成服务端证书
openssl ca -in serverreq.pem -out sslservercert.pem -config ./openssl.cnf
下面的步骤注意版本,java版本过低可能keytool做证书有问题。
OpenSSL 0.9.6m 17 Mar 2004
java -version -- Java(TM) SE Runtime Environment (build 1.6.0_03-b05)
5.生成客户端私钥并存入sslclient.keystore
keytool -genkey -alias sslclient -validity 365 -keyalg RSA -keysize 1024 -keystore sslclient.keystore -keypass 123456 -storepass 123456
6.从sslclient.keystore中提取客户端签名请求
keytool -certreq -alias sslclient -sigalg SHA1withRSA -file sslclient.csr -keypass 123456 -storepass 123456 -keystore sslclient.keystore
7.用CA私钥为服务端请求签名生成客户端证书
openssl ca -in sslclient.csr -out sslclient.crt -cert demoCA/cacert.pem -keyfile demoCA/private/cakey.pem -notext -config openssl.cnf
8.转换客户端证书格式
openssl x509 -in sslclient.crt -out sslclient.der -outform DER
9.sslclient.keystore导入根证书
keytool -import -v -trustcacerts -alias ca_root -file demoCA/cacert.pem -storepass 123456 -keystore sslclient.keystore
10.sslclient.keystore导入客户端证书
keytool -import -v -alias sslclient -file sslclient.der -keypass 123456 -storepass 123456 -keystore sslclient.keystore
11.运行程序
运行openssl自带测试服务端:openssl s_server -cert sslservercert.pem -key sslserverkey.pem -CAfile demoCA/cacert.pem -state -Verify 1 -ssl3
运行Java客户端(略)。
(上面的步骤参考了这篇文章:http://www.blogjava.net/alwayscy/archive/2009/02/03/85161.html
由于下面的问题,不能完全采用上面的方案。)
二、问题:由于证书的生产和颁发是由另外一个VC程序统一管理的,所以不可能为了我的Java程序而做一个额外的功能。证书颁发程序是将CA根证书、客户端证书和客户端私钥下发到系统某个目录下然后我去取用的。麻烦在程序生成的证书都是PEM格式的,不能直接导入Java的JKS库,需要做个转换。
1.在网上的几篇文章分别搜到些 PEM证书+私钥合并为pkcs12格式密钥库、pkcs12格式密钥库导入JKS密钥库、CA证书导入JKS密钥库的文章,于是整理了一下做了个小例子。
package change_format;
import java.security.KeyStore;
import java.security.Key;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.io.*;
import java.util.*;
public class ConvertPEMToJKS {
// certificate store format
public static final String PKCS12 = "PKCS12";
public static final String JKS = "JKS";
// PKCS12 keystore properties
public static final String INPUT_KEYSTORE_FILE = "src/change_format/keystore.pkcs12";
public static final String KEYSTORE_PASSWORD = "123456";
// JKS output file
public static final String OUTPUT_KEYSTORE_FILE = "src/change_format/keystore.jks";
public static final String CACERT_FILE = "src/change_format/ca2.crt";
public static final String PEMPRIKEY_FILE = "src/change_format/clientssl.pri";
public static final String PEMPUBKEY_FILE = "src/change_format/clientssl.crt";
public static void pktojks() {
try {
KeyStore inputKeyStore = KeyStore.getInstance("PKCS12");
FileInputStream fis = new FileInputStream(INPUT_KEYSTORE_FILE);
// If the keystore password is empty(""), then we have to set
// to null, otherwise it won't work!!!
char[] nPassword = null;
if ((KEYSTORE_PASSWORD == null)
|| KEYSTORE_PASSWORD.trim().equals("")) {
nPassword = null;
} else {
nPassword = KEYSTORE_PASSWORD.toCharArray();
}
inputKeyStore.load(fis, nPassword);
fis.close();
// System.out.println("keystore type=" + inputKeyStore.getType());
// ----------------------------------------------------------------------
// get a JKS keystore and initialize it.
KeyStore outputKeyStore = KeyStore.getInstance("JKS");
outputKeyStore.load(null, "123456".toCharArray());
// Now we loop all the aliases, we need the alias to get keys.
// It seems that this value is the "Friendly name" field in the
// detals tab <-- Certificate window <-- view <-- Certificate
// Button <-- Content tab <-- Internet Options <-- Tools menu
// In MS IE 6.
Enumeration enume = inputKeyStore.aliases();
while (enume.hasMoreElements()) // we are readin just one
// certificate.
{
String keyAlias = (String) enume.nextElement();
// System.out.println("alias=[" + keyAlias + "]");
if (inputKeyStore.isKeyEntry(keyAlias)) {
Key key = inputKeyStore.getKey(keyAlias, nPassword);
Certificate[] certChain = inputKeyStore
.getCertificateChain(keyAlias);
outputKeyStore.setKeyEntry(keyAlias, key, "123456"
.toCharArray(), certChain);
}
}
FileOutputStream out = new FileOutputStream(OUTPUT_KEYSTORE_FILE);
outputKeyStore.store(out, nPassword);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void jksaddcacert() {
try {
FileInputStream cacertfile = new FileInputStream(CACERT_FILE);
FileInputStream oldjks = new FileInputStream(OUTPUT_KEYSTORE_FILE);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) cf
.generateCertificate(cacertfile);
cacertfile.close();
KeyStore.TrustedCertificateEntry trustedEntry = new KeyStore.TrustedCertificateEntry(
cert);
KeyStore outputKeyStore = KeyStore.getInstance("JKS");
outputKeyStore.load(oldjks, "123456".toCharArray());
oldjks.close();
outputKeyStore.setEntry("ca_root", trustedEntry, null);
FileOutputStream out = new FileOutputStream(OUTPUT_KEYSTORE_FILE);
outputKeyStore.store(out, KEYSTORE_PASSWORD.toCharArray());
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private static final String localDir = "src\\change_format\\";
public static void pemaddpk() {
try {
Runtime rt = Runtime.getRuntime();
Process ps = null;
String exeStr = "openssl pkcs12 -export -in " + localDir
+ "clientssl.crt -inkey " + localDir
+ "clientssl.pri -out " + localDir
+ "keystore.pkcs12 -passout pass:123456";
System.out.println(exeStr);
ps = rt.exec(exeStr);
ps.waitFor();
int i = ps.exitValue();
if (i == 0) {
System.out.println("Convert PKCS12 Sucess!");
} else {
System.out.println("Convert PKCS12 Error!");
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
ConvertPEMToJKS.pemaddpk();
ConvertPEMToJKS.pktojks();
ConvertPEMToJKS.jksaddcacert();
}
}
2. 如上例子中遇到一个问题,就是我程序所在的部署机将来需要安装openssl才能执行pemaddpk()方法中的openssl脚本;或者需要部署人员额外对证书颁发程序颁发的证书做个转化。这两种方法都是比较繁琐的,终于找到BouncyCastle的开源SSL工具包可以直接读入PEM格式并导入JKS,真是Java做OpenSSL的福音啊。
将bcprov-jdk15-143.jar导入工作路径,我抽出了一小段代码,以后要用到SSL的话可以方便的调用。
SSLContextBuild.java :
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Properties;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import org.bouncycastle.openssl.PEMReader;
import org.bouncycastle.openssl.PasswordFinder;
public class SSLContextBuild {
public static SSLContext getSSLContext() {
// 获取证书路径
Properties prop = new Properties();
try {
//这里的路径是放在javaweb应用程序的web-inf/class下的
prop.load(SSLContextBuild.class.getClassLoader()
.getResourceAsStream("SSLCertPath.properties"));
} catch (IOException e) {
e.printStackTrace();
}
SSLContext sslContext = null;
try {
// 设定Security的Provider提供程序
Security
.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
// 读入客户端证书
PEMReader pr = new PEMReader(new FileReader(prop.get("client_cert")
.toString()));
X509Certificate cert = (X509Certificate) pr.readObject();
pr.close();
// 读入客户端私钥
PEMReader kr = new PEMReader(new FileReader(prop.get(
"client_privatekey").toString()), new PasswordFinder() {
public char[] getPassword() {
return "".toCharArray();
}
});
KeyPair key = (KeyPair) kr.readObject();
kr.close();
// 建立空JKS
KeyStore ksKeys = KeyStore.getInstance("JKS");
ksKeys.load(null, "123456".toCharArray());
// 导入客户端私钥和证书
ksKeys.setKeyEntry("clientkey", key.getPrivate(), "123456"
.toCharArray(), new Certificate[] { cert });
ksKeys.setCertificateEntry("clientcert", cert);
// 导入根证书作为trustedEntry,待改进代码,此处没用bouncycastle的API,用了应该能简化点
FileInputStream cacertfile = new FileInputStream(prop.get("cacert")
.toString());
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cacert = (X509Certificate) cf
.generateCertificate(cacertfile);
cacertfile.close();
KeyStore.TrustedCertificateEntry trustedEntry = new KeyStore.TrustedCertificateEntry(
cacert);
ksKeys.setEntry("ca_root", trustedEntry, null);
// 构建KeyManager、TrustManager
KeyManagerFactory kmf = KeyManagerFactory
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ksKeys, "123456".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ksKeys);
// 构建SSLContext
sslContext = SSLContext.getInstance("SSL");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
} catch (Exception e) {
e.printStackTrace();
}
return sslContext;
}
}
SSLCertPath.properties :
cacert=E:\\Ben\\ca2.crt
client_cert=E:\\Ben\\clientcert.crt
client_privatekey=E:\\Ben\\clientkey.pri
调用的时候:
try {
sslSocket = (SSLSocket) SSLContextBuild.getSSLContext()
.getSocketFactory()
.createSocket(HOST, PORT); //HOST like "192.168.1.X";PORT like 8888
sslSocket.setEnabledProtocols(new String[] { "SSLv3" }); //注意此处要与你服务器端的程序设定一致。现在比较常用的协议是SSLv3/TLSv1。
} catch (Exception e) {
e.printStackTrace();
}
整了一个多星期,从完全没有SSL的概念,到将其融入代码,真是要感谢网络啊,哈哈。很有感觉哦!
准备:
在网上找了若干资料,大多是Java服务器C++客户端的,无奈只有用英文搜索些国外站点的资料。
1.下载openssl,做测试(Linux版本的安装)。
安装openssl
下载:openssl-0.9.7m.tar.gz
解压:tar xzvf openssl-0.9.7m.tar.gz
cd openssl-0.9.7m/
默认配置:./config
重新建立依赖关系:make depend
测试:make test
安装:make install
安装完成后就可以用openssl自带的s_server和s_client做测试了,很方便。
2.下载bcprov-jdk15-143.jar,早知道有这个东西就省事了。(BouncyCastle.org出品的Java开源SSL工具包)
步骤:
一、跑通Java客户端与C++ openssl双向通讯。
1.建立证书(注:需要输入信息的时候需要与CA生成时统一,但不能完全一致,姓名可以不一)
新建目录:mkdir openssl_demo2
拷贝 openssl-0.9.7m/apps/ 下的CA.sh、openssl.cnf 到 openssl_demo2 下
cd openssl_demo2
2.新建CA公私钥
./CA.sh -newca
该命令的工作:
创建目录:demoCA/ 、 demoCA/private/ 、 demoCA/certs/ 、demoCA/private/ 、demoCA/newcerts/
文件:demoCA/serial(写入“01”) 、demoCA/index.txt
创建CA公私钥:demoCA/cacert.pem、demoCA/private/cakey.pem
3.新建服务器端私钥+公钥签名请求
openssl req -newkey rsa:1024 -out serverreq.pem -keyout sslserverkey.pem
4.用CA私钥为服务端请求签名生成服务端证书
openssl ca -in serverreq.pem -out sslservercert.pem -config ./openssl.cnf
下面的步骤注意版本,java版本过低可能keytool做证书有问题。
OpenSSL 0.9.6m 17 Mar 2004
java -version -- Java(TM) SE Runtime Environment (build 1.6.0_03-b05)
5.生成客户端私钥并存入sslclient.keystore
keytool -genkey -alias sslclient -validity 365 -keyalg RSA -keysize 1024 -keystore sslclient.keystore -keypass 123456 -storepass 123456
6.从sslclient.keystore中提取客户端签名请求
keytool -certreq -alias sslclient -sigalg SHA1withRSA -file sslclient.csr -keypass 123456 -storepass 123456 -keystore sslclient.keystore
7.用CA私钥为服务端请求签名生成客户端证书
openssl ca -in sslclient.csr -out sslclient.crt -cert demoCA/cacert.pem -keyfile demoCA/private/cakey.pem -notext -config openssl.cnf
8.转换客户端证书格式
openssl x509 -in sslclient.crt -out sslclient.der -outform DER
9.sslclient.keystore导入根证书
keytool -import -v -trustcacerts -alias ca_root -file demoCA/cacert.pem -storepass 123456 -keystore sslclient.keystore
10.sslclient.keystore导入客户端证书
keytool -import -v -alias sslclient -file sslclient.der -keypass 123456 -storepass 123456 -keystore sslclient.keystore
11.运行程序
运行openssl自带测试服务端:openssl s_server -cert sslservercert.pem -key sslserverkey.pem -CAfile demoCA/cacert.pem -state -Verify 1 -ssl3
运行Java客户端(略)。
(上面的步骤参考了这篇文章:http://www.blogjava.net/alwayscy/archive/2009/02/03/85161.html
由于下面的问题,不能完全采用上面的方案。)
二、问题:由于证书的生产和颁发是由另外一个VC程序统一管理的,所以不可能为了我的Java程序而做一个额外的功能。证书颁发程序是将CA根证书、客户端证书和客户端私钥下发到系统某个目录下然后我去取用的。麻烦在程序生成的证书都是PEM格式的,不能直接导入Java的JKS库,需要做个转换。
1.在网上的几篇文章分别搜到些 PEM证书+私钥合并为pkcs12格式密钥库、pkcs12格式密钥库导入JKS密钥库、CA证书导入JKS密钥库的文章,于是整理了一下做了个小例子。
package change_format;
import java.security.KeyStore;
import java.security.Key;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.io.*;
import java.util.*;
public class ConvertPEMToJKS {
// certificate store format
public static final String PKCS12 = "PKCS12";
public static final String JKS = "JKS";
// PKCS12 keystore properties
public static final String INPUT_KEYSTORE_FILE = "src/change_format/keystore.pkcs12";
public static final String KEYSTORE_PASSWORD = "123456";
// JKS output file
public static final String OUTPUT_KEYSTORE_FILE = "src/change_format/keystore.jks";
public static final String CACERT_FILE = "src/change_format/ca2.crt";
public static final String PEMPRIKEY_FILE = "src/change_format/clientssl.pri";
public static final String PEMPUBKEY_FILE = "src/change_format/clientssl.crt";
public static void pktojks() {
try {
KeyStore inputKeyStore = KeyStore.getInstance("PKCS12");
FileInputStream fis = new FileInputStream(INPUT_KEYSTORE_FILE);
// If the keystore password is empty(""), then we have to set
// to null, otherwise it won't work!!!
char[] nPassword = null;
if ((KEYSTORE_PASSWORD == null)
|| KEYSTORE_PASSWORD.trim().equals("")) {
nPassword = null;
} else {
nPassword = KEYSTORE_PASSWORD.toCharArray();
}
inputKeyStore.load(fis, nPassword);
fis.close();
// System.out.println("keystore type=" + inputKeyStore.getType());
// ----------------------------------------------------------------------
// get a JKS keystore and initialize it.
KeyStore outputKeyStore = KeyStore.getInstance("JKS");
outputKeyStore.load(null, "123456".toCharArray());
// Now we loop all the aliases, we need the alias to get keys.
// It seems that this value is the "Friendly name" field in the
// detals tab <-- Certificate window <-- view <-- Certificate
// Button <-- Content tab <-- Internet Options <-- Tools menu
// In MS IE 6.
Enumeration enume = inputKeyStore.aliases();
while (enume.hasMoreElements()) // we are readin just one
// certificate.
{
String keyAlias = (String) enume.nextElement();
// System.out.println("alias=[" + keyAlias + "]");
if (inputKeyStore.isKeyEntry(keyAlias)) {
Key key = inputKeyStore.getKey(keyAlias, nPassword);
Certificate[] certChain = inputKeyStore
.getCertificateChain(keyAlias);
outputKeyStore.setKeyEntry(keyAlias, key, "123456"
.toCharArray(), certChain);
}
}
FileOutputStream out = new FileOutputStream(OUTPUT_KEYSTORE_FILE);
outputKeyStore.store(out, nPassword);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void jksaddcacert() {
try {
FileInputStream cacertfile = new FileInputStream(CACERT_FILE);
FileInputStream oldjks = new FileInputStream(OUTPUT_KEYSTORE_FILE);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) cf
.generateCertificate(cacertfile);
cacertfile.close();
KeyStore.TrustedCertificateEntry trustedEntry = new KeyStore.TrustedCertificateEntry(
cert);
KeyStore outputKeyStore = KeyStore.getInstance("JKS");
outputKeyStore.load(oldjks, "123456".toCharArray());
oldjks.close();
outputKeyStore.setEntry("ca_root", trustedEntry, null);
FileOutputStream out = new FileOutputStream(OUTPUT_KEYSTORE_FILE);
outputKeyStore.store(out, KEYSTORE_PASSWORD.toCharArray());
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private static final String localDir = "src\\change_format\\";
public static void pemaddpk() {
try {
Runtime rt = Runtime.getRuntime();
Process ps = null;
String exeStr = "openssl pkcs12 -export -in " + localDir
+ "clientssl.crt -inkey " + localDir
+ "clientssl.pri -out " + localDir
+ "keystore.pkcs12 -passout pass:123456";
System.out.println(exeStr);
ps = rt.exec(exeStr);
ps.waitFor();
int i = ps.exitValue();
if (i == 0) {
System.out.println("Convert PKCS12 Sucess!");
} else {
System.out.println("Convert PKCS12 Error!");
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
ConvertPEMToJKS.pemaddpk();
ConvertPEMToJKS.pktojks();
ConvertPEMToJKS.jksaddcacert();
}
}
2. 如上例子中遇到一个问题,就是我程序所在的部署机将来需要安装openssl才能执行pemaddpk()方法中的openssl脚本;或者需要部署人员额外对证书颁发程序颁发的证书做个转化。这两种方法都是比较繁琐的,终于找到BouncyCastle的开源SSL工具包可以直接读入PEM格式并导入JKS,真是Java做OpenSSL的福音啊。
将bcprov-jdk15-143.jar导入工作路径,我抽出了一小段代码,以后要用到SSL的话可以方便的调用。
SSLContextBuild.java :
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Properties;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import org.bouncycastle.openssl.PEMReader;
import org.bouncycastle.openssl.PasswordFinder;
public class SSLContextBuild {
public static SSLContext getSSLContext() {
// 获取证书路径
Properties prop = new Properties();
try {
//这里的路径是放在javaweb应用程序的web-inf/class下的
prop.load(SSLContextBuild.class.getClassLoader()
.getResourceAsStream("SSLCertPath.properties"));
} catch (IOException e) {
e.printStackTrace();
}
SSLContext sslContext = null;
try {
// 设定Security的Provider提供程序
Security
.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
// 读入客户端证书
PEMReader pr = new PEMReader(new FileReader(prop.get("client_cert")
.toString()));
X509Certificate cert = (X509Certificate) pr.readObject();
pr.close();
// 读入客户端私钥
PEMReader kr = new PEMReader(new FileReader(prop.get(
"client_privatekey").toString()), new PasswordFinder() {
public char[] getPassword() {
return "".toCharArray();
}
});
KeyPair key = (KeyPair) kr.readObject();
kr.close();
// 建立空JKS
KeyStore ksKeys = KeyStore.getInstance("JKS");
ksKeys.load(null, "123456".toCharArray());
// 导入客户端私钥和证书
ksKeys.setKeyEntry("clientkey", key.getPrivate(), "123456"
.toCharArray(), new Certificate[] { cert });
ksKeys.setCertificateEntry("clientcert", cert);
// 导入根证书作为trustedEntry,待改进代码,此处没用bouncycastle的API,用了应该能简化点
FileInputStream cacertfile = new FileInputStream(prop.get("cacert")
.toString());
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cacert = (X509Certificate) cf
.generateCertificate(cacertfile);
cacertfile.close();
KeyStore.TrustedCertificateEntry trustedEntry = new KeyStore.TrustedCertificateEntry(
cacert);
ksKeys.setEntry("ca_root", trustedEntry, null);
// 构建KeyManager、TrustManager
KeyManagerFactory kmf = KeyManagerFactory
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ksKeys, "123456".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ksKeys);
// 构建SSLContext
sslContext = SSLContext.getInstance("SSL");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
} catch (Exception e) {
e.printStackTrace();
}
return sslContext;
}
}
SSLCertPath.properties :
cacert=E:\\Ben\\ca2.crt
client_cert=E:\\Ben\\clientcert.crt
client_privatekey=E:\\Ben\\clientkey.pri
调用的时候:
try {
sslSocket = (SSLSocket) SSLContextBuild.getSSLContext()
.getSocketFactory()
.createSocket(HOST, PORT); //HOST like "192.168.1.X";PORT like 8888
sslSocket.setEnabledProtocols(new String[] { "SSLv3" }); //注意此处要与你服务器端的程序设定一致。现在比较常用的协议是SSLv3/TLSv1。
} catch (Exception e) {
e.printStackTrace();
}
整了一个多星期,从完全没有SSL的概念,到将其融入代码,真是要感谢网络啊,哈哈。很有感觉哦!
评论
1 楼
82934162
2010-11-18
9.sslclient.keystore导入根证书
keytool -import -v -trustcacerts -alias ca_root -file demoCA/cacert.pem -storepass 123456 -keystore sslclient.keystore
这里打错了吧?应该是把根证书导入到自己的truststore里吧?不应该导入到自己存放privatekey的store里。
还有:
10.sslclient.keystore导入客户端证书
keytool -import -v -alias sslclient -file sslclient.der -keypass 123456 -storepass 123456 -keystore sslclient.keystore
这里是不是也写错了?是不是客户端证书也要导入到自己的truststore里?如果是的话,为什么呢?
可能是我小白。。。希望LZ能给解惑。。3Q
keytool -import -v -trustcacerts -alias ca_root -file demoCA/cacert.pem -storepass 123456 -keystore sslclient.keystore
这里打错了吧?应该是把根证书导入到自己的truststore里吧?不应该导入到自己存放privatekey的store里。
还有:
10.sslclient.keystore导入客户端证书
keytool -import -v -alias sslclient -file sslclient.der -keypass 123456 -storepass 123456 -keystore sslclient.keystore
这里是不是也写错了?是不是客户端证书也要导入到自己的truststore里?如果是的话,为什么呢?
可能是我小白。。。希望LZ能给解惑。。3Q
相关推荐
在Java客户端和VC(Visual C++)服务器之间实现SSL双向认证涉及以下几个关键步骤: 1. **证书准备**: - **服务器证书**:服务器需要一个由受信任的证书颁发机构(CA)签发的数字证书,包含服务器的公钥和身份信息...
对于桌面客户端,可能需要使用C++、Java或Qt等跨平台框架进行开发,而移动端则通常选择原生的Android(Java或Kotlin)或iOS(Swift或Objective-C)。现代客户端通常会采用MVVM(Model-View-ViewModel)或MVC(Model-...
这个服务端代码可能是用某种编程语言(如Java、Python、C++或Node.js等)编写的,它的主要功能是处理来自多个客户端的连接请求,确保消息的可靠传输,并可能包含了用户管理、会话管理、消息存储以及推送通知等相关...
Java的`java.net`包提供了Socket和ServerSocket类,用于建立客户端和服务端的连接,实现数据的双向传输。 3. **多线程** 在Java版QQ中,为了保证用户体验,通常会采用多线程技术来处理并发任务。例如,一个线程...
1. **Socket编程**:这是Java网络编程的基础之一,用于创建客户端与服务器之间的双向通信通道。Java中的`Socket`类和`ServerSocket`类分别用于客户端和服务端的通信。 2. **多线程处理**:在网络编程中,为了处理...
1. **服务器与客户端架构**:GRPC 采用双工流式通信,允许服务端和客户端同时发送请求和响应,这种模式提供了高效的交互。源代码中,`server` 和 `client` 的实现分别展示了如何创建和管理这些连接。 2. **Protobuf...
1. **高并发处理**:QQ服务端需要处理海量并发请求,因此会运用负载均衡、分布式系统架构,以及高性能的服务器编程语言如Java、Go或C++。 2. **消息路由与存储**:服务端需要快速、准确地将消息路由到正确的目标,...
Remote Call Function(RCF)库是一个C++编写的库,其设计目的是为了简化分布式系统中的远程方法调用(Remote Method Invocation),类似于Java中的RMI(Remote Method Invocation)机制。RCF库是CORBA(Common ...
PB的优势在于其高效、跨平台和语言无关性,支持C++, Java, Python等多种编程语言。通过定义.proto文件,我们可以声明数据结构,然后使用PB编译器生成相应的类或接口,方便在代码中操作和序列化/反序列化数据。 ...
`MyImServer`部分涉及服务器编程,可能使用Java的ServerSocket类来监听客户端的连接请求,并通过Socket对象处理每个连接。服务器需要维持一个连接池,处理多个客户端同时在线的情况。 7. **安全性**: 即时通讯的...
protobuf会将这些定义编译成不同编程语言的代码,使得服务端和客户端可以轻松地交换消息。 2. **Stub**:在gRPC中,客户端和服务器端都包含对应的Stub(存根)。客户端Stub负责调用远程服务,就像调用本地函数一样...
Flex SDK提供了一个名为`flash.net.Socket`的类,它允许我们创建客户端Socket连接,以便与服务器进行双向通信。通过这个API,我们可以读取和写入字节数据,实现低级别的网络通信。 2. 连接服务器 创建Socket对象后...
20、EJB与JAVA BEAN的区别? Java Bean 是可复用的组件,对Java Bean并没有严格的规范,理论上讲,任何一个Java类都可以是一个Bean。但通常情况下,由于Java Bean是被容器所创建(如Tomcat)的,所以Java Bean应具有...
在Android中,我们可以使用Java的`java.net.Socket`类或原生C++的`socket`函数进行Socket编程。 1. **Android应用层的Socket通信**: 在Android应用层,我们可以创建一个普通的Java Socket客户端来连接运行在...
1. **源代码文件**:通常包含用各种编程语言(如Java、Python、C++或Node.js)编写的网络服务端和客户端程序,这些代码会展示如何建立网络连接、发送和接收数据。 2. **配置文件**:可能包括服务器的配置信息,如...
- **丰富的客户端和服务端认证机制**:支持TLS/SSL、OAuth等认证方式。 - **强大的调试和监控工具**:提供了丰富的调试和监控工具,方便问题定位和性能优化。 #### 云原生环境下的微服务开发 - **云原生的概念**...
在Java、C++等编程语言中,Socket编程可以创建客户端和服务器端的连接,实现数据的双向交换。在即时通信软件中,通常会有一个服务端作为消息的中转站,多个客户端则通过Socket与服务端建立连接,发送和接收消息。 ...
套接字编程是网络编程的核心,本教程会详细介绍如何在Python、Java或C++等语言中创建和使用套接字,实现客户端与服务器之间的通信。这包括TCP套接字和UDP套接字的创建、连接、监听、发送和接收数据的步骤,以及异常...
23、EJB与JAVA BEAN的区别? Java Bean 是可复用的组件,对Java Bean并没有严格的规范,理论上讲,任何一个Java类都可以是一个Bean。但通常情况下,由于Java Bean是被容器所创建(如Tomcat)的,所以Java Bean应...
Gloox是一个C++编写的开源XMPP客户端库,它提供了完整的XMPP协议栈,支持XMPP核心、多用户聊天室、组件交互等功能。通过gloox,开发者可以方便地构建XMPP客户端和服务端应用程序。 在信息收集和存储方面,项目可能...