1、杂谈
1、古典密码学
核心:替换法/位移法(凯撒加密)
破解方法:频率分析法,即研究字母和字母组合在文本中出现的概率。
2、近代密码学:
恩尼格玛机
被图灵破解
3、现代密码学:
1、散列函数:散列函数,也叫杂凑函数、摘要函数或哈希函数,可将任意长度的消息经过运算,变成固定长度数值,常见的有MD5
、SHA-1
、SHA256
,多应用在文件校验,数字签名中。
2、对此密码:对称密码应用了相同的加密密钥和解密密钥。对称密码分为:序列密码(流密码),分组密码(块密码)两种。流密码是对信息流中的每一个元素(一个字母或一个比特)作为基本的处理单元进行加密,块密码是先对信息流分块,再对每一块分别加密。
3、非对称密码:非对称密码有两支密钥,公钥(publickey)和私钥(privatekey),加密和解密运算使用的密钥不同。用公钥对原文进行加密后,需要由私钥进行解密;用私钥对原文进行加密后(此时一般称为签名),需要由公钥进行解密(此时一般称为验签)。公钥可以公开的,大家使用公钥对信息进行加密,再发送给私钥的持有者,私钥持有者使用私钥对信息进行解密,获得信息原文。因为私钥只有单一人持有,因此不用担心被他人解密获取信息原文。
2、常见加密模式(部分代码可直接复用)
1、单密钥加密:DES加密/AES加密
/** * @Description DES对称加密标准,单密钥加密 * @Author lx * @Date 2020/12/15 16:05 **/ public class DESDemo { public static void main(String[] args) throws Exception { //1.原文 String str = "下雪了"; System.out.println("原文:"+str); //2.key,DES的加密key必须是8位 String key ="12345678"; /** * AES和DES区别 * 1.DES比AES原始 * 2.DES密钥必须是8位数组 :mQRnQ+PLy3s5e6I2UFZGNW0cmZX2Z+ON * 3.AES密钥是16位密钥,其他代码几乎一样 :dydk4yvmMOchvAyXCKuPIgf+U13Kia5U3w53KFaKnyE= * 4.加密后的结果不一样 */ //3.算法,DES String algorithm = "DES"; //4.形式,模式 String transformation = "DES"; //5.获取加密对象 Cipher cipher = Cipher.getInstance(transformation); //6.指定密钥规则 //传入2个参数:1.密钥key,必须是8位字节数组;2.alogrithm 算法; //返回SecretKeySpec,密钥规则 // SecretKeyFactory factory = SecretKeyFactory.getInstance(key.getBytes(), algorithm); SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), algorithm); /** * 对加密进行初始化 * 传入2 个参数:1.模式,加密模式或者解密模式;2.加密规则 */ cipher.init(Cipher.ENCRYPT_MODE,secretKeySpec); //进行加密 byte[] bytes = cipher.doFinal(str.getBytes()); /** * 打印密文,直接打印乱码,需要用base64进行转换 * 注意:tostring和new string()区别 * 1.tostring():用于打印hash地址或者对象 * 2.new String():用于打印密文 */ System.out.println("未进行base64转码前加密结果:"+new String(bytes)); /** * base64.encode()对密文进行解码,便于查看 * base64.decode()对密文进行转码,转回成密文 */ System.out.println("进行base64转码后的加密结果:"+Base64.encode(bytes)); } }
运行结果:
原文:下雪了 未进行base64转码前加密结果:r�w��5���T�.�Am� 进行base64转码后的加密结果:csB3veA1qbGUVIoujUFthw==
2、AES/EDS解密
public class AesDemo { // DES加密算法,key的大小必须是8个字节 public static void main(String[] args) throws Exception { String input ="原文"; // AES加密算法,比较高级,所以key的大小必须是16个字节 String key = "1234567812345678"; String transformation = "AES"; // 9PQXVUIhaaQ= // 指定获取密钥的算法 String algorithm = "AES"; // 先测试加密,然后在测试解密 String encryptDES = encryptDES(input, key, transformation, algorithm); System.out.println("加密:" + encryptDES); String s = dncryptDES(encryptDES, key, transformation, algorithm); System.out.println("解密:" + s); } /** * 使用DES加密数据 * * @param input : 原文 * @param key : 密钥(DES,密钥的长度必须是8个字节) * @param transformation : 获取Cipher对象的算法 * @param algorithm : 获取密钥的算法 * @return : 密文 * @throws Exception */ private static String encryptDES(String input, String key, String transformation, String algorithm) throws Exception { // 获取加密对象 Cipher cipher = Cipher.getInstance(transformation); // 创建加密规则 // 第一个参数key的字节 // 第二个参数表示加密算法 SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm); // ENCRYPT_MODE:加密模式 // DECRYPT_MODE: 解密模式 // 初始化加密模式和算法 cipher.init(Cipher.ENCRYPT_MODE,sks); // 加密 byte[] bytes = cipher.doFinal(input.getBytes()); // 输出加密后的数据 String encode = Base64.encode(bytes); return encode; } /** * 使用DES解密 * * @param input : 密文 * @param key : 密钥 * @param transformation : 获取Cipher对象的算法 * @param algorithm : 获取密钥的算法 * @throws Exception * @return: 原文 */ private static String dncryptDES(String input, String key, String transformation, String algorithm) throws Exception { // 1,获取Cipher对象 Cipher cipher = Cipher.getInstance(transformation); // 指定密钥规则 SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm); cipher.init(Cipher.DECRYPT_MODE, sks); // 3. 解密 byte[] bytes = cipher.doFinal(Base64.decode(input)); return new String(bytes); } }
运行结果:
加密:TUuxDy0h/Rx1KwhMFXEnog==
解密:原文
3、加密模式:ECB/CBC
4、填充模式
3、消息摘要
/** * @Description 消息摘要 * @Author lx * @Date 2020/12/15 16:38 **/ public class DigestDemo { public static void main(String[] args) throws Exception { /** * 获取消息摘要 */ //1.原文 String str = "消息摘要"; //2.算法,MD5 String algorithm ="MD5"; String MD5 = getDigest(str, algorithm); System.out.println("MD5--->"+MD5); /** * 使用不同算法,生成消息数字摘要 */ algorithm ="SHA-1"; String SHA1 = getDigest(str, algorithm); System.out.println("SHA1--->"+SHA1); algorithm ="SHA-256"; String SHA256 = getDigest(str, algorithm); System.out.println("SHA256--->"+SHA256); //7b0feaed8d7291cbaf1139e85ec6318da6a18972ae5faf3d6dbefe5b21bbd7bd //7b0feaed8d7291cbaf1139e85ec6318da6a18972ae5faf3d6dbefe5b21bbd7bd //889a828bfcf3c9f7adf862c9cd051d5b961be308 // System.out.println(new String(digest)); // // System.out.println(Base64.encode(digest)); // //323070dd4582eda3825fec99ee0887db //323070dd4582eda3825fec99ee887db //323070dd4582eda3825fec99ee0887db } /** * 因base64转码结果和直接用网页MD5生成密文不同 * 生成数字摘要,传入不同算法,不使用base64进行转码,直接使用16进制进行转换, * 字符位数不足2的在高位补0 * @param str 原文 * @param algorithm 算法 * @return * @throws NoSuchAlgorithmException */ private static String getDigest(String str, String algorithm) throws NoSuchAlgorithmException { //3.获取数字摘要对象 MessageDigest messageDigest = MessageDigest.getInstance(algorithm); //4.获取数字摘要的字节数组 byte[] digest = messageDigest.digest(str.getBytes()); StringBuffer sb = new StringBuffer(); for (byte b : digest) { //将每个字节转成16进制 String s = Integer.toHexString(b & 0xff); //直接打印会少2位 //如果生成的字符只有一个,在高位补0 if(s.length()==1){ s = "0"+s; } sb.append(s); } // System.out.println(sb); return sb.toString(); } }
运行结果:
MD5--->323070dd4582eda3825fec99ee0887db SHA1--->889a828bfcf3c9f7adf862c9cd051d5b961be308 SHA256--->7b0feaed8d7291cbaf1139e85ec6318da6a18972ae5faf3d6dbefe5b21bbd7bd