各大加密算法对比(原理、性能、安全、运用)

文章详细比较了对称加密(如DES、AES)和非对称加密(如RSA)的原理,以及MD5、SHA-256的不可逆特性。实测结果显示AES和MD5性能相近,RSA相对较慢。还探讨了算法的安全性和适用场景,如MD5用于校验,AES用于加密传输。

原理

按加密可逆可以分为:加密可逆算法和加密不可逆算法。加密可逆算法又可以分为:对称加密和非对称加密。

1、加密不可逆算法:一般采用hash算法加密,其原理一般是将原文长度补位成64的倍数,接着初始化固定长度的缓存值,经过循环与分组后的明文进行 与操作、或操作、非操作、异或操作 改变缓存值,最后的缓存值就是密文。该算法加密得到的密文是没有解密算法的,是不可逆的。常见的不可逆算法有:MD5,SHA、SM3。

2、对称加密算法:加密解密密钥相同,明文加密成密文后,密文是可以通过解密恢复原文的,其原理一般是将原文分组,经过 原文位置调换、密钥生成、原文与密钥进行轮函数(异或运算、多项式运算等)处理、分组单元进行字典表置换或位置换 等操作,将明文转化成密文。一般解密使用逆函数、返位移或字典表操作可以将密文转化为原文。常见的对称加密算法有:DES、3DES、AES、SM4、RC4、TEA、IDEA。

3、非对称加密算法:加密解密的密钥不同,其原理一般是用复杂的数学难题来做公钥私钥。即是获取了公钥,也很难计算出私钥。而且这些组成公钥私钥的数字在特定公式下,能将原文(O)和密文©相互转化。比如RSA的公钥(E,N)和私钥(D,N)都由两个数组成,但能通过公式 C= mod N以及 O= mod N 相互转化密文和原文。常见的非对称加密算法有:RSA、ECC。

性能

原理分析:非对称采用原文与缓存值hash函数循环进行与或非等操作,返回值也小,速度应该是最快的。而对称加密需要按位或分组与密钥进行轮函数处理,速度应该慢于不可逆加密算法。非对称加密算法由于计算量巨大,应该是最慢的。

实测:本次实测以Hutool工具的加密算法为准,测试md5、sha-256、des、aes、rsa的性能,分别测试它们在不同数量级原文下的加密速度。测试代码如下:

package com.longqi.bootsecurity;

import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.crypto.symmetric.AES;
import cn.hutool.crypto.symmetric.DES;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import org.apache.commons.lang3.RandomStringUtils;

import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.List;

/**
 * @author LQ
 * @projectName boot-integration
 * @description: 加密测试
 * @date 2023/3/2 20:35
 */
public class Application {

    public static void main(String[] args) {
        int len = 100;
        // 准备11个原文,每个算法第一次运行时间不记录,运行时间为后10次的平均值。
        List<String> dataList = new ArrayList<>(16);
        for (int i=0;i<11;i++){
            dataList.add(RandomStringUtils.randomAlphanumeric(len));
        }
        System.out.println("原文长度:"+len);
        System.out.println("原文:"+dataList.get(0));
        // 不可逆加密
        md5(dataList);
        sha256(dataList);
        // 对称加密
        des(dataList);
        aes(dataList);
        // 非对称加密
        rsa(dataList);
    }


    public static void md5(List<String> dataList){
        String encode = SecureUtil.md5(dataList.get(0));
        long startTime = System.nanoTime();
        for(int i=1;i<11;i++){
            SecureUtil.md5(dataList.get(i));
        }
        long endTime = System.nanoTime();
        System.out.println("MD5耗时:"+(endTime-startTime)/10+"ns");
        System.out.println("MD5密文:"+encode);
    }

    public static void sha256(List<String> dataList){
        String encode = SecureUtil.sha256(dataList.get(0));
        long startTime = System.nanoTime();
        for(int i=1;i<11;i++){
            SecureUtil.sha256(dataList.get(i));
        }
        long endTime = System.nanoTime();
        System.out.println("SHA256耗时:"+(endTime-startTime)/10+"ns");
        System.out.println("SHA256密文:"+encode);
    }

