数据安全系列5:常用的对称算法浅析

常用的算法介绍

常用的算法JAVA实现

jce及其它开源包介绍、对比

传送门

数据安全系列1:开篇

数据安全系列2:单向散列函数概念

数据安全系列3:密码技术概述

数据安全系列4:密码技术的应用-接口调用的身份识别

时代有浪潮,就有退去的时候

在我的博客文章里面,其中绝大多数都是专注于技术探讨,间或一些设计或项目管理的分享。极少有关于个人看法、感悟之类。不过在上一篇数据安全系列3:密码技术概述里面谈到了如何应对工作的压力:

打工的终极目标是跳槽或者变成合伙人

 所以这里就想再写几句,权当"吐槽"几句!

这是最好的时代,也是最坏的时代

“这是最好的时代,也是最坏的时代”,英国文学家狄更斯曾这样描述工业革命发生后的世界。这句话放在现在亦不为过,彼时彼刻恰如此时此刻!记得14年住在杭州出租屋的时候,偶然看到同学买的《浪潮之巅》被序里面的几句话所吸引:

因为,虽然对于一个公司来讲,赶上一次浪潮不能保证它长盛不衰;但是,对于一个人来讲,一生赶上这样一次浪潮就足够了。对于一个弄潮的年轻人来讲,最幸运的莫过于赶上一波大潮。

--------引自《浪潮之巅》

里面的内容:微软、google、IBM这些超一流公司的前世今生介绍;浏览器大战,客厅争夺、微机之争商战风起云涌;还有对于投资银行、华尔街、硅谷的角色解读;关于亚太地区,尤其是阿里巴巴的精准预测,深深打动了当时那个年轻人,迷茫又坚定的投入了软件开发行业!在后续的几年中也确实赶上了移动互联网这个浪潮。

近一百多年来,总有一些公司很幸运地、有意识或者无意识地站在技术革命的浪尖之上。
一旦处在了那个位置,即使不做任何事,也可以随着波浪顺顺当当地向前漂个十年甚至更长
的时间。在这十几年间,它们代表着科技的浪潮,直到下一波浪潮的来临。

--------也引自《浪潮之巅》

诚如作者所说,浪潮袭来整个行业生机勃勃、浪尖之上一切看起来皆有可为。但是浪潮退祛之后到底是继续繁荣、还是平稳衰退作者却并为给出预测。甚至哀鸿遍野都殊为可知,而且一切并非妄语!做为身在其中的从业者感受更是提前感受到了"寒冬"

经济的冲击

俗话说“春江水暖鸭告知”。首当其冲的是大家普遍会觉得找工作变难了,大家也不敢随便跳槽了:

  • 很多公司都开始裁员了,无论是所谓的老牌BAT、新晋的PATB这些互联网;还是国企所属
  • 很多公司都严查考勤了,包括宣称"不打卡"的互联网;也开始到期不续约了,变相裁员
  • 更重要的是降薪,不论是砍福利、通过绩效手段劝退、还是整体降薪

而这一切其实最终都是经济这只大手带来的影响,企业打响了"降本增效"的大旗,砍向了里面的每一个人。被迫离开的人有的找工作时间普遍变长了,GAP几个月屡见不鲜;还有的人可能就真的彻底告别这个行业了,离职=失业不再是一句自我调侃。

一个在阿里呆了5年的同事,怀着"闯一番"的念头主动离职,加入了做在线教育的创业公司,没过多久由于众所周知的原因失业了,从此在本地再也找不到合适的工作,最后异地去了苏州上班。

AI的冲击

除了外部环境冲击,行业内也在悄然起了变化。这2年AI的兴起其实对IT行业也有影响,这点不得不承认。比如我感觉AI对话的很多问题,就算是计算机专业领域,也回答的非常合理甚至更为全面(请放心这里不是打广告也不卖课...)。等哪一天AI真的能写业务逻辑,那就是真正的程序员革命,公司也不需要招这么多程序员了,这与前2年挂羊头狗肉的低代码有本质区别,意味着AI可能真的要来临了!

