前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >5分钟讲清楚常用加密算法

5分钟讲清楚常用加密算法

作者头像
编程思维
发布2023-03-23 14:23:57
7991
发布2023-03-23 14:23:57
举报
文章被收录于专栏:程序员面试小技巧

为什么要加密?

当然是为了保密。

最早的密码应用,都伴随着阴谋与战争。

中国古代的“阴符”、“阴书”就是其中的代表。


到了近代,二战最著名的一个故事,就是纳粹德国的Enigma密码机

以及图灵和他发明的密码破解机。

可以说,现代战争中,信息安全极其重要

如果你的部署、命令都被对手知道

你收到的指令都是对手伪造的

这还怎么打?


在当下,加密数据和密码的应用,

从军事,到商业领域,以及科学界

乃至每个人普通的生活

如果没有数据加密,每个人的信息都是透明的

想想可怕的电话诈骗,你还觉得自己的信息安全吗?

有一句话说的是:

大数据时代,没有秘密


加密方式

最常见的计算机加密方式有三种:

对称、非对称、摘要

对称的意思是:

代码语言:javascript
复制
我有一个秘钥K,能把原文 A 加密成 A1,还能把 A1 还原成 A

f(A, K) =A1
f(A1, K) =A

对称加密用途最为广泛,

操作简单,速度快,

适合场合多样

但缺点很明显,秘钥K太关键了

如果你需要让密文被其他授信的人访问

必须给他发秘钥

但问题是,

只要得到秘钥,就能破解一切,包括非法用户


非对称安全性稍微高一点

有2个秘钥,一般是成对的公钥和私钥

通常是用公钥加密,私钥解密

这种情况下,解决了对称加密的发送秘钥问题

现在公钥是公开的,私钥只有我自己有

永远不发送,就不会泄密


摘要加密一般采用的是hash算法,

只加密不解密,

适合于只验证对不对,而不验证是什么。

举个朴素例子:

二中的学生,学号格式是 L220130103 格式

三中的学生,学号格式是 PLE821 格式

现在我要验证这个人是哪个学校的,

其实无需关注具体内容,

简单判断一下长度就可以了


当然真正的算法没这么简单

下面具体来谈

便于大家统一理解

我们建一个项目

统一使用hutool工具包

代码语言:javascript
复制
    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>5.8.5</version>
    </dependency>

对称加密

最简单的是des方法

他使用一个简单的秘钥,就可以实现加密和解密

我们写一个junit的test,或者写一个main也可以

代码语言:javascript
复制
class Test1 {
	@Test
	void test() {
		String text0 = "这是原文";
		String key = "xiaomian";
		
		DES des = new DES(key.getBytes());
		String text1=des.encryptBase64(text0);
		System.out.println(text1);
	}
}

运行结果是 +iJWs7q8+dyiRBouA8lDBA==

我们使用秘钥 “xiaomian”,

把“这是原文”,加密成了一个看不懂的字符串

然后开始解密

代码语言:javascript
复制
class Test1 {
	@Test
	void test() {
		String key = "xiaomian";
		DES des = new DES(key.getBytes());
		
		String text2=des.decryptStr("+iJWs7q8+dyiRBouA8lDBA==");
		System.out.println(text2);
	}
}

运行结果是 这是原文

还是同一个key,

用相反的方法,把原文解出来了

操作非常简单。

des就是一个最简单的对称加解密方法

类似的还有aes算法

可以使用hutool工具包,

操作差不多

非对称加密

使用非对称的主要原因

就是 安全、安全、还是安全

非对称在性能方面和对称没的比

因此,建议非对称使用短数据场合

而长数据使用对称实现。


最常用的是RSA算法

首先要生成一对秘钥,这个就没法人工创造了

我们可以借助工具

代码语言:javascript
复制
class Test2 {
	@Test
	void test() {
        KeyPair pair = SecureUtil.generateKeyPair("RSA");
        String privateKey = Base64.encode(pair.getPrivate().getEncoded());
        System.out.println("privateKey:" + privateKey);
        String publicKey = Base64.encode(pair.getPublic().getEncoded());
        System.out.println("publicKey:" + publicKey);
	}
}

输出结果为:

代码语言:javascript
复制
privateKey:MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALBgrUOQySQB72VrGyijYZcaNM26t49oaKlNddu4SLpEdJzpUnVjXtIi9Nj/DkFBXgSB9FYdrv7MpQWzTmLw0do6pcfo2cekmBGPnFRdChtEf8Npq0pAV2LlNahwkB8fxZcbQYaaWBuBkx7aHT09JGsEpi9P3y7ae4vwYmFlWgEHAgMBAAECgYBVBnXgEWb1Zb1rLaPNBl3gQrDb0Dv29QUnQIElZ4QfzypMDipDDqFCObnA9cuAZ6uUDrWj4fFfQXX39oU+KwtuESddT9rJw1hPSy2i5ityEyYO5OZQRJaTVWPWzpph+bqFLkngaOvlr3OBG7YtywUL0P8toz2pOQKpoQOkffetuQJBAP26GKiOcs/sKhrzuM/t0S2ERXXDcu07jWxJ8gioQBuQaM7AA14tbiRzaZm3Xt+cGPjHJUGEJpDvGLQ9MavEZDMCQQCx9S+JevTGpxHMX/R3uUawlTsks1keyd0rqBtqQQx7V9Bm8htrlVU3QbhacFd/FJodWX7mGOAO6nLVGK/5qXvdAkB13zSBadvwuDg/WSZsgoEA8kgKk4gaqeXjft7QIsnVhFsMYauu3tAiYvOWE9ghbbU0LeAi9a+s+UayxRMERzJ9AkA5Y7fL32I2+kQMI9nEDnUUl1u2bzxLaJAx9wm4T3gGAwDLYkKjhEoyArjAOcCN1AgLdQQuklEXnlYgENEXc6flAkEAwDbTBfOtuP/6S5nU0gX9D5fYlF/fz4YTfBjHC2dZ/wrmWlJA0f7QFf5DysQB9AXJX6ZWL/3LkMtHPafqBMKpJw==