    public static void des(List<String> dataList){
        byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.DES.getValue()).getEncoded();
        System.out.println("DES密钥:"+ HexUtil.encodeHexStr(key));
        DES des = SecureUtil.des(key);
        String encode = des.encryptHex(dataList.get(0));
        long startTime = System.nanoTime();
        for(int i=1;i<11;i++){
            des.encryptHex(dataList.get(i));
        }
        long endTime = System.nanoTime();
        System.out.println("DES耗时:"+(endTime-startTime)/10+"ns");
        System.out.println("DES密文:"+encode);
    }

    public static void aes(List<String> dataList){
        byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.AES.getValue()).getEncoded();
        System.out.println("AES密钥:"+ HexUtil.encodeHexStr(key));
        AES aes = SecureUtil.aes(key);
        String encode = aes.encryptHex(dataList.get(0));
        long startTime = System.nanoTime();
        for(int i=1;i<11;i++){
            aes.encryptHex(dataList.get(i));
        }
        long endTime = System.nanoTime();
        System.out.println("AES耗时:"+(endTime-startTime)/10+"ns");
        System.out.println("AES密文:"+encode);
    }

    public static void rsa(List<String> dataList){
        KeyPair pair = SecureUtil.generateKeyPair("RSA");
        PrivateKey privateKey = pair.getPrivate();
        PublicKey publicKey = pair.getPublic();
        System.out.println("RSA公钥:"+ publicKey.toString());
        System.out.println("RSA私钥:"+ privateKey.toString());
        RSA rsa = SecureUtil.rsa(privateKey.getEncoded(),publicKey.getEncoded());
        String encode = rsa.encryptHex(dataList.get(0), KeyType.PublicKey);
        long startTime = System.nanoTime();
        for(int i=1;i<11;i++){
            rsa.encryptHex(dataList.get(i), KeyType.PublicKey);
        }
        long endTime = System.nanoTime();
        System.out.println("RSA耗时:"+(endTime-startTime)/10+"ns");
        System.out.println("RSA密文:"+encode);
    }


}

运行会打印 原文、密文、耗时,密钥,其中的耗时第一次耗时不计算,以各算法后10次平均值打印具体如下:

1、以下是10次加密长度100字符各加密算法的平均耗时(纳秒):

加密100长度字符,在处理同批次明文,密钥确定的情况下:AES性能最强、接着是MD5和RSA性能次之,最后是SHA-256与DES性能最差。当然,差距不大,最好与最坏也就3倍差距,最慢需要0.23毫秒。这里的字符空间大小为:100字节(Byte),即约为0.09765KB,最慢需要0.2毫秒。

2、以下是10次加密长度1000000的字符各加密算法的平均耗时(纳秒):

可以看出:AES与MD5性能最强,两者相差很小,然后是SHA-256和DES性能次之,最后RSA性能最慢,和别的算法差距明显。这里的字符空间大小为:1000000字节,即约为976.56KB,最慢需要0.2秒。

3、以下是10次加密长度100000000的字符各加密算法的平均耗时(豪秒),这里时间耗费较长,只统计5次:

可以看出:AES与MD5性能最强,两者相差很小,然后是SHA-256和DES性能次之,最后RSA性能最慢,和别的算法差距明显。这里的字符空间大小为:100000000字节,即约为95.37MB,最慢需要24秒。

总结:性能排名:AES、MD5、SHA-256、DES、RSA。具体分析如下:

AES:凭借分组整体替换,每次循环处理更多原文数据,即使需要密钥参与运算,还是能和MD5速度处于同一水平线上甚至略胜一点点。

MD5:虽然哈希算法里每次是3个32位字的原文与缓存值进行运算,虽然不需要密钥参与运算,但性能并没有与AES拉开差距,主要原因是每次处理的原文没有AES多。

SHA-256:和MD5相比,每次处理的字数不变,缓存值更多,算法更复杂,比MD5慢是正常的。

DES:由于没有分组处理,仅仅是按位替换,每次循环处理的原文数据少,再加上密钥需要参与运算,比不可逆算法慢是正常的。

RSA:基本符合预期,数据量少计算量小,凭借最简洁的运算,耗费时间少,但数据量一大,运算量大,就被拉开明显差距了。

安全

这里先讨论下各算法根据密文得到原文的加密或解密次数。

MD5:该算法不可逆,破解只能靠穷举法,而且原文越大,时间越长些,密文输出128bit,范围是2的128次方,即最长需要穷举原文加密次才能破解。

SHA-256:与MD5类似,破解只能靠穷举法,密文输出256bit,范围是2的256次方,即最长需要穷举原文加密次才能破解。

