当前位置: 首页 > news >正文

浅入浅出常见敏感数据处理的加密算法

对称加密算法

概念

对称加密算法是应用较早的加密算法,又称为共享密钥加密算法。在对称加密算法中,使用的密钥只有一个,发送接收双方都使用这个密钥对数据进行加密和解密。这就要求加密解密方事先都必须知道加密的密钥。

常见算法类型

列说明(对应算法表格)
列名含义说明
算法加密算法的名称(如AES、DES、3DES、SM1、SM4等)。
输出长度每次加密操作输出的密文块长度。通常等于分组长度。
分组长度加密算法每次处理数据的块大小(通常以比特或字节为单位,比如128位=16字节)。
密钥长度用于加密和解密的密钥长度(通常以比特为单位,某些算法支持多种密钥长度)。
工作模式算法的数据加密模式,如ECB(电子密码本模式)、CBC(密文分组链接)、CFB、OFB、CTR等。
填充模式明文不足一个分组长度时的填充方式,如PKCS#5、PKCS#7、ZeroPadding、NoPadding等。

块加密(分组加密):加密算法无法一次性处理过长的明文,这种情况下,将明文以密钥长度分割,分成一个个固定长度的数据组(块),分别进行加密然后组合,该方式即为块加密,也称分组加密。

算法
算法输出长度(位)输出长度(字节)分组长度秘钥长度(位)工作模式填充模式
AES128 bit16 bytes16 bytes128/192/256ECB/CBC/PCBC/CTR/…NoPadding/PKCS5Padding/PKCS7Padding/…
DES64 bit8 bytes8 bytes56 bitECB/CBC/PCBC/CTR/…NoPadding/PKCS5Padding/…
3DES64 bit8 bytes8 bytes112/168ECB/CBC/CFB/OFB/CTR/…NoPadding/ZeroPadding/PKCS7Padding/PKCS5Padding
SM1128 bit16 bytes16 bytes128 bitECB/CBC/CFB/OFB/CTR/…NoPadding/ZeroPadding/PKCS7Padding/PKCS5Padding
SM4128 bit16 bytes16 bytes128 bitECB/CBC/CFB/OFB/CTR/GCMISO10126Padding/NoPadding/ZeroPadding/PKCS7Padding/PKCS5Padding

使用案例

  1. 确定使用算法,以下示例:
  1. 算法名称:AES(推荐安全、广泛应用)
  2. 分组长度:128 bit(16字节)
  3. 密钥长度:128/192/256 bit(常用128)
  4. 常用模式:CBC(密文分组链接模式)
  5. 常用填充方案:PKCS7 / PKCS5
  1. 场景:

用户密码加密存储,假设有一个后台服务,需要将用户的敏感信息进行加密后存储到数据库。选择了AES-128-CBC算法。

  1. 代码演示
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;import java.security.SecureRandom;
import java.util.Base64;public class AESDemo {public static void main(String[] args) throws Exception {String plaintext = "Hello, Alice!";// 1. 生成128位密钥KeyGenerator keyGen = KeyGenerator.getInstance("AES");keyGen.init(128); // 128-bit AESSecretKey secretKey = keyGen.generateKey();byte[] keyBytes = secretKey.getEncoded();// 2. 生成IV(16字节)byte[] iv = new byte[16];new SecureRandom().nextBytes(iv);IvParameterSpec ivSpec = new IvParameterSpec(iv);// 3. 加密Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);byte[] ciphertextBytes = cipher.doFinal(plaintext.getBytes("UTF-8"));// 4. 输出加密结果(Base64 编码便于可视化和存储)String cipherBase64 = Base64.getEncoder().encodeToString(ciphertextBytes);String keyBase64 = Base64.getEncoder().encodeToString(keyBytes);String ivBase64 = Base64.getEncoder().encodeToString(iv);System.out.println("密文Base64: " + cipherBase64);System.out.println("密钥Base64: " + keyBase64);System.out.println("IV Base64: " + ivBase64);// 5. 解密Cipher cipher2 = Cipher.getInstance("AES/CBC/PKCS5Padding");cipher2.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);byte[] decryptedBytes = cipher2.doFinal(Base64.getDecoder().decode(cipherBase64));System.out.println("解密后: " + new String(decryptedBytes, "UTF-8"));}
}
  1. 核心步骤总结
  1. 选定算法(如AES-128-CBC),明确参数(密钥长度、分组长度)
  2. 准备密钥、IV:安全产生并保管
  3. 填充明文:保证数据块长度是分组长度整数倍
  4. 调用加密程序得到密文
  5. 存储密文/传输密文和必要的IV
  6. 实际使用时解密,获得原文

非对称加密算法

概念

非对称加密算法,又称为公开密钥加密算法。它需要两个密钥,一个称为公开密钥 (public key),即公钥,另一个称为私有密钥 (private key),即私钥。因为加密和解密使用的是两个不同的密钥,所以这种算法称为非对称加密算法。

常见类型

算法常用密钥长度(位)常见输出长度/密文长度*主要用途常用填充方式(如有)
RSA1024/2048/3072/4096与密钥长度对应(如2048位密钥加密输出256字节)加密、签名PKCS#1 v1.5, OAEP
ECC256/384/521与曲线及实现相关(如256位曲线密文约65-133字节)加密、签名通常无固定填充
SM2256密文约97字节(实现相关略有不同)加密、签名通常无固定填充
DH1024/2048/3072共享密钥长度与参数和实现相关密钥协商不适用(非加密用途)

输出长度/密文长度指一次加密输出的字节数,依密钥长度、填充、协议而异。DH不用于数据加密,输出为协商的共享密钥。

使用案例

  1. 原理简述
  1. 用户B生成RSA密钥对(公钥、私钥),将公钥发给用户A
  2. 用户A用公钥对消息加密并发送密文
  3. 用户B用私钥对密文解密,还原出原始消息
  1. 生成秘钥对java代码示例(java8及以上)
import java.security.*;public class GenerateRSAKeys {public static void main(String[] args) throws Exception {KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");keyGen.initialize(2048);KeyPair pair = keyGen.generateKeyPair();// 得到对象PublicKey pubKey = pair.getPublic();PrivateKey priKey = pair.getPrivate();System.out.println("公钥:" + java.util.Base64.getEncoder().encodeToString(pubKey.getEncoded()));System.out.println("私钥:" + java.util.Base64.getEncoder().encodeToString(priKey.getEncoded()));}
}
  1. 公钥加密,私钥解密
import java.security.*;
import javax.crypto.Cipher;
import java.util.Base64;public class RSADemo {public static void main(String[] args) throws Exception {// 1. 生成密钥对KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");keyGen.initialize(2048);KeyPair pair = keyGen.generateKeyPair();PublicKey publicKey = pair.getPublic();PrivateKey privateKey = pair.getPrivate();String plaintext = "这是一个敏感信息";// 2. 公钥加密Cipher encryptCipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);byte[] encryptedBytes = encryptCipher.doFinal(plaintext.getBytes("UTF-8"));String encryptedBase64 = Base64.getEncoder().encodeToString(encryptedBytes);System.out.println("密文(Base64):" + encryptedBase64);// 3. 私钥解密Cipher decryptCipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");decryptCipher.init(Cipher.DECRYPT_MODE, privateKey);byte[] decryptedBytes = decryptCipher.doFinal(Base64.getDecoder().decode(encryptedBase64));String decryptedText = new String(decryptedBytes, "UTF-8");System.out.println("解密后明文:" + decryptedText);}
}
  1. 小结
  1. 加密算法:RSA/ECB/OAEPWithSHA-256AndMGF1Padding(更安全,推荐)
  2. 明文与密文都是字节数组,密文经Base64编码方便显示和传输
  3. RSA适合小数据加密(通常克长度 < 200 字节),大数据需分段或用混合加密

摘要算法

概念

摘要算法通过哈希运算将原始数据转换为固定长度的摘要。MD5、SHA1等同样可用于摘要算法。摘要算法的特点是摘要值与原始数据密切相关,任何微小的数据变化都会导致摘要值的显著变化。摘要算法常用于检测数据的篡改和验证数据的完整性,但请注意,它并非一种加密算法,而是数据保护的一种辅助手段。

常见类型

算法输出长度(位)输出长度(字节)
MD512816
SHA-116020
SHA-25625632
SHA-38438448
SHA-51251264
SHA3-25625632
SM325632

主要用途

  1. 数字签名:对数据生成摘要,再对摘要签名,提高处理效率和安全。
  2. 文件完整性校验:如MD5校验文件传输和下载过程中的完整性。
  3. 密码存储:将密码哈希后存储,提升账号数据安全性。
  4. 数据去重和索引:快速查找和排重数据。

使用案例(SM3)

  1. 使用BouncyCastle库,因为标准Java暂不支持SM2。引入依赖:
<dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk18on</artifactId><version>1.78</version>
</dependency>
<dependency><groupId>org.bouncycastle</groupId><artifactId>bcpkix-jdk18on</artifactId><version>1.78</version>
</dependency>
  1. 生成SM2秘钥对
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.security.*;public class SM2KeyPairGenerator {public static KeyPair generateSM2KeyPair() throws Exception {Security.addProvider(new BouncyCastleProvider());KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("EC", "BC");keyPairGen.initialize(new ECGenParameterSpec("sm2p256v1"), new SecureRandom());return keyPairGen.generateKeyPair();}
}
  1. 电子合同签名
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.security.*;public class SM2SignerUtil {static {Security.addProvider(new BouncyCastleProvider());}// 签名public static byte[] sign(byte[] data, PrivateKey privateKey) throws Exception {Signature signature = Signature.getInstance("SM3withSM2", "BC");signature.initSign(privateKey);signature.update(data);return signature.sign();}
}
  1. 验签
public class SM2VerifyUtil {// 验签public static boolean verify(byte[] data, byte[] sig, PublicKey publicKey) throws Exception {Signature signature = Signature.getInstance("SM3withSM2", "BC");signature.initVerify(publicKey);signature.update(data);return signature.verify(sig);}
}
  1. 完整使用示例
import java.security.KeyPair;public class ContractSignDemo {public static void main(String[] args) throws Exception {// 1. 生成密钥对KeyPair keyPair = SM2KeyPairGenerator.generateSM2KeyPair();// 2. 模拟合同内容String contract = "甲方向乙方出售一台设备,金额10000元。";byte[] contractBytes = contract.getBytes("UTF-8");// 3. 签名byte[] signature = SM2SignerUtil.sign(contractBytes, keyPair.getPrivate());System.out.println("签名Base64: " + java.util.Base64.getEncoder().encodeToString(signature));// 4. 验签boolean isValid = SM2VerifyUtil.verify(contractBytes, signature, keyPair.getPublic());System.out.println("验签结果: " + isValid);// 5. 模拟合同被篡改byte[] tampered = "甲方向乙方出售一台设备,金额10001元。".getBytes("UTF-8");boolean isValid2 = SM2VerifyUtil.verify(tampered, signature, keyPair.getPublic());System.out.println("篡改内容验签: " + isValid2);}
}
  1. 输出示例
签名Base64: MCwCFHz...91AIFc...
验签结果: true
篡改内容验签: false
  1. 小结
  1. 签名方用私钥对合同内容生成数字签名
  2. 验签方用公钥对签名及原文进行校验,内容若被篡改则验签失败
  3. 适用于电子合同、票据、区块链等需要防篡改场景

问题记录(Q&A)

为什么加密用的是字节(byte[])?

  1. 本质:加密算法(如AES、DES等)本质只处理二进制数据(即一串0和1),在编程里表现为字节数组
  2. 不像文本:文本(如字符串)可以有各种编码(UTF-8、GBK等),而加密算法不认识什么字符,只认具体的字节
  3. 准确性:只有用字节,数据的原始位不会丢失,也能保证加密、解密的精准复原
举例
String s = "hello";
byte[] data = s.getBytes("UTF-8"); // 明确转成字节流
cipher.doFinal(data);              // 加密本质操作字节

什么是国密算法?

国密算法(中文全称为“国家商用密码算法”),通常指中国国家密码管理局(原国家密码管理局,现属于国家密码管理局和密码科学技术研究所双重管理)发布的一系列面向数据加密、信息安全的密码算法标准。这些算法广泛应用于金融、政务、通信等需要高安全等级的场合,特别是在国产化、合规与自主可控场景下,具有重要意义。

国密算法都有哪些?

算法名类别用途主要特点
SM1对称分组加密专用芯片/硬件加密算法未公开,仅限硬件实现,与AES类似,许可使用
SM2公钥密码算法数字签名、加密、密钥交换基于椭圆曲线ECC,自主研发,签名加密快于RSA,用于国密证书等
SM3杂凑(哈希)消息摘要、完整性校验输出256位,功能类似SHA-256,但原理不同,用于防篡改、签名摘要
SM4对称分组加密数据加密、VPN、无线通讯加密128位块长和密钥,公开标准,类似于AES,适合软硬件系统效率高
ZUC流加密算法3G/4G/5G移动通信空口加密面向无线通信设计,运算高效,适合实时加密
SM9标识密码算法基于标识的加解密、签名、协商以用户标识(如邮箱、手机号)为公钥,去中心化密钥管理,便于物联网等

国际算法都有哪些?

类型代表算法标准组织主要特点
对称加密AES、3DES、DESNIST、ISO加密解密效率高,适合大数据量加解密;实现简单
非对称加密RSA、ECC(ECDSA、ECDH)、DSANIST、ISO/IETF适合密钥交换、数字签名;密钥管理方便;安全性高
哈希算法SHA-1、SHA-2、SHA-3、MD5NIST、ISO单向运算、不可逆、防篡改,常用于完整性校验
流加密ChaCha20、RC4IETF加解密速度快,适合流式数据(如VPN、TLS)
消息认证码HMAC、CMACNIST、ISO基于哈希/分组加密,验证消息完整性和认证
密钥协商/交换DH、ECDHNIST、IETF用于安全地在线协商加密密钥,抵抗窃听和中间人攻击
密钥派生PBKDF2、HKDFIETF、NIST基于密码/主密钥安全地产生子密钥,增强密码抗攻击性

为什么很多时候展示、保存用16进制/BASE64?

  1. 人类不习惯直接看字节(看不到…也可能是乱码);加密后数据经常包含不可打印字符(比如0x00、0xA7、0xFF等),直接用字符串展现会乱码,写文件/网络传输也可能被破坏
  2. 16进制和BASE64是常用安全可见表示方法,16进制:每个字节用两位0-9A-F表示,占空间大些,但清晰直观
  3. Base64:把任意字节流转成ASCII字符,便于在网络、文本里安全传递和保存,比16进制更节省空间,实际用得更多
举例
byte[] b = { (byte)0xAB, (byte)0xCD, (byte)0x01}; 
String hex = javax.xml.bind.DatatypeConverter.printHexBinary(b); // "ABCD01"
String base64 = java.util.Base64.getEncoder().encodeToString(b); // "q80B"
实际场景
  1. 数据库保存密文:用16进制字符串或BASE64字符串,而不是原始字节
  2. 接口传输密文:通常也是Base64
  3. 加密函数参数:都要求字节流,不要直接用字符串
http://www.dtcms.com/a/338284.html

相关文章:

  • 如何在 Ubuntu 24.04 或 22.04 LTS 上安装 PowerShell
  • SHA-256 详解
  • UE5 批量编译蓝图技巧
  • Linux Miniconda安装教程与conda常用指令介绍
  • 区块链数字存证应用
  • 健身房预约系统SSM+Mybatis实现(四、登录页面+JWT+注销)
  • 【前端智能化】AG-UI实践及原理浅析
  • 决策树的笔记
  • steal tsoding‘s pastebeam code as go server
  • 芋道审批流配置流程表单超详细介绍
  • 15.web api 6
  • Unity 中控开发 多路串口服务器(一)
  • 【Goland】:数组与切片
  • 【25-cv-09352】Maradona 品牌维权,从球衣到周边全品类侵权高危
  • Jupyter 中实现交互式图表:ipywidgets 从入门到部署
  • 【数据集】全球大气监测计划(GAW)简介
  • 用户认证技术与HTTP协议
  • 基于pychrm工具的python读取 USB 摄像头(实时+保存录像+摄像头信息打印+镜像)—— OpenCV库
  • 【React Hooks】封装的艺术:如何编写高质量的 React 自-定义 Hooks
  • 【高等数学】第九章 多元函数微分法及其应用——第七节 方向导数与梯度
  • Localhost和127.0.0.1
  • 数据库原理及应用_数据库基础_第2章关系数据库标准语言SQL_数据类型表操作(定义、操作和修改)
  • 终极方案!lightRag/graphRag离线使用tiktoken持续报错SSLError,不改源码,彻底解决!
  • MySQL和HiveSQL在查询上的区别
  • 上网行为管理
  • 用户认证与应用控制技术
  • 深入浅出 SQL:数据库操作的核心语言完全指南
  • 【c++】从灵活到规范:自定义消息机制的设计与实践
  • day10(练习题)
  • Three.js 动画循环学习记录