publicKey:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwYK1DkMkkAe9laxsoo2GXGjTNurePaGipTXXbuEi6RHSc6VJ1Y17SIvTY/w5BQV4EgfRWHa7+zKUFs05i8NHaOqXH6NnHpJgRj5xUXQobRH/DaatKQFdi5TWocJAfH8WXG0GGmlgbgZMe2h09PSRrBKYvT98u2nuL8GJhZVoBBwIDAQAB

看吧,鬼也看不懂

不过能用就行

接下来,开始使用秘钥对,进行加密和解密

代码语言:javascript
复制
class Test2 {
	static String privateKey;
	static String publicKey;
	
	@BeforeAll
	static void createKey() {
        KeyPair pair = SecureUtil.generateKeyPair("RSA");
        privateKey = Base64.encode(pair.getPrivate().getEncoded());
        System.out.println("privateKey:" + privateKey);
        publicKey = Base64.encode(pair.getPublic().getEncoded());
        System.out.println("publicKey:" + publicKey);
	}
	
	@Test
	void test() {
		String text = "这是原文";
		RSA rsa = new RSA(AsymmetricAlgorithm.RSA_ECB_PKCS1.getValue(), privateKey, publicKey);

        String text1 = rsa.encryptBase64(text, KeyType.PublicKey);
        System.out.println("公钥加密: " + text1);
        String text2 = rsa.decryptStr(text1, KeyType.PrivateKey);
        System.out.println("私钥解密: " + text2);
	}
}

输出结果为:

代码语言:javascript
复制
公钥加密: KSifTf6tS6LGlBT9LJC33VXzkXtaQEIGJcpf1BU2ptzRXTtBzvjx83EffCqntD7/M7ZciTr4MIBFBPFCxLs9NVEeC4K9/B8fQE/3hdsMzWBTnKQzQR2vd1i5mOgFaHYwTLwrq9Dbkv1YGluCb004YtLEqdjSO/Oljs7x2YVtvGc=
私钥解密: 这是原文

也可以反过来用

代码语言:javascript
复制
	@Test
	void test() {
		String text = "这是原文";
		RSA rsa = new RSA(AsymmetricAlgorithm.RSA_ECB_PKCS1.getValue(), privateKey, publicKey);

        String text1 = rsa.encryptBase64(text, KeyType.PrivateKey);
        System.out.println("私钥加密: " + text1);
        String text2 = rsa.decryptStr(text1, KeyType.PublicKey);
        System.out.println("公钥解密: " + text2);
	}
代码语言:javascript
复制
私钥加密: Ty5YGXHUajKHtlmQ7yGYJtc39Rjb3IvSIm7WWg4+Ge6u8MDeJ3TLYZokgBbAMZRcZBZ8bIWiou12+KxoW8moRwke4PlWVipgwhC2l6qo7WtTMiwnGh+0+B8wnY3OySFK4ZeOMQFgYuiTL2uZqofLXyNzwID7GKCfWI6EL29wtbE=
公钥解密: 这是原文

对称算法的特点就是

随便先用谁,然后用另一个解

一般来说,有意义的信息,加密传递

建议使用 公钥加密,私钥解密

这种方法,确保信息只能由你指定的对象收到

另一种反过来的做法,

私钥加密,公钥解密

用于数字签名场合

证明这个签名是某人做的

因为只有他有他自己的私钥

摘要加密

摘要加密是单向的

能加不能解

主要目的是生成特征码

常用算法包括 md5,sha 等等

代码语言:javascript
复制
class Test3 {
	@Test
	void test() {
		String text = "这是原文";
		String text1 = DigestUtil.md5Hex(text);
        System.out.println(text1);
	}
}

输出结果是:

代码语言:javascript
复制
531ffeed49bb13a6cf93049cc1e5ee53

比如系统密码,一般采用摘要加密

假设我的密码是 123456,

md5之后变成了 e10adc3949ba59abbe56e057f20f883e

如果有人能看到数据库表,

哪怕他找到了我的密码 e10adc3949ba59abbe56e057f20f883e,

也不知道我实际的密码是123456

当登陆时,会对用户输入的密码再次md5,

如果结果还等于e10adc3949ba59abbe56e057f20f883e,

就表示输对了密码。


摘要加密的特点是

输出结果位数是固定的

比如上面列出的md5,加密后永远是固定长度

他的特点主要是:

代码语言:javascript
复制
输入不同,加密结果就不同

输入相同,加密结果一定相同

现在一般md5用的也少,主要是长度和复杂度

一般使用 sha256 或 sha512

他可以做简化验证

比如,我有一个文档,大小为 100M

如何验证他的内容发生串改

我们不可能拿2个100M的文件,逐个字节比较

这时,只要对2者分别做摘要运算,

得到一个短的字符串,对他们比较就可以了

这种验证的特点是:我知道你对和不对,但我不知道哪错了

总结

三种方法中,一般使用原则是

  1. 速度快,用对称
  2. 安全高/数据少,用非对称
  3. 用于验证对错,保留特征码,用摘要

大家可以试试,顺便安利一下hutool,

非常优秀的工具包

之后我们会专文介绍国密算法

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 加密方式
  • 对称加密
  • 非对称加密
  • 摘要加密
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档