https及证书认证

一、HTTPS通讯原理

Https是基于安全目的的Http通道,其安全基础由SSL层来保证。

最初由Netscape公司研发,主要提供了通讯双方的身份认证和加密通信方法。

二、SSL协议通信过程

1.客户端浏览器发送一个连接请求给服务器,服务器将自己的证书(包含服务器公钥S_PuKey)、对称加密算法种类以及其他相关信息返回给客户端

2.客户端浏览器检查服务器传送到CA证书是否由自己信赖的CA中心签发,若是,则执行第4步,否则,给客户一个警告:询问是否继续访问

3.客户端浏览器比较证书里的信息,如证书有效期,服务器域名和公钥S_PuKey,与服务器传回的信息是否一致,如果一致,则浏览器完成对服务器的身份认证。

4.服务器要求客户端发送客户端证书(包含客户端公钥C_PuKey)、支持的对称加密方案,以及其他的相关信息。收到后,服务器进行相同的身份验证,若没有通过验证,则拒绝连接;

5.服务器根据客户端浏览器发送的密码种类,选择一种加密程度最高的方案,用客户端公钥C_PuKey加密后通知客户端浏览器

6.客户端浏览器通过私钥C_PrKey解密后,得知服务器选择的加密方案,并选择一个通话密钥Key,接着用服务器公钥S_PuKey加密后发送给服务器

7.服务器接收到的浏览器传送的消息,用私钥S_PrKey解密,获得通话密钥key

8.接下来的数据传输都使用该对称密钥key进行加密。

上面所述的是双向认证SSL协议的具体通讯过程,服务器和用户双方必须都有证书。由此可见,SSL协议是通过非对称密钥机制保证双方身份认证,并完成建立连接,在实际数据通讯时通过对称密钥机制保证数据安全性

三、SSL协议基础

SSL协议位于TCP/IP协议与各种应用层之间,本身又分为两层:

SSL记录协议:(SSL Record Protocol)建立在可靠传输协议(TCP)之上,为上层协议提供数据,封装,压缩,加密等基本功能。

SSL握手协议:(SSL Handshake Protocol)在SSL记录协议之上,用于实际数据传输前,通讯双方进行身份认证,协商加密算法,交换加密密钥等。

四、HTTPS与HTTP的区别?

协议基础不同:HTTPS在HTTP的基础上加入了SSL层

通讯方式不同:HTTPS在数据通讯之前需要客户端、服务器进行握手(身份验证),建立连接后,传输数据需要经过加密,通信端口为443

五、Android配置

1.需要验证证书

a.导出公钥。在浏览器上用https访问tomcat,查看其证书,并另存为一个文件(存成了X.509格式:xxxx.cer)

b.导入公钥。把xxxx.cer放在Android的assets文件夹中,以方便在运行时通过代码读取此证书

以下为方便大家复制:

AssetManageram=context.getAssets();

InputStreamins=am.open("robusoft.cer");

try{

//读取证书

CertificateFactorycerFactory=CertificateFactory.getInstance("X.509");//问1

Certificatecer=cerFactory.generateCertificate(ins);

//创建一个证书库,并将证书导入证书库

KeyStorekeyStore=KeyStore.getInstance("PKCS12","BC");//问2

keyStore.load(null,null);

keyStore.setCertificateEntry("trust",cer);

returnkeyStore;

}finally{

ins.close();

}

//把咱的证书库作为信任证书库

SSLSocketFactorysocketFactory=newSSLSocketFactory(keystore);

Schemesch=newScheme("https",socketFactory,443);

//完工

HttpClientmHttpClient=newDefaultHttpClient();

mHttpClient.getConnectionManager().getSchemeRegistry().register(sch);

2.不需要验证证书

方便复制:

public class Demo extends Activity {

/** Called when the activity is first created. */

private TextView text;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

text = (TextView)findViewById(R.id.text);

GetHttps();

}

private void GetHttps(){

String https = " https://800wen.com/";

try{

SSLContext sc = SSLContext.getInstance("TLS");

sc.init(null, new TrustManager[]{new MyTrustManager()}, new SecureRandom());

HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

HttpsURLConnection.setDefaultHostnameVerifier(new MyHostnameVerifier());

HttpsURLConnection conn = (HttpsURLConnection)new URL(https).openConnection();

conn.setDoOutput(true);

conn.setDoInput(true);

conn.connect();

BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));

