首页 > 其他分享 >HTTPS加密原理

HTTPS加密原理

时间:2023-03-28 22:35:40浏览次数:41  
标签:加密 String System static HTTPS new 原理 byte

一、单向加密

单向加密算法又叫做不可逆算法, 就是明文被加密后,原则上是不能还原的;

名称 运行速度 安全性
MD5
SHA-1
SHA-256 更慢 更高
// hutool工具包有md5,sha1,sha256等加密算法
<dependency>
  <groupId>cn.hutool</groupId>
  <artifactId>hutool-all</artifactId>
</dependency>
public static void main(String[] args) throws NoSuchAlgorithmException {
    System.out.println(Arrays.toString(DigestUtil.md5("常见加密算法"))); //16位byte数组
    System.out.println(DigestUtil.md5Hex16("常见加密算法")); // 16位
    System.out.println(DigestUtil.md5Hex("常见加密算法")); // 32位
}

[12, 116, 39, -14, 17, -57, 63, -111, 78, -13, -14, 3, 62, -73, -64, -22]
11c73f914ef3f203
0c7427f211c73f914ef3f2033eb7c0ea

二、对称加密

对称加密就是用钥匙key给消息加密,然后用同一把钥匙key给消息解密,就是加密解密用同一个密钥.

算法 密钥长度 速度 安全性 资源消耗
DES 56/64 较快 低(完全依赖密钥,易受穷举搜索法攻击)
AES 128/192/256 高(ECB模式生成固定密钥安全性低,CBC模式每次生成的密文都不同安全性高)
IDEA 128 较慢 高(军事级,可抗差值分析和相关分析)

由于性能和安全性考虑,这里使用AES加密算法为例

AES的ECB模式:每次产生的密文都是相同的

public class AESECBUtil {
    /**
     * 加密
     *
     * @param content 加密内容
     * @param aesKey  加密aeskey,一定要16个字节
     */
    public static String encryption(String content, String aesKey) throws Exception {
        SecretKeySpec secretKey = new SecretKeySpec(aesKey.getBytes(), "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);

        byte[] bytes = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
        return Base64Utils.encodeToString(bytes);
    }

    /**
     * 解密
     *
     * @param content 解密内容
     * @param aesKey  加密使用的key,一定要16个字节
     */
    public static String decrypt(String content, String aesKey) throws Exception {
        byte[] bytes = StringUtils.isEmpty(content) ? null : Base64Utils.decodeFromString(content);
        SecretKeySpec secretKey = new SecretKeySpec(aesKey.getBytes(), "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        byte[] decryptBytes = cipher.doFinal(bytes);
        return new String(decryptBytes, StandardCharsets.UTF_8);
    }

    public static void main(String[] args) throws Exception {
        String msg = "这是测试内容";
        // key一定要16个字节
        String key = "123456789abcdefg";
        String encryption = encryption(msg, key);
        System.out.println(encryption);
        String decrypt = decrypt(encryption, key);
        System.out.println(decrypt);
    }
}
vjphG35JfUn8n8l0Iqos2qrURPN7J3zZaiPXU+3Rhmk=
这是测试内容

AES的CBC模式:每次产生的密文都是不相同的,安全性更高

public class AESCBCUtil {
    //这里需要设置你的32位字节密钥
    public static final String ENCRYPT_OR_DECRYPT_KEY = "1234567890abcdef1234567890abcdef";
    // 256位密钥 = 32 bytes Key:
    //CBC模式是安全性较高的AES加密模式,它需要一个随机数作为IV参数,这样对于同一份明文,每次生成的密文都不同
    public static final byte[] BYTES_KEY = ENCRYPT_OR_DECRYPT_KEY.getBytes(StandardCharsets.UTF_8);
    public static final String INSTANCE = "AES/CBC/PKCS5Padding";
    public static final String AES = "AES";

    // 加密
    public static String encrypt(String password) throws Exception {
        Cipher cipher = Cipher.getInstance(INSTANCE);
        SecretKeySpec keySpec = new SecretKeySpec(BYTES_KEY, AES);
        // CBC模式需要生成一个16 bytes的initialization vector
        SecureRandom sr = SecureRandom.getInstanceStrong();
        byte[] iv = sr.generateSeed(16);
        IvParameterSpec ivps = new IvParameterSpec(iv);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivps);
        byte[] data = cipher.doFinal(password.getBytes(StandardCharsets.UTF_8));
        // IV不需要保密,把IV和密文一起返回
        return DatatypeConverter.printBase64Binary(join(iv, data));
    }

    // 解密
    public static String decrypt(String password) throws Exception {
        byte[] iv = new byte[16];
        byte[] input = DatatypeConverter.parseBase64Binary(password);
        byte[] data = new byte[input.length - 16];
        // 把password分割成IV和密文
        System.arraycopy(input, 0, iv, 0, 16);
        System.arraycopy(input, 16, data, 0, data.length);
        // 解密
        Cipher cipher = Cipher.getInstance(INSTANCE);
        SecretKeySpec keySpec = new SecretKeySpec(BYTES_KEY, AES);
        IvParameterSpec ivps = new IvParameterSpec(iv);
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivps);
        return new String(cipher.doFinal(data), StandardCharsets.UTF_8);
    }

