加密与安全_探索对称加密算法

文章目录

  • 概述
  • 常用的对称加密算法
  • AES
    • ECB模式
    • CBC模式 (推荐)
    • ECB VS CBC
  • 附:AES工具类
  • 总结

在这里插入图片描述


概述

对称加密算法是一种加密技术,使用相同的密钥来进行加密和解密数据。在这种算法中,发送方使用密钥将明文(未加密的数据)转换为密文(加密的数据),而接收方使用相同的密钥将密文还原为明文。

对称加密算法的安全性依赖于密钥的保密性,因为任何持有相同密钥的人都能够解密数据。

常见的对称加密算法包括AES(高级加密标准)和DES(数据加密标准)。虽然对称加密算法在性能上通常比非对称加密算法更高效,但在密钥管理和分发方面存在挑战。

通俗来讲,可以这么理解: 对称加密算法就像是一把钥匙可以打开一个锁。在这里,你有一个钥匙(密钥),用它来锁住(加密)你的信息,然后你可以用同样的钥匙(密钥)来解锁(解密)它。这意味着发送方和接收方都使用相同的密钥来加密和解密信息。


常用的对称加密算法

常用的对称加密算法包括:

  1. AES(Advanced Encryption Standard):这是目前最常用的对称加密算法之一。它使用128、192或256位密钥来加密数据,并已被广泛采用于许多安全应用中。

  2. DES(Data Encryption Standard):虽然已被AES所取代,但仍然在一些遗留系统中使用。DES使用56位密钥对数据进行加密。

  3. 3DES(Triple Data Encryption Standard):3DES是DES的改进版本,它对数据应用三次DES算法,提高了安全性。但由于计算成本高昂,现在已经不太常用。

  4. Blowfish:这是一个可扩展的对称加密算法,可以使用变长密钥,从32位到448位。它曾经很流行,但由于一些安全性方面的考虑,现在使用较少。

  5. RC4(Rivest Cipher 4):尽管曾被广泛使用,但由于存在一些严重的安全漏洞,现在已经不建议使用。


从程序的角度看,所谓加密,就是这样一个函数,它接收密码和明文,然后输出密文:

secret = encrypt(key, message);

而解密则相反,它接收密码和密文,然后输出明文:

plain = decrypt(key, secret);  

从程序的角度看,所谓加密,就是这样一个函数,它接收密码和明文,然后输出密文:

secret = encrypt(key, message);

而解密则相反,它接收密码和密文,然后输出明文:

plain = decrypt(key, secret);  

加密和解密确实可以被视为类似上面的函数,但实际上,它们可能会更为复杂一些,尤其是在实现对称加密算法时。

在使用对称加密算法时,这两个函数通常被称为加密函数和解密函数。例如,在使用AES算法时,加密函数会接收密钥(key)和明文(message),然后输出密文(ciphertext)。而解密函数则接收密钥(key)和密文(ciphertext),然后输出明文(message)

算法密钥长度工作模式填充模式
AES128/192/256ECB/CBC/PCBC/CTR/…NoPadding/PKCS5Padding/PKCS7Padding/…
DES56/64ECB/CBC/PCBC/CTR/…NoPadding/PKCS5Padding/…

密钥长度直接决定加密强度,而工作模式和填充模式可以看成是对称加密算法的参数和格式选择。


这些对称加密算法在不同的场景中都有各自的优缺点,选择合适的算法取决于安全性需求、性能和应用环境。AES通常被认为是最安全和高效的对称加密算法之一,因此在许多情况下被首选使用


AES

AES算法是目前应用最广泛的加密算法。

ECB模式

先用ECB模式加密并解密. 代码如下

package com.artisan.securityalgjava.aes;

import java.security.*;
import java.util.Base64;

import javax.crypto.*;
import javax.crypto.spec.*;

/**
 * @author 小工匠
 * @version 1.0
 * @mark: show me the code , change the world
 */
public class AesECBExample {