DES:该算法密钥只有56位有效,有密文后解密速度恒定,需要穷举密钥解密次才能破解。

AES:该算法密钥有128、192、256位,再只有密文的情况下,这三种密钥都得穷举,最长得解密才破解。

RSA:该算法密钥有512、1024、2048位,光穷举密钥就得运行次,再加上该算法加密解密耗时长,破解异常困难。

以上算法安全性是:RSA>SHA-256=>AES>MD5>DES。

运用

MD5:由于速度快,雪崩效应,返回值固定。常用于文件或数据校验。

SHA-256:由于速度比MD5稍慢,雪崩效应,返回值固定,且安全性远大于MD5,也不担心密钥暴露。可用于文件或数据校验,保存密码。

DES:该算法已淘汰,速度慢,安全性差,现在基本没有运用了。

AES:由于速度快,算法可逆,安全性高(不暴露密钥的话),可用于加密传输信息。

RSA:由于安全性高,算法可逆,有公钥和私钥,但大量数据下加密解密慢,可用于验签、加密传输少量信息。

黑客学习资源推荐

最后给大家分享一份全套的网络安全学习资料,给那些想学习 网络安全的小伙伴们一点帮助!

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

😝朋友们如果有需要的话,可以V扫描下方二维码联系领取~

1️⃣零基础入门
学习路线

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

image

需要详细路线图的,下面获取

路线对应学习视频

同时每个成长路线对应的板块都有配套的视频提供:

image-20231025112050764

2️⃣视频配套工具&国内外网安书籍、文档
工具

######视频

image1

######书籍

image2

资源较为敏感,未展示全面,需要的下面获取

### 3️⃣Python面试集锦

面试资料

在这里插入图片描述在这里插入图片描述

简历模板

在这里插入图片描述

因篇幅有限,资料较为敏感仅展示部分资料,添加上方即可获取👆

------ 🙇‍♂️ 本文转自网络,如有侵权,请联系删除 🙇‍♂️ ------