    public static byte[] join(byte[] bs1, byte[] bs2) {
        byte[] r = new byte[bs1.length + bs2.length];
        System.arraycopy(bs1, 0, r, 0, bs1.length);
        System.arraycopy(bs2, 0, r, bs1.length, bs2.length);
        return r;
    }

    public static void main(String[] args) throws Exception {
        String password = "这是CBC产生的密文";
        String encryptStr1 = encrypt(password);
        System.out.println("第一次加密:" + encryptStr1);
        String decryptStr1 = decrypt(encryptStr1);
        System.out.println("第一次解密:" + decryptStr1);

        String encryptStr2 = encrypt(password);
        System.out.println("第二次加密:" + encryptStr2);
        String decryptStr2 = decrypt(encryptStr1);
        System.out.println("第二次解密:" + decryptStr2);
    }
}
第一次加密:ujUa1sQAYN4tWDa9vrSnaiV8oFUjwb7dyRL93C3w3G7wzf1bs+L+/l1ipyjWkfzH
第一次解密:这是CBC产生的密文
第二次加密:QYP4nzAd/2DDuKiSMck1W3TuddXf71BBUSSzzS2f9h3cXolNZEwq0IUFWclJiDcQ
第二次解密:这是CBC产生的密文

可以从结果看到,第一次加密和第二次加密的密文都是不同的, 但是可以解析出相同的明文,安全系数很高.

三、非对称加密

非对称加密算法需要两个密钥:公开密钥(publickey:简称公钥)和私有密钥(privatekey:简称私钥)。公钥与私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。

常见的非对称加密有以下两种,这里以经典的RSA为例:

名称 成熟度 安全性 运算速度 资源消耗
RSA
ECC
public class RSAEncrypt {
    /**
     * 加密算法 DESEDE
     */
    private static String ALGORITHM = "RSA";
    /**
     * key值大小
     */
    private static int KEYSIZE = 1024;
    /**
     * 公钥存放文件自定义
     */
    private static final String PUBLIC_KEY_FILE = "PublicKey";
    /**
     * 私钥存放文件自定义
     */
    private static final String PRIVATE_KEY_FILE = "PrivateKey";
    /**
     * object 对象流
     */
    private static ObjectInputStream ois = null;

    /**
     * 生成密钥对
     */
    private static void generateKeyPair() throws Exception {
        //RSA算法可信任的随机数源
        SecureRandom sr = new SecureRandom();
        //RSA算法创建KeyPairGenerator对象
        KeyPairGenerator kpg = KeyPairGenerator.getInstance(ALGORITHM);
        //随机数据源初始化KeyPairGenerator对象
        kpg.initialize(KEYSIZE, sr);
        //生成密匙对
        KeyPair kp = kpg.generateKeyPair();
        //得到公钥
        Key publicKey = kp.getPublic();
        //得到私钥
        Key privateKey = kp.getPrivate();
        //用对象流将生成的密钥写入文件
        ObjectOutputStream ois = new ObjectOutputStream(new FileOutputStream(PUBLIC_KEY_FILE));
        ois.writeObject(publicKey);
        ois.close();
        ois = new ObjectOutputStream(new FileOutputStream(PRIVATE_KEY_FILE));
        ois.writeObject(privateKey);
        ois.close();
    }