    public static void main(String[] args) throws Exception {
        // 原文:
        String message = "Hello, Artisan!";
        System.out.println("Message: " + message);

        // 128位密钥 = 16 bytes Key:
        byte[] key = "1234567890abcdef".getBytes("UTF-8");

        // 加密:
        byte[] data = message.getBytes("UTF-8");
        byte[] encrypted = encrypt(key, data);
        System.out.println("Encrypted: " + Base64.getEncoder().encodeToString(encrypted));

        // 解密:
        byte[] decrypted = decrypt(key, encrypted);
        System.out.println("Decrypted: " + new String(decrypted, "UTF-8"));
    }

    // 加密方法
    public static byte[] encrypt(byte[] key, byte[] input) throws GeneralSecurityException {
        // 创建加密对象
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        // 创建密钥规范
        SecretKey keySpec = new SecretKeySpec(key, "AES");
        // 初始化加密对象
        cipher.init(Cipher.ENCRYPT_MODE, keySpec);
        // 执行加密操作
        return cipher.doFinal(input);
    }

    // 解密方法
    public static byte[] decrypt(byte[] key, byte[] input) throws GeneralSecurityException {
        // 创建解密对象
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        // 创建密钥规范
        SecretKey keySpec = new SecretKeySpec(key, "AES");
        // 初始化解密对象
        cipher.init(Cipher.DECRYPT_MODE, keySpec);
        // 执行解密操作
        return cipher.doFinal(input);
    }
}
    

ECB模式是最简单的AES加密模式,它只需要一个固定长度的密钥,固定的明文会生成固定的密文,这种一对一的加密方式会导致安全性降低

CBC模式 (推荐)

package com.artisan.securityalgjava.aes;

import java.security.*;
import java.util.Base64;

import javax.crypto.*;
import javax.crypto.spec.*;

/**
 * @author 小工匠
 * @version 1.0
 * @mark: show me the code , change the world
 * @desc: AES CBC模式加解密示例
 */
public class AesCBCExample {

    public static void main(String[] args) throws Exception {
        // 原文:
        String message = "Hello, Artisan!";
        System.out.println("Message: " + message);
        // 256位密钥 = 32 bytes Key:
        byte[] key = "1234567890abcdef1234567890abcdef".getBytes("UTF-8");
        // 加密:
        byte[] data = message.getBytes("UTF-8");
        byte[] encrypted = encrypt(key, data);
        System.out.println("Encrypted: " + Base64.getEncoder().encodeToString(encrypted));
        // 解密:
        byte[] decrypted = decrypt(key, encrypted);
        System.out.println("Decrypted: " + new String(decrypted, "UTF-8"));
    }

    /**
     * 加密
     * @param key
     * @param input
     * @return
     * @throws GeneralSecurityException
     */
    public static byte[] encrypt(byte[] key, byte[] input) throws GeneralSecurityException {
        // 创建AES加密器
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        // 创建密钥规范
        SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
        // CBC模式需要生成一个16 bytes的初始化向量
        SecureRandom sr = SecureRandom.getInstanceStrong();
        byte[] iv = sr.generateSeed(16);
        IvParameterSpec ivps = new IvParameterSpec(iv);
        // 初始化加密器
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivps);
        // 执行加密操作
        byte[] data = cipher.doFinal(input);
        // IV不需要保密,把IV和密文一起返回
        return join(iv, data);
    }

    /**
     * 解密
     * @param key
     * @param input
     * @return
     * @throws GeneralSecurityException
     */
    public static byte[] decrypt(byte[] key, byte[] input) throws GeneralSecurityException {
        // 把input分割成IV和密文
        byte[] iv = new byte[16];
        byte[] data = new byte[input.length - 16];
        System.arraycopy(input, 0, iv, 0, 16);
        System.arraycopy(input, 16, data, 0, data.length);
        // 创建AES解密器
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        // 创建密钥规范
        SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
        IvParameterSpec ivps = new IvParameterSpec(iv);
        // 初始化解密器
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivps);
        // 执行解密操作
        return cipher.doFinal(data);
    }

    /**
     * 拼接两个字节数组
     * @param bs1
     * @param bs2
     * @return
     */
    public static byte[] join(byte[] bs1, byte[] bs2) {
        byte[] r = new byte[bs1.length + bs2.length];
        System.arraycopy(bs1, 0, r, 0, bs1.length);
        System.arraycopy(bs2, 0, r, bs1.length, bs2.length);
        return r;
    }

}

