网络安全面试的HTTPS问题_HTTPS原理剖析

一、什么是HTTP协议

HTTP规范主要内容

1.请求方式 request method

最常见的就是GET和POST,还有其他请求方式

类型描述
GET请求从服务器获取资源
HEAD类似于GET请求,只不过不会返回实体数据,只获取报头
POST向服务器提交数据
PUT替换服务器的内容
DELETE请求服务器删除指定的资源
TRACE对链路进行测试或者诊断
…………

而且HTTP协议是可扩展的

2.请求和响应格式

HTTP请求request格式
在这里插入图片描述

HTTP响应response格式
在这里插入图片描述

3.响应状态码

类型描述
1xx信息,服务器收到请求,需要请求者继续执行操作
2xx成功,操作被成功接收并处理
2xx重定向,需要进一步的操作以完成请求
4xx客户端错误,请求包含语法错误或无法完成请求
5xx服务端错误,服务器在处理请求的过程中发生了错误

4.通信特点

1.请求应答模式

2.灵活可扩展

3.可靠传输——基于传输层的TCP协议(3次握手,4次挥手)

4.无状态——stateless,这一次访问和下一次访问没有任何关联----》cookie和session的诞生

二、为什么HTTP不安全

1.泄漏——破坏机密性
数据明文传输

2.篡改——破坏完整性

3.冒充——破坏真实性

泄漏的问题怎么解决?
数据加密,发送密文
在这里插入图片描述

1975年IBM公布了DES(Data Encryption Standard,标准加密算法,一种对称加密算法)

对称加密:共享密钥加密

比如:
密钥–12345678
encrypt(“bones 666”,“12345678”)----->密文
decrypt(“9jI4vE1h+frU4I/ZVAIEhQ==”,“12345678”) ----->明文

这个过程是可逆的

下面Java代码用来实现DES加密算法:(JDK版本8,太高无法运行,因为有一些包是1.8的)

public class DESEncrypt {

    public static final String ALGORITHM ="DES";

    public static void main(String[] args) throws Exception {
        // 定义密钥
        String key = "12345678";
        // 明文
        String text = "zyy 好爽";
        // 加密
        String cipher = encryptDesCipher(text, key);
        System.out.println("DES加密后密文:"+cipher);

        // 解密
        text = decryptDesCipher(cipher, key);
        System.out.println("DES解密后明文:"+text);
    }

    // DES加密算法
    private static String encryptDesCipher(String text, String origKey) throws Exception{
        Key key = new SecretKeySpec(origKey.getBytes(), ALGORITHM);
        Cipher cipher = Cipher.getInstance("DES");
        cipher.init(Cipher.ENCRYPT_MODE, key);
        return Base64.encode(cipher.doFinal(text.getBytes()));
    }

    // DES解密算法
    private static String decryptDesCipher(String text, String origKey) throws Exception{
        Key key = new SecretKeySpec(origKey.getBytes(), ALGORITHM);
        Cipher cipher = Cipher.getInstance("DES");
        cipher.init(Cipher.DECRYPT_MODE, key);
        return new String(cipher.doFinal(Base64.decode(text)));
    }
}

运行结果:
在这里插入图片描述

当然还有改进版本的DES,这里就先不提。现在应该要关注的就是这个对称加密算法用在通信中,是如何工作的?

在这里插入图片描述

(1)服务端和客户端约定一个密钥
(2)客户端向服务端发送加密好之后的信息,服务端解密

难点1:密钥传输问题,密钥如何约定?总不能物理传输吧,hhh
难点2:访问人数一多,就要生成很多密钥,维护以及查找非常消耗性能和资源。

总结:对称加密的特点

不足:
1.密钥的私密性问题
2.密钥的存储、管理问题
优点:
计算简单,速度快

三、对称加密和非对称加密

对称加密已经分析在上面了,下面说说非对称加密。