    /**
     * 加密方法
     *
     * @param source 源数据
     * @return
     */
    public static String encrypt(String source) throws Exception {
        ois = new ObjectInputStream(new FileInputStream(PUBLIC_KEY_FILE));
        Key key = (Key) ois.readObject();
        ois.close();
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] b = source.getBytes();
        b = cipher.doFinal(b);
        return Base64.getEncoder().encodeToString(b);
    }

    /**
     * 解密算法
     *
     * @param cryptograph
     * @return
     * @throws Exception
     */
    public static String decrypt(String cryptograph) throws Exception {
        ois = new ObjectInputStream(new FileInputStream(PRIVATE_KEY_FILE));
        Key key = (Key) ois.readObject();
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, key);
        byte[] b = Base64.getDecoder().decode(cryptograph);
        b = cipher.doFinal(b);
        return new String(b);
    }

    public static void main(String[] args) throws Exception {
//        generateKeyPair();
        String source = "Hello World 要加密的字符串!!!@@@???   ===dd!";// 要加密的字符串
        String cryptograph = encrypt(source);// 生成的密文
        String cryptograph1 = encrypt(source);// 生成的密文
        String cryptograph2 = encrypt(source);// 生成的密文
        System.out.println(cryptograph);
        System.out.println(cryptograph1);
        System.out.println(cryptograph2);
        String target = decrypt(cryptograph);// 解密密文
        String target1 = decrypt(cryptograph1);// 解密密文
        String target2 = decrypt(cryptograph2);// 解密密文
        System.out.println(target);
        System.out.println(target1);
        System.out.println(target2);
    }
}
  • 公钥加密,私钥解,产生的密文都不相同
Ki5FfK2nZN1i8KAe6uImS220P98YopKk3aLcm2ievFPjgjt8q4EdqZAfrEwyXW0S3uo0EwBOle5e7lLqjmakk3BBaDGyyC/pZgtU8nCGLE6h56cRmi2aR/O3TrazQyOJ3vap0ex+Jc2uZmGX+Y4QYMzyd0h9hAcfcAs0xc9xnYw=
dPLgLMLgjjoljLOHYa7o9vhTtABNoYr03RqJUSDx2JCTN7n4pZbPD5BbfnrX0WsjM1+o6NgK/fVb8/FTUe7Wg/iq+HE/gW7bqprUl0k9UZXLLft6EWWNyZfoMcNXk3q3Dgb7IXK0qXf0WbWYcUBTf0g2KPsJJLmomYtkl+f9e4s=
DDE0mGZ49rBQ4Q2i4Iz01ybjTntRatTdvty5tYZXbo52GiINc/emcaqCilkL19mzUmTECVna8b/9L3duBJ9WbQoHQpes2KvSjn4Q1tYh+VZhIiUMuN/D4YqBIssFYGgK6rN2W7+f9Z+vVRxPnP2pDFh3ORbEl+ttBcHOy996XoE=
Hello World 要加密的字符串!!!@@@???   ===dd!
Hello World 要加密的字符串!!!@@@???   ===dd!
Hello World 要加密的字符串!!!@@@???   ===dd!
  • 私钥加密,公钥解,产生的密文相同
bfYvfBB3pTWanx/uBKpEkETeulsdNW75vGBU6xbeH5c+eUCtxtTAZV4UlZuZGL3CgPd04r3oBjTCssi1efUM2eUovfgSevKFlOaXSfp+mg6A3UhY1DKWvHSSFd7NkasftbA9D34COqB8RyUVGvJMYBIk6t55v5u1K52Rq1nsjMY=
bfYvfBB3pTWanx/uBKpEkETeulsdNW75vGBU6xbeH5c+eUCtxtTAZV4UlZuZGL3CgPd04r3oBjTCssi1efUM2eUovfgSevKFlOaXSfp+mg6A3UhY1DKWvHSSFd7NkasftbA9D34COqB8RyUVGvJMYBIk6t55v5u1K52Rq1nsjMY=
bfYvfBB3pTWanx/uBKpEkETeulsdNW75vGBU6xbeH5c+eUCtxtTAZV4UlZuZGL3CgPd04r3oBjTCssi1efUM2eUovfgSevKFlOaXSfp+mg6A3UhY1DKWvHSSFd7NkasftbA9D34COqB8RyUVGvJMYBIk6t55v5u1K52Rq1nsjMY=
Hello World 要加密的字符串!!!@@@???   ===dd!
Hello World 要加密的字符串!!!@@@???   ===dd!
Hello World 要加密的字符串!!!@@@???   ===dd!

四、HTTPS原理

HTTP存在的问题:

  • 无法保证消息的保密性
  • 无法保证消息的完整性和准确性
  • 无法保证消息来源的可靠性

HTTPS就是为了解决以上问题,这里的S值得是SSL加密,简单来说,HTTPS采用了一些加解密,数字证书,数字签名的技术来实现数据安全;

  • 数字证书与数字签名