CBC模式下,需要一个随机生成的16字节IV参数,必须使用SecureRandom生成。因为多了一个IvParameterSpec实例,因此,初始化方法需要调用Cipher的一个重载方法并传入IvParameterSpec

观察输出,可以发现每次生成的IV不同,密文也不同, 如下图所示

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

代码实现了AES CBC模式的加密和解密功能。在加密过程中,生成了一个16字节的初始化向量(IV),在解密时使用了这个IV来确保安全性。

因此,CBC模式,它需要一个随机数作为IV参数,这样对于同一份明文,每次生成的密文都不同 .


ECB VS CBC

AES有几种不同的模式,其中最常见的两种是ECB(Electronic Codebook)模式和CBC(Cipher Block Chaining)模式。

  1. ECB模式(电子密码本模式)
  • 特点
    • 将明文分成块,每个块使用相同的密钥进行加密。
    • 相同的明文块在加密后会得到相同的密文块。
    • 每个块的加密是独立的,不受其他块的影响。
  • 优点
    • 简单,容易并行化处理。
    • 适用于对称加密需求较简单的场景。
  • 缺点
    • 容易受到重放攻击的影响,因为相同的明文块会产生相同的密文块,没有隐藏明文块之间的关系。
    • 不适合加密大量数据或需要保护隐私的数据,因为无法隐藏明文块之间的模式。
  1. CBC模式(密码块链接模式)
  • 特点
    • 在加密前,会对明文块进行异或运算,并与前一个密文块进行混合,然后再加密。
    • 需要一个初始化向量(IV)来增加随机性,防止重放攻击。
    • 密文块的加密依赖于前一个密文块,因此密文块之间存在依赖关系。
  • 优点
    • 对于相同的明文块,使用不同的IV会产生不同的密文块,增加了安全性。
    • 可以加密大量数据,并且可以隐藏明文块之间的模式。
  • 缺点
    • 加密速度较ECB模式慢,因为需要依赖前一个密文块。
    • 不太容易并行化处理,因为每个块的加密都依赖于前一个块的加密结果。

综上所述,ECB模式简单快速,适合简单的加密需求,但安全性较差,不适合加密大量数据或需要保护隐私的数据。而CBC模式相对更安全,能够隐藏明文块之间的模式,适合加密大量数据或需要保护隐私的数据,但加密速度较慢


附:AES工具类

package com.artisan.securityalgjava.aes;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.security.spec.KeySpec;
import java.util.Arrays;
import java.util.Base64;

/**
 * @author 小工匠
 * @version 1.0
 * @mark: show me the code , change the world
 * @desc: AES加密解密工具类, 提供了AES加密解密的功能,使用了CBC模式和PBKDF2算法生成密钥
 */
public class AESCipher {

    /**
     * 密钥生成算法
     */
    private static final String SECRET_KEY_ALGORITHM = "PBKDF2WithHmacSHA256";
    /**
     * 加密算法
     */
    private static final String ENCRYPTION_ALGORITHM = "AES/CBC/PKCS5Padding";
    /**
     * 密钥长度
     */
    private static final int KEY_SIZE = 256;
    /**
     * 迭代次数
     */
    private static final int ITERATION_COUNT = 65536;
    /**
     * 初始化向量长度
     */
    private static final int IV_SIZE = 16;

