temz 2023-03-10 22:26 采纳率: 100%
浏览 55
已结题

java和android作ssl通信如何使用CA证书

Java 和 android 作SSLsocket 时如何使用CA证书以保证安全呢?
找权威机构买ca证书,能买到什么文件,直接就是CA证书吗?是把CA证书放到keystore的load的地址就可以了吗
也就是在下面的代码把CA的路径写到tpath吗?Android端需要怎么设置呢?有没有牛人能详细给说一说啊

 private static String kpath = "e:\\keytool\\sslsocket.keystore";  
    private static String tpath = "e:\\keytool\\sslsocketserver.keystore";  
    private static char[] password = "aaaaaaa".toCharArray();  
    public static void main(String[] args) {  
        boolean flag = true;  
        SSLContext context = null;  
        try {  
            KeyStore ks = KeyStore.getInstance("JKS");  
            ks.load(new FileInputStream(kpath), password);  
            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");  
            kmf.init(ks, password);  
            KeyManager[] km = kmf.getKeyManagers();  
            KeyStore ts = KeyStore.getInstance("JKS");  
            ts.load(new FileInputStream(tpath), password);  
            TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");  
            tmf.init(ts);  
            TrustManager[] tm = tmf.getTrustManagers();  
            context = SSLContext.getInstance("SSL");  
            context.init(km, tm, null);  
        } catch (..... e) {  
            e.printStackTrace();   //捕获异常  
        }  
        SSLServerSocketFactory ssf = (SSLServerSocketFactory) context.getServerSocketFactory();  

  • 写回答

6条回答 默认 最新

  • CodeBytes 2023-03-10 22:40
    关注

    该回答引用ChatGPT

    如有疑问,可以回复我!
    在Java中使用SSLSocket时,使用CA证书可以保证通信的安全性。为了使用CA证书,您需要遵循以下步骤:

    1、购买CA证书:
    您可以从一些权威的证书颁发机构(CA)购买CA证书。购买后,您将收到一个包含CA证书的文件,通常是.pem或.crt文件格式。

    2、将CA证书导入keystore:
    将CA证书导入您的keystore中。您可以使用keytool工具或代码来执行此操作。以下是使用keytool导入CA证书的示例命令:

    keytool -import -alias myca -file myca.crt -keystore mykeystore.jks
    
    

    其中,myca是CA证书的别名,myca.crt是CA证书文件,mykeystore.jks是您的keystore文件。

    3、将keystore用作服务器证书:
    在您的代码中,将keystore文件加载为服务器证书。以下是使用Java代码将keystore加载为服务器证书的示例代码:

    
    String kpath = "path/to/keystore.jks";  
    char[] password = "keystore_password".toCharArray();  
    KeyStore ks = KeyStore.getInstance("JKS");  
    ks.load(new FileInputStream(kpath), password);  
    KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");  
    kmf.init(ks, password);  
    KeyManager[] km = kmf.getKeyManagers();  
    
    

    其中,kpath是keystore文件的路径,password是keystore文件的密码。

    4、将keystore用作客户端信任的证书:
    在您的代码中,将keystore文件加载为客户端信任的证书。以下是使用Java代码将keystore加载为客户端信任的证书的示例代码:

    
    String tpath = "path/to/truststore.jks";  
    char[] password = "truststore_password".toCharArray();  
    KeyStore ts = KeyStore.getInstance("JKS");  
    ts.load(new FileInputStream(tpath), password);  
    TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");  
    tmf.init(ts);  
    TrustManager[] tm = tmf.getTrustManagers();  
    
    

    其中,tpath是truststore文件的路径,password是truststore文件的密码。

    5、使用SSLContext初始化:
    使用SSLContext初始化,并将KeyManager和TrustManager传递给它。以下是使用Java代码初始化SSLContext的示例代码:

    
    SSLContext context = SSLContext.getInstance("SSL");  
    context.init(km, tm, null);  
    
    

    其中,km是KeyManager,tm是TrustManager,null表示使用默认的随机数生成器。

    6、使用SSLServerSocketFactory创建SSLServerSocket:
    最后,使用SSLServerSocketFactory创建SSLServerSocket。以下是使用Java代码创建SSLServerSocket的示例代码:

    SSLServerSocketFactory ssf = context.getServerSocketFactory();  
    SSLServerSocket serverSocket = (SSLServerSocket) ssf.createServerSocket(port);  
    
    

    其中,port是服务器端口号。

    对于Android端,步骤类似,但是需要将证书文件放在正确的位置,并使用正确的密码。您可以将证书文件放在res/raw文件夹中,并使用以下代码加载证书:

    InputStream inputStream = getResources().openRawResource(R.raw.my_ca_cert);
    CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
    X509Certificate caCert = (X509Certificate) certificateFactory.generateCertificate(inputStream);
    inputStream.close();
    
    
    

    其中,R.raw.my_ca_cert是证书文件的资源ID。

    7、接下来,您可以使用以下代码将证书导入到TrustManager中:

    
    KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
    keyStore.load(null, null);
    keyStore.setCertificateEntry("my_ca_cert", caCert);
    
    TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
        TrustManagerFactory.getDefaultAlgorithm());
    trustManagerFactory.init(keyStore);
    
    TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
    
    

    8、然后,您可以使用SSLContext初始化,并将TrustManager传递给它:

    
    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(null, trustManagers, null);
    
    

    9、最后,您可以使用以下代码创建SSLSocket:

    
    SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
    SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket("hostname", port);
    
    

    其中,hostname是服务器主机名,port是服务器端口号。

    10、请注意,在Android 7.0及更高版本中,默认情况下禁用了对所有未受信任的CA证书的连接。如果您的服务器使用的是自签名证书,您需要使用以下代码来绕过此限制:

    
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        sslSocketFactory = new TLSUtil().getSslSocketFactory(trustManagers);
    }
    
    public class TLSUtil {
        public SSLSocketFactory getSslSocketFactory(TrustManager[] trustManagers) {
            try {
                SSLContext sslContext = SSLContext.getInstance("TLS");
                sslContext.init(null, trustManagers, new SecureRandom());
                SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
                return sslSocketFactory;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
    
    

    这将使用一个自定义的SSLSocketFactory来创建SSLSocket,并绕过Android的CA证书限制。请注意,这可能会降低通信的安全性,因为您无法保证服务器的身份。因此,建议仅在测试和开发环境中使用此方法。在生产环境中,应使用由受信任的CA颁发机构颁发的证书来保证通信的安全性。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(5条)

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 3月16日
  • 已采纳回答 3月11日
  • 创建了问题 3月10日

悬赏问题

  • ¥20 机器学习能否像多层线性模型一样处理嵌套数据
  • ¥20 西门子S7-Graph,S7-300,梯形图
  • ¥50 用易语言http 访问不了网页
  • ¥50 safari浏览器fetch提交数据后数据丢失问题
  • ¥15 matlab不知道怎么改,求解答!!
  • ¥15 永磁直线电机的电流环pi调不出来
  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效