为了解决非对称加密中公匙来源的不安全性。我们可以使用数字证书和数字签名来解决

  1. 数字证书的申请
    • 自己本地先生成一对RSA密匙,然后拿着自己的公匙以及其他信息(比如说企业名称)去CA申请数字证书
    • CA在拿到这些信息后,会选择一种单向Hash算法(类似MD5)对这些信息进行加密,可以防止篡改, 加密之后的东西我们称之为摘要
    • CA还会用自己的私匙对摘要进行加密,摘要加密后的数据我们称之为数字签名
    • CA将会把我们的申请信息(包含服务器的公匙)和数字签名整合在一起,由此而生成数字证书给到浏览器
  2. 浏览器怎么验证数字签名
    • 服务器在获取到数字证书后,服务器会将数字证书发送给客户端,客户端就需要用CA的公匙解密数字证书并验证数字证书的合法性
    • 我们的电脑和浏览器中已经内置了一部分权威机构的根证书,这些根证书中包含了CA的公匙
    • 客户端用CA的公匙解密数字证书,如果解密成功则说明证书来源于合法的认证机构。解密成功后,客户端就拿到了摘要。
    • 客户端会按照和CA一样的Hash算法将申请信息生成一份摘要,并和解密出来的那份做对比,如果相同则说明内容完整,没有被篡改
    • 最后,客户端安全的从证书中拿到服务器的公匙就可以和服务器进行安全的非对称加密通信了
  • HTTPS原理
  1. 浏览器验证完数字证书后,本地生成一个随机的AES密钥xxx
  2. 通过服务器传来的公钥对xxx进行加密,服务器拿到后通过私钥进行解密,拿到xxx
  3. 双方都知道了密钥,建立了HTTPS的链接,就可以用它来加密通信了

标签:加密,String,System,static,HTTPS,new,原理,byte
From: https://www.cnblogs.com/sun2020/p/17267013.html

相关文章

  • 最小生成树+点乘原理
    点乘原理对于两个向量,最小向量点乘即为向量中最大的去乘另外一个向量中最小的,重复执行,最后的结果即为最小的观察题意,易得二分答案p,再写一个check()函数即可在check过......
  • 一文剖析:LVS/Nginx/HAProxy原理及应用场景
    负载均衡已经发展成为网络架构中的基础核心组件,消除了服务器单点故障,可以进行请求流量分流,提升冗余,保证服务器的稳定性。在开源的软件负载均衡中,应用最为广泛的有LVS、Nginx......
  • 19-springboot自动配置原理
    SpringBoot自动配置原理(SpringBoot自动装配原理,SpringBootstarter原理)SpringBoot可以根据定义在classpath下的类,自动的给你生成一些Bean,并加载到Spring的Context中,自动配......
  • Javascript 加密解密方法
    本文链接Javascript和我之前发的python加密以及go加密解密不一样不需要导那么多的库只需要安装几个库其中需要了解最多的crypto-js具体就不多介绍了直接上官......
  • k8s service原理
    1.为什么需要servicePod是非永久性资源,会动态创建和销毁,pod的ip会变化,而service会动态感知pod的变化,而对调用方无感知,调用方只需要访问固定的servicename就可以动态地访......
  • mongodb和redis设计原理简析
    redis:1、NIO通信  因都在内存操作,所以逻辑的操作非常快,减少了CPU的切换开销,所以为单线程的模式(逻辑处理线程和主线程是一个)。  reactor模式,实......
  • 交换机的工作原理
    1.以太网帧的格式包的数据大小有(46---1500字节),帧的数据大小有(64---1518字节)帧是将目标地址、源地址等都进行了封装2.交换机的工作原理2.1插上交换机进入初始状态交换......
  • 【解答】MySQL MTR的实现原理与优势
    MySQLMTR(MySQLTestRun)是MySQL数据库测试框架,用于自动化测试MySQL数据库系统的功能和性能。MTR由MySQL官方提供,包含了大量的测试用例,可以对MySQL数据库系统的各......
  • 编程原理
    编程原理一、问题求解1、问题求解(ProblemSolving):指描述问题,以及开发计算机程序来解决问题的整个过程。这个过程经历多个阶段,包括理解待解决问题、设计概念化解决方案,以及用......
  • let 运行原理
    1.servlet的工作过程以及容器的作用Servlet没有main()方法,他们受控与另外一个java应用,这个java应用称为容器(Container)。Tomcat就是这么一个容器,web服务器应用(如Apache)......