    /**
     * 生成密钥
     *
     * @param password
     * @param salt
     * @return
     * @throws Exception
     */
    private static SecretKeySpec generateKey(String password, byte[] salt) throws Exception {
        SecretKeyFactory factory = SecretKeyFactory.getInstance(SECRET_KEY_ALGORITHM);
        KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, ITERATION_COUNT, KEY_SIZE);
        SecretKey tmp = factory.generateSecret(spec);
        return new SecretKeySpec(tmp.getEncoded(), "AES");
    }

    /**
     * 加密
     *
     * @param plaintext
     * @param password
     * @return
     * @throws Exception
     */
    public static String encrypt(String plaintext, String password) throws Exception {
        // 生成盐
        byte[] salt = new byte[16];
        // 生成初始化向量
        byte[] iv = new byte[IV_SIZE];
        byte[] encryptedBytes;

        // 生成盐和初始化向量
        SecureRandom random = new SecureRandom();
        random.nextBytes(salt);
        random.nextBytes(iv);

        // 生成密钥
        SecretKeySpec keySpec = generateKey(password, salt);
        Cipher cipher = Cipher.getInstance(ENCRYPTION_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(iv));

        // 执行加密操作
        encryptedBytes = cipher.doFinal(plaintext.getBytes());

        // 将盐、初始化向量和密文拼接并返回Base64编码字符串
        byte[] combined = new byte[salt.length + iv.length + encryptedBytes.length];
        System.arraycopy(salt, 0, combined, 0, salt.length);
        System.arraycopy(iv, 0, combined, salt.length, iv.length);
        System.arraycopy(encryptedBytes, 0, combined, salt.length + iv.length, encryptedBytes.length);

        return Base64.getEncoder().encodeToString(combined);
    }

    /**
     * 解密
     *
     * @param encryptedText
     * @param password
     * @return
     * @throws Exception
     */
    public static String decrypt(String encryptedText, String password) throws Exception {
        // 解析Base64编码字符串并分离盐、初始化向量和密文
        byte[] combined = Base64.getDecoder().decode(encryptedText);
        byte[] salt = Arrays.copyOfRange(combined, 0, 16);
        byte[] iv = Arrays.copyOfRange(combined, 16, 32);
        byte[] encryptedBytes = Arrays.copyOfRange(combined, 32, combined.length);

        // 生成密钥
        SecretKeySpec keySpec = generateKey(password, salt);
        Cipher cipher = Cipher.getInstance(ENCRYPTION_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(iv));

        // 执行解密操作并返回明文字符串
        byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
        return new String(decryptedBytes);
    }

    /**
     * 测试方法
     *
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        // 测试加密解密功能
        String encrypted = encrypt("组热么共和国的啥范德萨", "dddd");
        System.out.println("Encrypted: " + encrypted);
        String decrypted = decrypt(encrypted, "dddd");
        System.out.println("Decrypted: " + decrypted);
    }
}


总结

对称加密算法使用同一个密钥进行加密和解密,适用于需要高效加解密的场景。常见的对称加密算法包括DES、AES和3DES等。

对称加密算法使用同一个密钥进行加密和解密,常用的算法包括DES、AES和3DES等。

  • DES(Data Encryption Standard):DES是一种较早的对称加密算法,使用56位密钥进行加密和解密。由于密钥长度较短,DES已经不再被推荐使用,因为它容易受到穷举攻击。

  • AES(Advanced Encryption Standard):AES是目前广泛使用的对称加密算法之一。它使用128位、192位或256位密钥进行加密和解密。AES算法的安全性和性能较高,因此被广泛应用于各种安全领域。

  • 3DES(Triple Data Encryption Standard):3DES是对DES算法的改进,通过对数据应用三次DES算法来提高安全性。3DES使用的密钥长度为56位,因此它的安全性较DES提高了很多。但由于AES的出现和3DES的计算复杂性,3DES的使用逐渐减少。

密钥长度由算法设计决定。对于AES算法,它支持的密钥长度为128位、192位和256位。一般来说,密钥长度越长,加密的安全性越高,但同时也带来了更高的计算成本。

在使用对称加密算法时,需要指定以下参数:

  • 算法名称:即使用的加密算法,例如DES、AES和3DES等。
  • 工作模式:指定了加密算法在加密大块数据时的工作模式,常见的工作模式包括ECB、CBC、CFB、OFB等。
  • 填充模式:指定了在加密数据块大小不足时如何填充数据,常见的填充模式包括PKCS5Padding、NoPadding等。

选择合适的算法名称、工作模式和填充模式,可以根据具体的安全需求和性能要求进行调整。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/421345.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ApplicationContext为什么可以通过@Autowired 进行注入

一、分析 在我们日常开发中,有时我们会使用这样的的一段代码 app.getBean(User.class);那么这里的app就是ApplicationContext,如何获得这个ApplicatitionContext呢,无非就两种方式 实现ApplicationContextAware接口中的 setApplicationCon…

uniApp 调整小程序 单个/全部界面横屏展示效果

我们打开uni项目 小程序端运行 默认是竖着的一个效果 我们打开项目的 pages.json 给需要横屏的界面 的 style 属性 加上 "mp-weixin": {"pageOrientation": "landscape" }界面就横屏了 如果是要所有界面都横屏的话 就直接在pages.json 的 gl…

01、MongoDB -- 下载、安装、配置文件等配置 及 副本集配置

目录 MongoDB -- 下载、安装、配置 及 副本集配置启动命令启动 mongodb 的服务器(单机和副本集)启动单机模式的 mongodb 服务器启动副本集的 3 个副本节点(mongodb 服务器) 启动 mongodb 的客户端 MongoDB 下载MongoDB 安装1、解压…

2024全国水科技大会暨高氨氮废水厌氧氨氧化处理技术论坛(四)

一、会议背景 为积极应对“十四五”期间我国生态环境治理面临的挑战,加快生态环境科技创新,构建绿色技术创新体系,全面落实科学技术部、生态环境部等部委编制的《“十四五”生态环境领域科技创新专项规划》,积极落实省校合作&…

ABAP - SALV教程 01- 开篇:打开SALV的三种方式之一

关于SALV,这里参考巨佬江正军的文章讲解,在做SAP开发的遇到困难和瓶颈的时候,每每读到巨佬的文章都会灵感爆发、醍醐灌顶。https://www.cnblogs.com/jiangzhengjun/p/4291387.html 博主由于是由JAVA转型的ABAP开发,刚接触ABAP的时…

AI智能分析网关V4智慧环保/智慧垃圾站视频智能分析与监控方案

一、背景介绍 随着城市化进程的加速,垃圾处理问题日益受到人们的关注,传统的垃圾站管理方式已经无法满足现代社会的需求。针对当前垃圾站的监管需求,TSINGSEE青犀可基于旗下视频智能检测AI智能分析网关V4与安防监控视频综合管理系统EasyCVR平…

OGMN: Occlusion-guided Multi-task Network for Object Detection in UAV Images

OGMN: Occlusion-guided Multi-task Network for Object Detection in UAV Images用于无人机图像目标检测的遮挡引导多任务网络 摘要 物体之间的遮挡是无人机图像中物体检测中被忽视的挑战之一。由于无人机的高度和角度可变,无人机图像中的遮挡比自然场景中的遮挡…

Redis 之五:Redis 的主从复制

概念 主从复制,是指将一台 Redis 服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave);数据的复制是单向的,只能由主节点到从节点。 默认情况下,每台Redis服务器都是主节…

(二十一)devops持续集成开发——使用jenkins的Docker Pipeline插件完成docker项目的pipeline流水线发布

前言 本节内容会介绍如何使用Docker Pipeline插件实现docker项目的pipeline流水线项目的可持续化集成发布,在开始本节内容之前,我们要先搭建好docker环境,以及镜像本地存储仓库docker harbor,关于docker和docker harbor的安装,可查看作者往期博客内容。 正文 ①安装Doc…

【AIGC】“光影交织的恋曲:绝美情侣在蓝天下的深情互动“

外貌特征 (Physical Appearance):给远景镜头,这对情侣拥有出众的容貌和气质。男子身材挺拔,五官立体鲜明,阳光洒在他俊朗的脸庞上,更显英气逼人;女子则拥有一头柔顺亮丽的秀发,明亮的眼睛如同星…

动态规划课堂3-----简单多状态问题(买卖股票最佳时机)

目录 引入: 例题1:按摩师(打家劫舍I) 例题2:打家劫舍II 例题3:删除并获得点数 例题4:粉刷房子 例题5:买卖股票的最佳时机含冷冻 结语: 引入: 相信看到…

指针篇章-(1)

指针(1)学习流程 —————————————————————————————————————————————————————————————————————————————————————————————————————————————…

QML中表格中数据获取

1.在生成的动态表格中获取某格数据的内容 import QtQuick 2.15 import QtQuick.Window 2.15import QtQuick.Controls 2.0 import Qt.labs.qmlmodels 1.0 import QtQuick.Layouts 1.15Window {width: 640height: 480visible: truetitle: qsTr("Hello World")TableMod…

探索Redis 6.0的新特性

Redis(Remote Dictionary Server)是一个开源的内存中数据结构存储系统,通常被用作缓存、消息队列和实时数据处理等场景。它的简单性、高性能以及丰富的数据结构支持使其成为了众多开发者和企业的首选。在Redis 6.0版本中,引入了一…

ubuntu22.04 成功编译llvm和clang 3.4.0,及 bitcode 函数名示例,备忘

1, 获取llvm 仓库 从github上获取: $ git clone --recursive https://github.com/llvm/llvm-project.git 2, 检出 llvmorg-3.4.0 tag 针对llvm 3.4.0版本,检出 $ cd llvm-project $ git tag $ git checkout llvmorg-3.4.0 3, 配置并编译llvm 使用 M…

矩阵爆破逆向之条件断点的妙用

不知道你是否使用过IDA的条件断点呢?在IDA进阶使用中,它的很多功能都有大作用,比如:ida-trace来跟踪调用流程。同时IDA的断点功能也十分强大,配合IDA-python的输出语句能够大杀特杀! 那么本文就介绍一下这…

Siemens-NXUG二次开发-获取prt中体与类型、实体面与类型、实体边与类型、边上点的Tag标识[Python UF][20240302]

Siemens-NXUG二次开发-获取prt中体与类型、实体面与类型、实体边与类型、边上点的Tag标识[Python UF][20240302] 1.python uf函数1.1 NXOpen.UF.Obj.CycleObjsInPart1.2 NXOpen.UF.Obj.AskTypeAndSubtype1.3 NXOpen.UF.Modeling.AskBodyFaces1.4 NXOpen.UF.Modeling.AskFaceEdg…

韦东山嵌入式Liunx入门驱动开发四

文章目录 一、异常与中断的概念及处理流程1-1 中断的引入1-2 栈(1) CPU实现a ab的过程(2) 进程与线程 1-3 Linux系统对中断处理的演进1-4 Linux 中断系统中的重要数据结构(1) irq_desc 结构体(2) irqaction 结构体(3) irq_data 结构体(4) irq_domain 结构体(5) irq_domain 结构…

mac苹果电脑c盘满了如何清理内存?2024最新操作教程分享

苹果电脑用户经常会遇到麻烦:内置存储器(即C盘)空间不断缩小,电脑运行缓慢。在这种情况下,苹果电脑c盘满了怎么清理?如何有效清理和优化存储空间,提高计算机性能?成了一个重要的问题。今天,我想给大家详细介…

Unity 切换场景

场景切换前必须要将场景拖动到Build中 同步加载场景 using System.Collections; using System.Collections.Generic; //using UnityEditor.SearchService; using UnityEngine; // 场景管理 需要导入该类 using UnityEngine.SceneManagement;public class c3 : MonoBehaviour {…