山重水复疑无路,柳暗花明又一村

十年前我刚加入这一行的时候,就听过35岁危机,当时大家对这种观点更多的是一种自嘲。时过境迁再回首人已中年。不过借用一句古话,天塌下来还有高个子顶着,就不要再散播焦虑,让我们言归正传,看看常用的密码算法吧

密码学家的工具箱

章节名称的由来

前面推荐了作为一本入门书的《图解密码技术_百度百科 》,里面提出了密码学家的工具箱这个说法,也通过讨论得到了下面这个图:

常见的密码算法

有一点要明确下来的就是所讨论的加密算法最终目的,是为了解决信息安全所面临的问题:

机密性

我们为了保证信息的机密性,也就是不让别人看到信息或者看到了也"看不懂"所以引入了加密的这种方法,而出于安全性与性能的区别,又有很多不同的加密算法。其中最常见的就是对称加密!

对称加密算法
对称加密基本概念

对称加密是指加密和解密使用相同密钥的加密算法。发送方使用密钥将明文加密成密文,接收方使用相同的密钥将密文解密回明文。对称加密算法通常计算效率高,适合大量数据的加密。

加密过程

解密过程

DES

先来看看DES算法:

DES全称为Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法,1977年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS),并授权在非密级政府通信中使用,随后该算法在国际上广泛流传开来。需要注意的是,在某些文献中,作为算法的DES称为数据加密算法(Data Encryption Algorithm,DEA),已与作为标准的DES区分开来。

----------------------引自百度百科DES

它出现的时期比较早,由于现在计算机技术的发展已不再推荐使用,因为可以被暴力破解了。它的加密过程如下:

图片来源《 图解密码技术_百度百科 》

 看一个用JAVA生成的例子:

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class DESExample {
    private static final String ALGORITHM = "DES";
    
    public static String encrypt(String key, String value) throws Exception {
        // DES需要8字节的密钥
        if (key.length() < 8) {
            throw new IllegalArgumentException("Key must be at least 8 characters for DES");
        }
        
        SecretKeySpec secretKey = new SecretKeySpec(key.substring(0, 8).getBytes("UTF-8"), ALGORITHM);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        byte[] encryptedBytes = cipher.doFinal(value.getBytes());
        return Base64.getEncoder().encodeToString(encryptedBytes);
    }
    
    public static String decrypt(String key, String encryptedValue) throws Exception {
        SecretKeySpec secretKey = new SecretKeySpec(key.substring(0, 8).getBytes("UTF-8"), ALGORITHM);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        byte[] decodedBytes = Base64.getDecoder().decode(encryptedValue);
        byte[] decryptedBytes = cipher.doFinal(decodedBytes);
        return new String(decryptedBytes);
    }
    
    public static void main(String[] args) {
        try {
            String key = "mySecret"; // 8字节的密钥
            String original = "Hello, World!";
            
            String encrypted = encrypt(key, original);
            System.out.println("Encrypted: " + encrypted);
            
            String decrypted = decrypt(key, encrypted);
            System.out.println("Decrypted: " + decrypted);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

上面的示例代码可以完整的展现DES的加解密过程,但是要强调几点:

  • DES 已被 NIST 淘汰(2005 年),切勿用于新项目
  • 密钥为什么需要 8 字节?DES 算法要求密钥必须是 8 字节(64 位)(实际有效密钥为 56 位,8 位用于奇偶校验)
3DES

接着看看看看3DES算法:

3DES(即Triple DES)是DES向AES过渡的加密算法,它使用3条56位的密钥对数据进行三次加密。是DES的一个更安全的变形。它以DES为基本模块,通过组合分组方法设计出分组加密算法。比起最初的DES,3DES更为安全。

现在由于DES已经可以在限时的时间内破解,因此三重DES就是开发出来替代DES的一种分组密码。它的加密过程如下:

图片来源《 图解密码技术_百度百科 》

看一个用JAVA生成的例子: 

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class TripleDESExample {
    private static final String ALGORITHM = "DESede";
    
    public static String encrypt(String key, String value) throws Exception {
        // 3DES需要24字节的密钥
        if (key.length() < 24) {
            throw new IllegalArgumentException("Key must be at least 24 characters for 3DES");
        }
        
        SecretKeySpec secretKey = new SecretKeySpec(key.substring(0, 24).getBytes("UTF-8"), ALGORITHM);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        byte[] encryptedBytes = cipher.doFinal(value.getBytes());
        return Base64.getEncoder().encodeToString(encryptedBytes);
    }
    
    public static String decrypt(String key, String encryptedValue) throws Exception {
        SecretKeySpec secretKey = new SecretKeySpec(key.substring(0, 24).getBytes("UTF-8"), ALGORITHM);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        byte[] decodedBytes = Base64.getDecoder().decode(encryptedValue);
        byte[] decryptedBytes = cipher.doFinal(decodedBytes);
        return new String(decryptedBytes);
    }
    
    public static void main(String[] args) {
        try {
            String key = "mySecretKey12345678901234"; // 24字节的密钥
            String original = "Hello, World!";
            
            String encrypted = encrypt(key, original);
            System.out.println("Encrypted: " + encrypted);
            
            String decrypted = decrypt(key, encrypted);
            System.out.println("Decrypted: " + decrypted);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
AES

接着看看AES算法:

密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。

这个标准用来替代原先的DES(Data Encryption Standard),已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院 (NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准。2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一

 ----------------------引自百度百科AES

由于AES的设计目标就是要解决DES的安全性的问题,所以在没有特殊的要求场景(比如旧程序兼容性问题)都建议使用AES。它的加密过程如下:

图解密码技术_百度百科

看一个用JAVA生成的例子: 

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.util.Base64;

public class AESUtil {
    private static final String ALGORITHM = "AES";
    private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";
    private static final int IV_SIZE = 16; // 128位IV
    
    /**
     * AES加密(使用CBC模式)
     */
    public static String encrypt(String key, String value) throws Exception {
        // 生成随机IV
        byte[] iv = new byte[IV_SIZE];
        new SecureRandom().nextBytes(iv);
        
        SecretKeySpec secretKey = new SecretKeySpec(
            key.getBytes("UTF-8"), ALGORITHM);
        IvParameterSpec ivSpec = new IvParameterSpec(iv);
        
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
        
        byte[] encrypted = cipher.doFinal(value.getBytes());
        
        // 将IV和加密数据合并
        byte[] encryptedIVAndText = new byte[iv.length + encrypted.length];
        System.arraycopy(iv, 0, encryptedIVAndText, 0, iv.length);
        System.arraycopy(encrypted, 0, encryptedIVAndText, iv.length, encrypted.length);
        
        return Base64.getEncoder().encodeToString(encryptedIVAndText);
    }
    
    /**
     * AES解密
     */
    public static String decrypt(String key, String encryptedValue) throws Exception {
        byte[] ivAndEncrypted = Base64.getDecoder().decode(encryptedValue);
        
        // 提取IV
        byte[] iv = new byte[IV_SIZE];
        System.arraycopy(ivAndEncrypted, 0, iv, 0, iv.length);
        
        // 提取加密数据
        byte[] encrypted = new byte[ivAndEncrypted.length - IV_SIZE];
        System.arraycopy(ivAndEncrypted, IV_SIZE, encrypted, 0, encrypted.length);
        
        SecretKeySpec secretKey = new SecretKeySpec(
            key.getBytes("UTF-8"), ALGORITHM);
        IvParameterSpec ivSpec = new IvParameterSpec(iv);
        
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
        
        byte[] decrypted = cipher.doFinal(encrypted);
        return new String(decrypted);
    }
    
    public static void main(String[] args) {
        try {
            String key = "MySecretKey12345"; // 16字节用于AES-128
            String original = "敏感数据需要加密";
            
            String encrypted = encrypt(key, original);
            System.out.println("加密结果: " + encrypted);
            
            String decrypted = decrypt(key, encrypted);
            System.out.println("解密结果: " + decrypted);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
SM4

    SM4(原名SMS4)是中国国家密码管理局发布的商用密码算法标准(GB/T 37033-2018),属于对称分组密码算法。其分组长度和密钥长度均为128位,与AES(Advanced Encryption Standard)类似,但属于中国自主知识产权的加密算法。以下是SM4的基本原理及Java实现的详细说明。

    SM4属于国密范畴,它有其自身的特点,尤其是在信创的大背景下,使得它的应用会越来越广泛:

    一、SM4算法概述

    1. 分组长度:128位(16字节)
    2. 密钥长度:128位(16字节)
    3. 加密轮数:32轮
    4. 工作模式:支持ECB(电子密码本)、CBC(密码块链接)、CFB(反馈模式)、OFB(输出反馈模式)等。
    5. 应用场景:适用于需要国密合规的场景,如金融、政务、物联网等。

    Java标准库(JCE)默认不支持SM4,需通过第三方库(如 Bouncy Castle)实现。

    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcprov-jdk15on</artifactId>
        <version>1.70</version> <!-- 使用最新版本 -->
    </dependency>

    看一个用JAVA生成的例子: 

    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    import javax.crypto.Cipher;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
    import java.security.Security;
    
    public class SM4Example {
        static {
            // 注册Bouncy Castle提供者
            Security.addProvider(new BouncyCastleProvider());
        }
    
        // SM4加密
        public static byte[] encrypt(byte[] data, byte[] key) throws Exception {
            SecretKey secretKey = new SecretKeySpec(key, "SM4");
            Cipher cipher = Cipher.getInstance("SM4/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            return cipher.doFinal(data);
        }
    
        // SM4解密
        public static byte[] decrypt(byte[] cipherText, byte[] key) throws Exception {
            SecretKey secretKey = new SecretKeySpec(key, "SM4");
            Cipher cipher = Cipher.getInstance("SM4/ECB/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            return cipher.doFinal(cipherText);
        }
    
        public static void main(String[] args) throws Exception {
            String plainText = "Hello, SM4!";
            byte[] key = "1234567890abcdef".getBytes(); // 16字节密钥
    
            // 加密
            byte[] encrypted = encrypt(plainText.getBytes(), key);
            System.out.println("加密结果(Base64): " + java.util.Base64.getEncoder().encodeToString(encrypted));
    
            // 解密
            byte[] decrypted = decrypt(encrypted, key);
            System.out.println("解密结果: " + new String(decrypted));
        }
    }
    
    分析对比

    上面介绍了几种常用、主流的算法,下面表格列出了相应的特点:

    算法密钥长度块大小状态特点
    DES56位64位已淘汰早期标准,易被暴力破解
    3DES112/168位64位逐渐淘汰DES的三重应用,安全性提高但效率低
    AES128/192/256位128位推荐使用目前最广泛使用的标准,安全高效
    SM4128位128位推荐使用适用于需要国密合规的场景,如金融、政务等

    除此以外还一些不是很常用的算法:

    Blowfish32-448位64位可用速度快,但块大小较小
    RC440-2048位流密码不推荐曾广泛使用,现发现多处漏洞

    这里就不展开了,有兴趣的可以直接链接查看。

    还有一个值得关注的算法是Gooble开发的ChaCha20

    ChaCha20-Poly1305是Google所采用的一种新式加密算法,性能强大,在CPU为精简指令集ARM平台上尤为显著(ARM v8前效果较明显),在同等配置的手机中表现是AES的4倍(ARM v8之后加入了AES指令,所以在这些平台上的设备,AES方式反而比chacha20-Poly1305方式更快,性能更好),可减少加密解密所产生的数据量进而可以改善用户体验,减少等待时间,节省电池寿命等。

    ChaCha20-Poly1305是由ChaCha20流密码和Poly1305消息认证码(MAC)结合的一种应用在互联网安全协议中的认证加密算法,由Google公司率先在Andriod移动平台中的Chrome中代替RC4使用。

    由于其算法精简、安全性强、兼容性强等特点,目前Google致力于全面将其在移动端推广

    模式介绍

    从上面的对比讨论可以看出,现在推荐的加密算法要么是AES、要么是SM4这两种。它们的代码也极其类似:

    // AES
    private static final String ALGORITHM = "AES";
        private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";
        private static final int IV_SIZE = 16; // 128位IV
    
    SecretKey secretKey = new SecretKeySpec(key.getBytes("UTF-8"), ALGORITHM);
            IvParameterSpec ivSpec = new IvParameterSpec(iv);
    
            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
    // SM4
    SecretKey secretKey = new SecretKeySpec(key, "SM4");
            Cipher cipher = Cipher.getInstance("SM4/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);

    这里的格式:AES/CBC/PKCS5Padding是指定算法的参数格式,表示为

    算法/工作模式/填充模式
    工作模式
    图片来源《 图解密码技术_百度百科 》

    这里列个表格来对比看看:

    模式全称特点安全性推荐使用
    ECBElectronic Codebook相同明文→相同密文❌ 极不安全绝不使用
    CBCCipher Block Chaining需要IV,错误传播⚠️ 需谨慎实现传统系统可用
    CTRCounter类似流密码,可并行✅ 良好适合流式处理
    GCMGalois/Counter Mode认证加密,带完整性最佳现代系统首选
    写在最后

    关于数据安全虽然整理了好几篇文章。不过说实话,我觉得对于算法还是没有入门,最多是使用上初窥门径(尝试看了一下算法源码,就是看不懂。。。),所以建议大家有兴趣还是先看看作为一本入门书的《图解密码技术_百度百科 》虽然看了第2遍了,还是常看常新!

    至于非对称算法,我们下篇文章再来仔细讨论

    附录:JCA与JCE关系

     因为它们底层都是使用的同一个加密算法框架Java Cryptography Architecture (JCA) :

    JCA是Java平台的加密体系基础架构,它是一个框架性设计而非具体实现:

    • 本质:一套服务提供者接口(SPI)和应用程序接口(API)的集合
    • 核心包java.securityjava.security.certjava.security.interfaces
    • 设计目标
      • 提供统一的加密服务访问方式
      • 支持算法独立性(应用程序不依赖特定算法)
      • 支持Provider机制(可插拔的加密实现)
      • 遵循"一次编写,到处运行"的Java原则

    而它对应的代码就在jce.jar包里面,是对jca的扩展:

    JCE是JCA的官方扩展,专注于提供对称加密、非对称加密和密钥协商功能:

    • 本质:JCA框架的扩展规范
    • 核心包javax.cryptojavax.crypto.interfacesjavax.crypto.spec
    • 关键类CipherKeyGeneratorSecretKeyFactoryMac

    3. jce.jar

    jce.jar是JCE规范的具体实现文件

    • 位置$JAVA_HOME/jre/lib/jce.jar
    • 内容:SunJCE Provider的实现代码
    • 作用:提供JCE API的具体算法实现
    • 历史:最初是独立下载的扩展包,现已成为标准JDK的一部分

    详细关系解析

    JCA是基础架构,JCE是其扩展

    • JCA:提供基础加密服务框架,包括:

      • 消息摘要(MD5, SHA)
      • 数字签名(DSA, RSA)
      • 密钥生成(KeyPairGenerator)
      • 安全随机数生成(SecureRandom)
    • JCE:在JCA基础上扩展了:

      • 对称加密(AES, DES, 3DES)
      • 非对称加密(RSA加密/解密)
      • 密钥协商(Diffie-Hellman)
      • 消息认证码(HMAC)

    关键区别:JCA主要关注"验证"(如数字签名),而JCE关注"保密"(如数据加密)

    评论
    成就一亿技术人!
    拼手气红包6.0元
    还能输入1000个字符
     
    红包 添加红包
    表情包 插入表情
     条评论被折叠 查看
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值