<think>好的,我现在需要帮助用户解决在Java中使用Hutool库实现AES加密并将结果转为Base64编码的问题。用户已经提供了之前的对话和相关的引用,我需要综合这些信息来给出正确的示例代码。 首先,回顾用户之前的提问,他们想要通过用户账号生成16位的MD5作为AES的IV,并且现在的问题是关于如何用Hutool进行AES加密后转成Base64编码。用户可能已经了解了一些基本的Hutool用法,但需要具体的代码示例。 接下来,查看用户提供的引用内容。引用[1]和引用[5]提到了Hutool的AES加密示例,其中引用[1]中的代码使用了SecureUtil.aes来创建AES对象,并展示了加密为Hex和Base64的方法。引用[5]则提到了依赖的版本和Hutool的AES类。这些信息很重要,因为用户需要正确的依赖配置和代码结构。 用户现在的需求是生成示例代码,所以需要确保代码正确且符合最佳实践。根据之前的回答,用户可能需要生成动态密钥和IV,或者使用固定密钥。考虑到安全性,动态生成更可靠,但用户可能也需要固定密钥的示例,所以应该提供两种方案。 在引用[1]中,示例代码使用了SecureUtil.generateKey来生成密钥,这符合动态生成密钥的做法。但用户可能需要指定密钥的情况,比如从字符串生成,这时候需要确保密钥长度符合AES的要求(128、192、256位)。Hutool的SecureUtil.md5可以生成128位的密钥,而SecureUtil.generateKey(256)则生成256位的密钥,这里需要注意密钥长度的处理。 另外,用户提到需要将加密结果转为Base64编码。在Hutool中,aes.encryptBase64方法可以直接返回Base64字符串,这比手动转换更方便,如引用[1]中的示例所示。所以代码中应该直接使用这个方法。 还要注意加密模式和填充方式。用户之前的示例中使用了CBC模式,但默认情况下Hutool的AES可能使用ECB模式,所以在代码中需要明确指定模式,尤其是当需要IV的时候。但当前用户的问题没有提到IV,可能只需要基本的AES加密,所以可能需要区分是否有IV的情况。 根据引用[2],用户可能对不同的加密模式有所了解,比如CBC需要IV,而ECB不需要。所以示例代码中应该包括这两种情况,但用户当前的问题可能更关注Base64编码,因此需要明确说明不同模式下的处理。 现在需要整合这些信息,编写出正确的示例代码。首先,确保依赖正确,如引用[3]和引用[5]中的hutool-crypto版本。然后,生成密钥,可以选择动态生成或从字符串生成。加密时选择模式,如ECB或CBC,并处理IV(如果有的话)。最后,使用encryptBase64方法输出结果。 可能的疑问点:用户是否需要指定模式?如果用户没有指定,默认是什么?根据Hutool文档,默认是ECB模式,但为了代码清晰,最好显式指定。此外,密钥生成的方式是否正确,是否需要处理密钥长度的问题,比如当使用字符串作为密钥时,如何确保长度符合要求。 总结步骤: 1. 添加Hutool依赖。 2. 生成或定义密钥。 3. 创建AES对象,指定模式和填充。 4. 加密数据并转换为Base64。 5. 提供解密示例(可选,但用户可能需要)。 需要确保代码示例中的密钥生成符合AES要求,比如使用SecureUtil.generateKey生成指定长度的密钥,或者使用SecureUtil.md5生成128位的密钥。如果用户希望从字符串生成密钥,可能需要使用合适的哈希函数或调整字符串长度。 最后,检查是否需要处理IV,但根据用户当前的问题,可能不需要,除非特别提到。不过之前的回答中用户涉及到了IV,所以可能需要包含相关示例,但当前问题更关注加密和Base64转换,所以可能分开处理。 最终,给出两种示例:一种是动态生成密钥,另一种是使用固定字符串密钥,并说明注意事项,如密钥长度、模式选择等。确保代码简洁,并参考之前的引用内容,特别是引用[1]和引用[5]中的代码结构。</think>### **Java Hutool AES加密转Base64完整示例** ```java import cn.hutool.crypto.SecureUtil; import cn.hutool.crypto.symmetric.AES; public class AesBase64Example { public static void main(String[] args) { // 1. 明文数据 String plaintext = "Hello, AES + Base64!"; // 2. 生成AES密钥(256位) byte[] key = SecureUtil.generateKey("AES", 256).getEncoded(); // 3. 创建AES实例(默认ECB模式/PKCS5Padding) AES aes = SecureUtil.aes(key); // 4. 加密并转为Base64 String encryptedBase64 = aes.encryptBase64(plaintext); System.out.println("Base64密文: " + encryptedBase64); // 5. 解密验证 String decrypted = aes.decryptStr(encryptedBase64); System.out.println("解密结果: " + decrypted); } } ``` --- ### **关键点说明** 1. **密钥生成** - `SecureUtil.generateKey("AES", 256)` 生成符合AES-256标准的随机密钥[^1] - 若需固定密钥,可直接指定字节数组(长度需为16/24/32字节): ```java byte[] key = "YourFixedKey123456".getBytes(); // 需满足长度要求 ``` 2. **模式与填充** - 默认使用`ECB`模式 + `PKCS5Padding`填充[^1] - 指定CBC模式需额外提供IV(16字节): ```java AES aes = new AES(Mode.CBC, Padding.PKCS5Padding, key, ivBytes); ``` 3. **Base64编码** - `encryptBase64()` 方法直接返回Base64字符串[^1] - 等价于手动转换: ```java byte[] encryptedBytes = aes.encrypt(plaintext); String base64 = Base64.encode(encryptedBytes); ``` --- ### **增强版(含动态IV的CBC模式)** ```java // 生成随机IV(16字节) byte[] iv = SecureUtil.generateKey(16).getEncoded(); // 创建AES实例(CBC模式) AES aes = new AES(Mode.CBC, Padding.PKCS5Padding, key, iv); // 加密(IV需随密文存储) String encryptedWithIv = HexUtil.encodeHexStr(iv) + ":" + aes.encryptBase64(plaintext); ``` --- ### **注意事项** 1. **密钥安全** - 避免硬编码密钥,推荐使用密钥管理系统(如Vault)[^3] 2. **模式选择** - ECB模式简单但安全性低,CBC/CTR/GCM模式更安全[^4] 3. **依赖版本** - 确保使用Hutool 5.7.15+(Maven依赖见引用[3][^3]) --- ### **相关问题** 1. 如何解决`Invalid AES key length`异常? 2. AES-GCM模式在Hutool中如何实现? 3. Base64编码和Hex编码有何区别? 4. 如何验证加密后的数据完整性? 5. 为什么要避免重复使用相同的IV?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值