StringBuffer sb = new StringBuffer();

String line;

while ((line = br.readLine()) != null)

sb.append(line);

text.setText(sb.toString());

}catch(Exception e){

Log.e(this.getClass().getName(), e.getMessage());

}

}

private class MyHostnameVerifier implements HostnameVerifier{

@Override

public boolean verify(String hostname, SSLSession session) {

// TODO Auto-generated method stub

return true;

}

}

private class MyTrustManager implements X509TrustManager{

@Override

public void checkClientTrusted(X509Certificate[] chain, String authType)

throws CertificateException {

// TODO Auto-generated method stub

}

@Override

public void checkServerTrusted(X509Certificate[] chain, String authType)

throws CertificateException {

// TODO Auto-generated method stub

}

@Override

public X509Certificate[] getAcceptedIssuers() {

// TODO Auto-generated method stub

return null;

}

}

}

 

HTTP与HTTPS区别及Android证书配置

区别

HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure Sockets Layer)协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。

HTTPS和HTTP的区别主要如下:

1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。

2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。

3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。

4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

HTTPS 工作原理、工作流程

1. 客户端发起请求

2. 服务端配置公钥私钥。如果是使用购买的证书,把公钥告诉客户端。

3. 服务端把当前此次请求的证书(公钥)传送过来

image.png

4. 客户端进行证书解析

客户端会验证公钥是否有效。如果没有问题,就回生成一个随机值,并对其进行加密,(这个随机值其实就是对称加密的私钥)

5. 将加密后的随机值等加密信息传给服务端

6.服务端解密信息

服务端用私钥解密后,得到了客户端传过来的随机值(私钥),然后把内容进行对称加密。

7. 通信。因为客户端跟服务端都有对称加密的秘钥。所以ok了。

加密过程中的对称加密非对称加密

首先用的是非对称加密。把公钥给客户端,私钥在服务端。客户端用公钥验证通过后,会生成私钥进行对称加密。然后传给后台。
为什么这么做呢。

  • 对称加密加密与解密使用的是同样的密钥,所以速度快,但由于需要将密钥在网络传输,所以安全性不高。
  • 非对称加密使用了一对密钥,公钥与私钥,所以安全性高,但加密与解密速度慢。
  • 所以第一次用公钥私钥验证。没问题之后,在用对称加密。这样既安全又高效。

Android证书配置。结合流程看一下

/**
     * 使用购买的证书
     */
    public static SSLSocketFactory getDefSSLSocketFactory() {
        try {
            //初始化SSLContext
            SSLContext sslContext = SSLContext.getInstance(PROTOCOL_TYPE);
            final TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {

                @Override
                public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                }

                //验证服务端证书的公钥
                @Override
                public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                    if (chain == null) {
                        throw new IllegalArgumentException("checkServerTrusted:x509Certificate array isnull");
                    }
                    if (!(chain.length > 0)) {
                        throw new IllegalArgumentException("checkServerTrusted: X509Certificate is empty");
                    }
                    if (!(!TextUtils.isEmpty(authType) && authType.toUpperCase().contains("RSA"))) {
                        throw new CertificateException("checkServerTrusted: AuthType is not RSA");
                    }
                    // Hack ahead: BigInteger and toString(). We know a DER encoded Public Key begins
                    // with 0×30 (ASN.1 SEQUENCE and CONSTRUCTED), so there is no leading 0×00 to drop.
                    RSAPublicKey pubkey = (RSAPublicKey) chain[0].getPublicKey();
                    /* signum:1表示是正数;radix:16表示字节数组转16进制 */
                    String encoded = new BigInteger(1 /* positive */, pubkey.getEncoded()).toString(16);
                    final boolean expected = PUB_KEY.equalsIgnoreCase(encoded);  //验证服务端证书的公钥
                    if (!expected) {
                        throw new CertificateException("checkServerTrusted: got error public key:" + encoded);
                    }
                }

                @Override
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return new java.security.cert.X509Certificate[0];
                }
            }};
            //将随机数等加密之后传给服务端。
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
            return sslContext.getSocketFactory();
        } //省略各种异常处理,请自行添加
        catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        return null;
    }

图中的方法是验证服务端购买的证书。如果是信任所有证书的。这三个重写的方法不需要做操作。直接用默认即可。

猜你喜欢

转载自blog.csdn.net/jianpan_zouni/article/details/89246508