非对称加密(公开密钥加密)
1.生成密钥对key pair(算法生成的)
{publicKey、privateKey}

2.公钥加密
encrypt(“bones 666”,publicKey);—>密文

3.私钥解密
decrypt(“”,privateKey);---->明文

举一个生活中的智慧来理解:
在这里插入图片描述

代码实现(1977年RSA,世界上第一个非对称加密的算法):(JDK1.8运行)

public class RSAEncrypt {
    private final static int KEY_SIZE = 1024;
    public static final String ALGORITHM ="RSA";
    public static final String CHARSET ="UTF-8";
    private static Map<Integer, String> keyMap = new HashMap<Integer, String>();

    public static void main(String[] args) throws Exception {
        // 生成密钥对
        genKeyPair();
        String publicKey =  keyMap.get(0);
        String privateKey = keyMap.get(1);
        System.out.println("公钥:" + publicKey);
        System.out.println("私钥:" + privateKey +"\n");
        System.out.println("----------------------------");
        String message = "bones 666";

        // 用公钥加密,得到密文
        String cipher = encrypt(message, publicKey);
        System.out.println("用公钥加密后的密文:" + cipher);

        // 用私钥解密,得到明文
        String messageDe = decrypt(cipher, privateKey);
        System.out.println("用匹配的私钥解密后的明文:" + messageDe);
    }

    /**
     * 随机生成密钥对
     */
    public static void genKeyPair() throws NoSuchAlgorithmException {
        // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(ALGORITHM);
        // 初始化密钥对生成器
        keyPairGen.initialize(KEY_SIZE, new SecureRandom());
        // 生成一个密钥对,保存在keyPair中
        KeyPair keyPair = keyPairGen.generateKeyPair();
        // 得到私钥
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        // 得到公钥
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        String publicKeyString = Base64.getEncoder().encodeToString(publicKey.getEncoded());
        // 得到私钥字符串
        String privateKeyString = Base64.getEncoder().encodeToString(privateKey.getEncoded());
        // 将公钥和私钥保存到Map
        //0表示公钥
        keyMap.put(0, publicKeyString);
        //1表示私钥
        keyMap.put(1, privateKeyString);
    }

    /**
     * RSA公钥加密
     * @param str    加密字符串
     * @param publicKey 公钥
     * @return 密文
     * @throws Exception 加密过程中的异常信息
     */
    public static String encrypt(String str, String publicKey) throws Exception {
        // base64编码的公钥
        byte[] decoded = Base64.getDecoder().decode(publicKey);
        RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance(ALGORITHM).generatePublic(new X509EncodedKeySpec(decoded));
        // RSA加密
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        String outStr = Base64.getEncoder().encodeToString(cipher.doFinal(str.getBytes(CHARSET)));
        return outStr;
    }

    /**
     * RSA私钥解密
     * @param str    加密字符串
     * @param privateKey 私钥
     * @return 明文
     * @throws Exception 解密过程中的异常信息
     */
    public static String decrypt(String str, String privateKey) throws Exception {
        // 64位解码加密后的字符串
        byte[] inputByte = Base64.getDecoder().decode(str);
        // base64编码的私钥
        byte[] decoded = Base64.getDecoder().decode(privateKey);
        RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance(ALGORITHM).generatePrivate(new PKCS8EncodedKeySpec(decoded));
        // RSA解密
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, priKey);
        String outStr = new String(cipher.doFinal(inputByte));
        return outStr;
    }

}

main方法运行结果:
在这里插入图片描述

非对称加密算法用在通信中,是如何工作的?

非对称加密算法流程

1.消息接收方生成密钥对,公开公钥
2.消息发送方用公钥加密消息
3.消息接收方用私钥解密消息

(1)浏览器获得服务器的公钥

在这里插入图片描述
注意:私钥自己保存

(2)公钥加密,私钥解密

在这里插入图片描述

(注意:上面用的是同一把公钥)

非对称加密的特点

