密码学
概述
- 密码学:主要是研究编制密码和破译密码得学科
- 密码学的主要目的:研究如何隐藏信息并且把信息传递出去得的一个学科
- 应用:网络安全、信息安全、区块链等学科的基础
- 古典密码学 -> 类似古代史
- 近代密码学 -> 类似近代史
- 现代密码学 -> 类似现代史
古典密码学
核心原理:替换法、移位法
- 替换法
- 就是使用固定的信息,将原文替换成密文如:hello,将b替换为a,将e替换为v,将l替换为t,将o替换为y,那么hello加密之后就是:avtty
- 第一种:单表替换
- 原文和密文使用的是同一张表
- 如:将原文替换成密文如:hello,将b替换为a,将e替换为v,将l替换为t,将o替换为y,那么hello加密之后就是:avtty
- 第二种:多表替换
- 原文和密文不是同一张表
- 如,表1:abcde - swtrp,表2:abcde - chfhk,表3:abcde - jftou
- 原文:bee 密钥:312
- 加密之后:fpk
- 移位法
- 是按照字母,在字母表上面的位置,进行移动
- 凯撒加密
- 例如:abcde - cdefg 向后移动2位
- 破解方式
- 频度分析法破译密码,在不知道加密规则的前提下,进行破译密码
- 通过概率论研究字母或者字母组合在文本中出现的频率
- 密码中的频率和英文字母的频率,进行匹配,就可以解密
- 如何设置密码才比较安全
- 密码不要太常见
- 各个应用软件里面的密码不要设置一样 - 撞库(破解一个软件的密码,去匹配所有软件的密码,成为撞库)
- 在设置密码的时候,可以加一些特殊的标记,和网站相关的标记方便记忆
- 古代密码
- 武则天破解 ”青鹅“ 造反案 拆字加密
- 凯撒加密
- 解密凯撒加密:使用频度分析法进行猜测破解
近代密码学
核心原理:替换法、移位法
- 恩尼格玛密码机(二战)
- 核心使用的是移位法和替换法
- 被人工智能之父图灵破解
现代密码学
散列函数
- MD5
- SHA-1
- SHA-256
- SHA512
对称加密
- 核心原理
- 使用的加密方式和解密方式是同一把密钥
- 流加密 如:123345,对1、2、3、3、4、5 分别加密,然后再将其拼接起来
- 块解密 如:123345,对123、345 一整块解密,然后拼接成密文
- DES加密解密
- 特点
- 加密速度快,可以加密大文件
- 密文不可逆,一旦密钥文件泄漏,就会导致数据泄漏
- 加密后编码表找不到相应的字符,出现乱码
- 一般结合Base64使用
- 密钥key必须是8个字节
- Base64
- 不是加密算法,是可读性算法
- 目的不是为了保护数据,目的是为了可读性
- base64是由64个字符组成 大写A - Z,小写 a - z,数字 0 - 9,两个符合 + 和 /
- base58:一般用在于比特币上
- 和base64的区别,没有数字0,也没有字母o,没有大写字母 I 也没有小写字母 i 没有 + 和 /
- base64原理
- 是三个字节为一组,一个字节8位 ,一共就是24位,base64 把三个字节转换为4组,每组6位,一个字节应该是8位,缺少2位,在高位补齐,高位补0
- 这样做的好处,base64取后面的6位,可以把base64控制到 0 ~ 63 之间
- 11 1111 => 32 + 16 + 8 + 4 + 2 + 1 = 63
- 在base64里面,需要设置一共是三个字节为一组,如果在输出的时候,不够三个字节,就要使用 = 进行补齐
- AES加密解密
- 密钥必须是16个字节
- toString()和new String()的原理和区别
- new String:如果在使用编码解码,使用 new String,根据参数,字节数组,使用Java虚拟机默认编码格式,会对这个字节数组进行decode。找到对应的字符 (转码的时候使用)
- toString: 实际上调用的的Object里面的toString方法,一般的Object的toString方法,返回的是哈希值。做对象打印,使用toString,或者得到地址的时候
- 加密模式
- ECB(电子密码本)
- 把一段文本进行分拆加密,使用同一个key,分别进行加密,然后组合到一起
- 优点:可以并行处理数据
- 缺点:同样的原文生成的是同样的密文,不能很好的保护数据
- 同时加密,原文的一样的,加密出来的密文也是一样的
- CBC(密码块连接)
- 每一个明文块会给前一个密文块进行异或后,再进行加密
- 优点:同样的原文生成的密文不一样
- 缺点:串行处理数据
- ECB(电子密码本)
- 填充模式
- NoPadding(不填充)
- 在DES加密算法下,要求原文长度必须是8byte的整倍数
- 在AES加密算法下,要求原文长度必须是16bytes的整数倍
- PKCS5padding
- 数据块大小为8位,不够就补足
- NoPadding(不填充)
- 消息摘要
- 又称为数字摘要
- 它是唯一一个对应一个消息或者文本的固定长度的值,由一个单向hash加密函数对消息进行作用而产生
- 使用数字摘要生成的值是不可以篡改的,为了保证文件或者值得安全
- 特点
- 无论输入得消息有多长,计算出来的消息摘要的长度总是固定的,例如使用MD5算法摘要的消息有128个比特位,使用SHA-1算法摘要消息最终有160比特位的输出
- 只要输入的消息不同,对其进行摘要之后的消息也比不相同,但是相同的输入会有相同的输出,消息摘要是单向、不可逆的
非对称加密
- 非对称加密的特点
- 有两把密钥,使用公钥加密,必须使用私钥解密。或者是私钥加密,必须使用公钥解密
- 公钥和私钥是一对,叫做密钥对
- RSA算法和ECC算法
- RSA 以下是代码实现
public class RSADemo {
public static void main(String[] args) throws Exception {
// 创建密钥对
String algorithm = "RSA";
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
// 生成密钥对
KeyPair keyPair = keyPairGenerator.generateKeyPair();
// 生成私钥
PrivateKey aPrivate = keyPair.getPrivate();
// 生成公钥
PublicKey aPublic = keyPair.getPublic();
// 获取私钥的字节数组
byte[] privateEncodedBytes = aPrivate.getEncoded();
// 获取公钥的字节数组
byte[] publicEncodedBytes = aPublic.getEncoded();
// 使用base64 编码
String privateEncoded = Base64.encode(privateEncodedBytes);
String publicEncoded = Base64.encode(publicEncodedBytes);
System.out.println(privateEncoded);
System.out.println(publicEncoded);
}
}
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALrXZxGPW9JihIKLX2FgeJ6HYy8z
DQYNkKyj8crctM6AQW11XijRG997FNocgR2rfwX3vwbwJj/3zsQ1MHIPtGAuttlJZzlx9egqCqfe
adL+dTVj3FGyrNR2RjKcOl4dXgkqbs0c8mjJyyJzytxaMajp6pQTjbCcoenxSTEKMdZfAgMBAAEC
gYBUyh3G9UTZM8Yoq/EL8siqQIx9RfCaF5vZDMlUo1YWBFQsxT+GzGaWw3dSB+98NHB/l8+D6YWi
L+YQWobyrDfRSnE6TZQkoTGiiGUveJR2GhfDYKLURmUyrlqovCW1gxoTN5W8Jc1mroq6CKzsjEwf
lO/qNWVn5MPNLqictiZ5EQJBAPVbN/HQUJgLaZLvQXcBMymu7qC7yS4xJHPbI9UIkbHBBs5xasDF
CJQk5tDyiiWcP+EmFAICcQYPOdnuYSeZ9xcCQQDC8loxaSZH9mSCQwFEIGRHV+weycKm0KK/uSVB
HAHDeaEJHaOtykwygQjLv7fyJN/9zBLgu7liiKbcIJY1FCf5AkAL6p1B+lsft1YuU757OCyy9pMS
bWxs+OgLVHZeD2d8GaLp/eowaKFtCInJVi5Ne1RC7CWGn3W71Jt7sS84zCqLAkATU3VPiq4J2kpS
g5P/jfqC/BtjXfsXEH3h5dfkoYMnPsqRHcgZNYHiS9p0YHg64B74iR+h+dpCA2wPTIe3kVz5AkEA
5mnK6UbCaqUeKZzjXLGLJ1JVhGCc9QvPWHO+dO7OfPUE7yzBbqMiwTEFCijSpLDi5+qrMpYAAUZh
U1e6F51ZJQ==
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC612cRj1vSYoSCi19hYHieh2MvMw0GDZCso/HK
3LTOgEFtdV4o0RvfexTaHIEdq38F978G8CY/987ENTByD7RgLrbZSWc5cfXoKgqn3mnS/nU1Y9xR
sqzUdkYynDpeHV4JKm7NHPJoycsic8rcWjGo6eqUE42wnKHp8UkxCjHWXwIDAQAB
- 私钥加密
public class RSADemo {
public static void main(String[] args) throws Exception {
// 创建密钥对
String algorithm = "RSA";
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
// 生成密钥对
KeyPair keyPair = keyPairGenerator.generateKeyPair();
// 生成私钥
PrivateKey aPrivate = keyPair.getPrivate();
// 生成公钥
PublicKey aPublic = keyPair.getPublic();
// 获取私钥的字节数组
byte[] privateEncodedBytes = aPrivate.getEncoded();
// 获取公钥的字节数组
byte[] publicEncodedBytes = aPublic.getEncoded();
// 使用base64 编码
String privateEncoded = Base64.encode(privateEncodedBytes);
String publicEncoded = Base64.encode(publicEncodedBytes);
// System.out.println(privateEncoded);
// System.out.println(publicEncoded);
// 创建加密对象
Cipher cipher = Cipher.getInstance(algorithm);
// 对加密初始化
// 加密的模式,第二个,使用那把要是加密
cipher.init(Cipher.ENCRYPT_MODE, aPrivate);
// 使用私钥加密
String input = "甜";
byte[] bytes = cipher.doFinal(input.getBytes());
System.out.println(Base64.encode(bytes));
}
}
J0q66D3VMqllATeqBAWlZ8nJVHGz0pbjq6G9lbvawp4kzQ581QYTsDA5FsRxJWehNAVO0LEQEQ/G
+bqNUD/aDr7NZruZpJ3mlGBq/tUrwjxe48v38Jcj1UFtl3N0UlJBCgCuvM09n7QPW31ouzxyRStS
dH/MqwR6ryrR+hwCEA8=
- 公钥解密
public class RSADemo {
public static void main(String[] args) throws Exception {
// 创建密钥对
String algorithm = "RSA";
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
// 生成密钥对
KeyPair keyPair = keyPairGenerator.generateKeyPair();
// 生成私钥
PrivateKey aPrivate = keyPair.getPrivate();
// 生成公钥
PublicKey aPublic = keyPair.getPublic();
// 获取私钥的字节数组
byte[] privateEncodedBytes = aPrivate.getEncoded();
// 获取公钥的字节数组
byte[] publicEncodedBytes = aPublic.getEncoded();
// 使用base64 编码
String privateEncoded = Base64.encode(privateEncodedBytes);
String publicEncoded = Base64.encode(publicEncodedBytes);
// System.out.println(privateEncoded);
// System.out.println(publicEncoded);
// 创建加密对象
Cipher cipher = Cipher.getInstance(algorithm);
// 对加密初始化
// 加密的模式,第二个,使用那把要是加密
cipher.init(Cipher.ENCRYPT_MODE, aPrivate);
// 使用私钥加密
String input = "甜";
byte[] bytes = cipher.doFinal(input.getBytes());
System.out.println(Base64.encode(bytes));
cipher.init(Cipher.DECRYPT_MODE,aPublic);
byte[] bytes1 = cipher.doFinal(bytes);
String s = new String(bytes1);
System.out.println(s);
}
}
b9C7sLQ86iO8sTDDeo0Shcw9EMiyKHmJax65Dw62r2JOcs5BtHu8IlcqD+OLNk6MHDtExxWAlbOb
g3x05dITki6jJpnCxrOcNU6GaJl+bAICQpV2IWkxDYVBjdoaeD0uCSlZVrC6pxzeiqyfa8VAR2Os
GckaJ59efM37UIjoP64=
甜
- 数字摘要
- 数字签名和数字整数
- 公钥数字签名,只有信息的发送者,才能产生别人无法伪造的一段数字串
- 数字证书
- keytool工具的使用
自己对于密码学不是很了解,这里只是做简单的介绍