优点:
1.不用担心密钥阐述过程中泄漏
2.存储、管理成本低

不足:
1.加密、解密更慢----》会涉及到大数乘法大数模等运算
2.如果服务器在发放公钥的时候,被黑客或者别的骗子掉包了怎么办 ?(身份冒充问题

公钥传输:如果公钥被调包–中间人攻击(MITM)

Man-in-the-Middle Attack (MITM)
在这里插入图片描述

服务器将公钥发送出去之后,是不够权威和可信的,无法验证。

可信问题

看一个生活中的案例:

某村首富突然去世,留下巨额遗产
儿子继承遗产,需要证明他爸是他爸

需要一个公信力的机构,比如派出所;也可以亲自鉴定,DNA

如何证明身份?

数字证书:Digital Certificate
证书授权中心(CA):Certificate Authority ----- CA

全球有很多颁发这种证书的机构,比如百度的证书:
在这里插入图片描述

CA颁发的证书

提交:域名、公司、联系人、公钥

证书包含:
颁发者、域名、公钥、有效期等

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

颁发证书就基本可以解决中间人攻击了。

问题:有人冒充CA咋办

1.如果骗子冒充你的身份,用他的域名去办证书会怎么样?
·不要怀疑这么多!CA不是吃干饭的,有权威性
·如果域名不匹配,浏览器会报错:
在这里插入图片描述

2.骗子网站把你的证书放到他的网站,冒充你怎么办?
·偷了证书没有用,没有私钥都是白扯

3.骗子把你的证书里面的公钥换成他自己的怎么办?
·如何防止证书内容被篡改?联系生活实际,借条和合同如何保证是你本人签署,未经篡改?—>签名+指纹
·计算机中,指纹就是校验哈希值
比如kali官网中,文件下载会提供Hash Code:
在这里插入图片描述
(check sum----摘要)

生成摘要,防止篡改

在这里插入图片描述

哈希方法:比如MD5(现在已经基本不用了),SHA256

对摘要加密,得到指纹

1.CA用哈希算法服务器公钥生成摘要(哈希值),机密后得到指纹
2.客户端用哈希算法服务器公钥生成摘要(哈希值),解密指纹,对比摘要

在这里插入图片描述

在这里插入图片描述

这样子就会陷入俄罗斯套娃。

摘要的加密和对比(非常重要!!!)

第一步:
CA生成一对密钥对
CA用它的私钥对摘要进行加密,得到一串密文,这个就是指纹

第二步:客户端用CA的公钥对指纹进行解密,得到摘要,然后跟自己计算出来的摘要进行对比。

问题:
1.为什么用私钥加密,公钥解密
2.如果浏览器要用CA的公钥解密(验签)指纹,CA的公钥在哪?浏览器从哪里得到?

CA公钥的传输

CA的公钥是怎么发给客户端的?

谁来证明CA的公钥的权威性?

如果有人冒充CA颁发的证书给自己怎么办?

加签验签(非常重要!

!!)

·公钥加密——私钥解密
·私钥加签——公钥验签

·用公钥加密,就可以保证只有持有私钥的人才能读取消息,没有私钥的人不能解密。保证私密。
·用私钥加签,就可以保证只有持有私钥的人才能发出消息,否则无法通过公钥验签。保证身份不可伪造。

加签验签代码

Java代码(JDK1.8)

public class RSASignature {
    public static final String ENCRYPT_ALGORITHM = "RSA";
    public static final String SIGN_ALGORITHM = "SHA1WithRSA";
    private static final int KEY_SIZE = 1024;
    private static Map<Integer, String> keyMap = new HashMap<Integer, String>();

    public static void main(String[] args) throws NoSuchAlgorithmException {
        // 生成公钥和私钥
        genKeyPair();
        String publicKey =  keyMap.get(0);
        System.out.println("公钥:" +publicKey);
        System.out.println();
        String privateKey = keyMap.get(1);
        System.out.println("私钥:" + privateKey);
        System.out.println();

        String sign = sign("bones666", privateKey);
        System.out.println("私钥签名后结果:" + sign);

        System.out.println();
        System.out.println("对密文用明文、公钥验签后结果:" + doCheck("bones666",sign, publicKey));
    }


    /**
     * 随机生成密钥对
     */
    public static void genKeyPair() throws NoSuchAlgorithmException {
        // RSA算法生成公钥和私钥对
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(ENCRYPT_ALGORITHM);
        // 初始化密钥对生成器
        keyPairGen.initialize(KEY_SIZE, new SecureRandom());
        // 生成一个密钥对,保存在keyPair中
        KeyPair keyPair = keyPairGen.generateKeyPair();
        // 得到私钥、公钥
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        // 得到字符串
        String publicKeyString = Base64.getEncoder().encodeToString(publicKey.getEncoded());
        String privateKeyString = Base64.getEncoder().encodeToString(privateKey.getEncoded());
        // 将公钥和私钥保存到Map
        keyMap.put(0, publicKeyString);
        keyMap.put(1, privateKeyString);
    }

    /**
     * RSA签名
     */
    public static String sign(String content, String privateKey) {
        try {
            PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(new BASE64Decoder().decodeBuffer(privateKey));
            KeyFactory factory = KeyFactory.getInstance(ENCRYPT_ALGORITHM);
            PrivateKey priKey = factory.generatePrivate(priPKCS8);
            java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHM);
            signature.initSign(priKey);
            signature.update(content.getBytes());
            byte[] signed = signature.sign();
            return new BASE64Encoder().encode(signed);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * RSA验签
     */
    public static boolean doCheck(String content, String sign, String publicKey) {
        try {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            byte[] encodedKey = new BASE64Decoder().decodeBuffer(publicKey);
            PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));

            java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHM);

            signature.initVerify(pubKey);
            signature.update(content.getBytes());

            boolean bverify = signature.verify(new BASE64Decoder().decodeBuffer(sign));
            return bverify;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

}

运行结果:
在这里插入图片描述

签名和验签的流程

验签:
1.对服务器公曰用哈希算法生成摘要(哈希值)
2.用CA公钥对指纹(密文)进行解密,得到摘要(哈希值)
3.对比两个摘要(哈希值)是否匹配

加签:
1.对服务器公钥用哈希算法生成摘要(哈希值)
2.用CA私钥对摘要加密,得到指纹(密文)

在这里插入图片描述

CA的公钥其实在你的电脑中(CA的证书是有信任链的,CA的根证书早就放在了你的电脑中了)

win+R–MMC可以查看根证书

那如果操作系统很久很久没有更新那怎么办呢?那只能更新操作系统了

比如在win7系统中安装mysql报错了:
在这里插入图片描述

其实就是根证书没有。

有时候需要自己把这个根证书放在电脑中怎么做呢?
用AWVS漏洞扫描工具就要求安装一个根证书:
在这里插入图片描述
一般安装根证书这个操作是非常敏感的。

最后还有一个问题:

问题:服务器回复你的消息,但是没有加密怎么办?

浏览器给服务器发消息,用服务器的公钥加密,服务器用自己的私钥解密。

但是服务器没有浏览器的公钥,那服务器怎么响应消息给浏览器呢?

这里要补充一下:

安全的通信

1.认证
2.协商
3.通信

在这里插入图片描述
在通信过程中,其实并不是一直用非对称加密的。非对称加密更多的是用在身份认证中。

SSL/TLS在HTTP中的应用

上面介绍的这种通信方式就是网景公司(Netscape)提出的。

SSL(Secure Socket Layer)安全 套接层

后来又改名成

TLS(Transport Layer Security)传输层安全协议

HTTP和HTTPS

要说明HTTP和HTTPS的关系,需要了解SSL/TLS的工作层次

在这里插入图片描述

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值