news 2026/9/1 12:01:02

JAVA各种加密与解密方式

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JAVA各种加密与解密方式

一、凯撒加密

在密码学中,凯撒加密是一种最简单且最广为人知的加密技术。它是一种替换加密的技术,明文中的所有字母都在字母表上向后(或向前)按照一个固定数目进行偏移后被替换成密文。这个加密方法是以罗马共和时期恺撒的名字命名的,当年恺撒曾用此方法与其将军们进行联系。

public class caesarCipher { public static void main(String[] args) { String show = "ABCDEFGHIJKLMNOPQRSTUVWXYZ~~"; int key = 3; String ciphertext = encryption(show, key, true); System.out.println(ciphertext); String showText = encryption(ciphertext, key, false); System.out.println(showText); } /** * @param text 明文/密文 * @param key 位移 * @param mode 加密/解密 true/false * @return 密文/明文 */ private static String encryption(String text, int key, boolean mode) { char[] chars = text.toCharArray(); StringBuffer sb = new StringBuffer(); for (char aChar : chars) { int a = mode ? aChar + key : aChar - key; char newa = (char) a; sb.append(newa); } return sb.toString(); } }

明文字母表:ABCDEFGHIJKLMNOPQRSTUVWXYZ~~

密文字母表:DEFGHIJKLMNOPQRSTUVWXYZ[\]

注意:当字符的ASCII码+偏移量>127,密文转化出来会乱码,~(波浪号):126+3=129

二、Base64

Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。

base64 : A-Z a-z 0-9 + /

Base64要求把每三个8Bit的字节转换为四个6Bit的字节(3*8 = 4*6 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节,也就是说,转换后的字符串理论上将要比原来的长1/3。

import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException; import com.sun.org.apache.xml.internal.security.utils.Base64; import java.nio.charset.StandardCharsets; public class base64Demo { public static void main(String[] args) throws Base64DecodingException { //MQ== 一个字节补两个= System.out.println(Base64.encode("1".getBytes(StandardCharsets.UTF_8))); //MTE= 两个字节补一个= System.out.println(Base64.encode("11".getBytes(StandardCharsets.UTF_8))); //MTEx System.out.println(Base64.encode("111".getBytes(StandardCharsets.UTF_8))); //解密11 System.out.println(new String(Base64.decode("MTE="))); } }

三、信息摘要算法(MD5 或 SHA)

信息摘要是安全的单向哈希函数,它接收任意大小的数据,并输出固定长度的哈希值。

import com.alibaba.fastjson.JSON; import com.sun.org.apache.xml.internal.security.utils.Base64; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.HashMap; //信息摘要是安全的单向哈希函数,它接收任意大小的数据,并输出固定长度的哈希值。 public class DigestDemo { /** * @param input 明文 * @param algorithm 算法 MD5 | sha-1 SHA-256 | * @return 密文 Base64 & Hex */ private static String toHexOrBase64(String input, String algorithm) throws NoSuchAlgorithmException { MessageDigest digest = MessageDigest.getInstance(algorithm); byte[] digest1 = digest.digest(input.getBytes(StandardCharsets.UTF_8)); String base64 = Base64.encode(digest1); StringBuffer haxValue = new StringBuffer(); for (byte b : digest1) { //0xff是16进制数,这个刚好8位都是1的二进制数,而且转成int类型的时候,高位会补0 int val = ((int) b) & 0xff;//只取得低八位 //在&正数byte值的话,对数值不会有改变 在&负数数byte值的话,对数值前面补位的1会变成0, if (val < 16) { haxValue.append("0");//位数不够,高位补0 } haxValue.append(Integer.toHexString(val)); } HashMap<String, String> DigestMap = new HashMap<>(); DigestMap.put("Base64", base64); DigestMap.put("Hex", String.valueOf(haxValue)); return JSON.toJSONString(DigestMap); } }

加密原文:123456

算法Base64
MD5
4QrcOUm6Wau+VuBX8g+IPg==
sha-1
fEqNCco3Yq9h5ZUglD3CZJT4lBs=
sha-256
jZae727K08KaOmKSgOaGzww/XVqGr/PKEgIMkjrcbJI=
算法Hex
MD5e10adc3949ba59abbe56e057f20f883e
sha-17c4a8d09ca3762af61e59520943dc26494f8941b
sha-2568d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92

四、对称加密(Des,Triple Des,AES)

采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密。常用的单向加密算法:

  • DES(Data Encryption Standard):数据加密标准,速度较快,适用于加密大量数据的场合;
  • 3DES(Triple DES):是基于DES,对一块数据用三个不同的密钥进行三次加密,强度更高;
  • AES(Advanced Encryption Standard):高级加密标准,是下一代的加密算法标准,速度快,安全级别高,支持128、192、256位密钥的加密;

加密原文:你好世界!!

import com.sun.org.apache.xerces.internal.impl.dv.util.Base64; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; public class desOrAesDemo { public static void main(String[] args) throws Exception { String text = "你好世界!!"; String key = "12345678";//des必须8字节 // 算法/模式/填充 默认 DES/ECB/PKCS5Padding String transformation = "DES"; String key1 = "1234567812345678";//aes必须16字节 String transformation1 = "AES"; String key2 = "123456781234567812345678";//TripleDES使用24字节的key String transformation2 = "TripleDes"; String extracted = extracted(text, key, transformation, true); System.out.println("DES加密:" + extracted); String extracted1 = extracted(extracted, key, transformation, false); System.out.println("解密:" + extracted1); String extracted2 = extracted(text, key1, transformation1, true); System.out.println("AES加密:" + extracted2); String extracted3 = extracted(extracted2, key1, transformation1, false); System.out.println("解密:" + extracted3); String extracted4 = extracted(text, key2, transformation2, true); System.out.println("Triple Des加密:" + extracted4); String extracted5 = extracted(extracted, key2, transformation2, false); System.out.println("解密:" + extracted5); } /** * @param text 明文/base64密文 * @param key 密钥 * @param transformation 转换方式 * @param mode 加密/解密 */ private static String extracted(String text, String key, String transformation, boolean mode) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { Cipher cipher = Cipher.getInstance(transformation); // key 与给定的密钥内容相关联的密钥算法的名称 SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), transformation); //Cipher 的操作模式,加密模式:ENCRYPT_MODE、 解密模式:DECRYPT_MODE、包装模式:WRAP_MODE 或 解包装:UNWRAP_MODE) cipher.init(mode ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, secretKeySpec); byte[] bytes = cipher.doFinal(mode ? text.getBytes(StandardCharsets.UTF_8) : Base64.decode(text)); return mode ? Base64.encode(bytes) : new String(bytes); } }
算法密匙密文
DES
12345678 8位
j+tPzTH7ttEeK+FrJaLY8OwmOezdN8hF
AES
12345678*2 16位
/+cq03JhyvrTIJyYvWwc2Dc/bFUBNKelKPSANnWgsAw=
TripleDes
12345678*3 24位j+tPzTH7ttEeK+FrJaLY8OwmOezdN8hF

五、非对称加密

公钥加密,也叫非对称(密钥)加密(public key encryption),属于通信科技下的网络安全二级学科,指的是由对应的一对唯一性密钥(即公开密钥和私有密钥)组成的加密方法。它解决了密钥的发布和管理问题,是商业密码的核心。在公钥加密体制中,没有公开的是私钥,公开的是公钥。常用的算法:

RSA、ElGamal、背包算法、Rabin(Rabin的加密法可以说是RSA方法的特例)、Diffie-Hellman (D-H) 密钥交换协议中的公钥加密算法、Elliptic Curve Cryptography(ECC,椭圆曲线加密算法)。

1.生成公钥和私钥文件

目前JDK1.8支持 RSA、DSA、DIFFIEHELLMAN、EC

/** * 生成公钥和私钥文件 * @param algorithm 算法 * @param privatePath 私钥路径 * @param publicPath 公钥路径 */ private static void generateKeyFile(String algorithm, String privatePath, String publicPath) throws NoSuchAlgorithmException, IOException { //返回生成指定算法的 public/private 密钥对的 KeyPairGenerator 对象 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm); //生成一个密钥对 KeyPair keyPair = keyPairGenerator.generateKeyPair(); //私钥 PrivateKey privateKey = keyPair.getPrivate(); //公钥 PublicKey publicKey = keyPair.getPublic(); byte[] privateKeyEncoded = privateKey.getEncoded(); byte[] publicKeyEncoded = publicKey.getEncoded(); String privateEncodeString = Base64.encode(privateKeyEncoded); String publicEncodeString = Base64.encode(publicKeyEncoded); //需导入commons-io FileUtils.writeStringToFile(new File(privatePath), privateEncodeString, StandardCharsets.UTF_8); FileUtils.writeStringToFile(new File(publicPath), publicEncodeString, StandardCharsets.UTF_8); }

2.使用RSA进行加密、解密

package cryptography; import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException; import com.sun.org.apache.xml.internal.security.utils.Base64; import org.apache.commons.io.FileUtils; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.security.*; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; public class RSADemo { public static void main(String[] args) throws Exception { String text = "===你好世界==="; String algorithm = "RSA"; PublicKey publicKey = getPublicKey(algorithm, "rsaKey/publicKey2.txt"); PrivateKey privateKey = getPrivateKey(algorithm, "rsaKey/privateKey2.txt"); String s = RSAEncrypt(text, algorithm, publicKey); String s1 = RSADecrypt(s, algorithm, privateKey); System.out.println(s); System.out.println(s1); //generateKeyFile("DSA","D:\\privateKey2.txt","D:\\publicKey2.txt"); } /** * 获取公钥,key * @param algorithm 算法 * @param publicPath 密匙文件路径 * @return */ private static PublicKey getPublicKey(String algorithm, String publicPath) throws IOException, NoSuchAlgorithmException, Base64DecodingException, InvalidKeySpecException { String publicEncodeString = FileUtils.readFileToString(new File(publicPath), StandardCharsets.UTF_8); //返回转换指定算法的 public/private 关键字的 KeyFactory 对象。 KeyFactory keyFactory = KeyFactory.getInstance(algorithm); //此类表示根据 ASN.1 类型 SubjectPublicKeyInfo 进行编码的公用密钥的 ASN.1 编码 X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decode(publicEncodeString)); return keyFactory.generatePublic(x509EncodedKeySpec); } /** * 获取私钥,key * @param algorithm 算法 * @param privatePath 密匙文件路径 * @return */ private static PrivateKey getPrivateKey(String algorithm, String privatePath) throws IOException, NoSuchAlgorithmException, Base64DecodingException, InvalidKeySpecException { String privateEncodeString = FileUtils.readFileToString(new File(privatePath), StandardCharsets.UTF_8); //返回转换指定算法的 public/private 关键字的 KeyFactory 对象。 KeyFactory keyFactory = KeyFactory.getInstance(algorithm); //创建私钥key的规则 此类表示按照 ASN.1 类型 PrivateKeyInfo 进行编码的专用密钥的 ASN.1 编码 PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decode(privateEncodeString)); //私钥对象 return keyFactory.generatePrivate(pkcs8EncodedKeySpec); } /** * 加密 * @param text 明文 * @param algorithm 算法 * @param key 私钥/密钥 * @return 密文 */ private static String RSAEncrypt(String text, String algorithm, Key key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, NoSuchProviderException { Cipher cipher = Cipher.getInstance(algorithm); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] bytes = cipher.doFinal(text.getBytes(StandardCharsets.UTF_8)); return Base64.encode(bytes); } /** * 解密 * @param extracted 密文 * @param algorithm 算法 * @param key 密钥/私钥 * @return String 明文 */ private static String RSADecrypt(String extracted, String algorithm, Key key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, Base64DecodingException, NoSuchProviderException { Cipher cipher = Cipher.getInstance(algorithm); cipher.init(Cipher.DECRYPT_MODE, key); byte[] bytes1 = cipher.doFinal(Base64.decode(extracted)); return new String(bytes1); } /** * 生成公钥和私钥文件 * @param algorithm 算法 * @param privatePath 私钥路径 * @param publicPath 公钥路径 */ private static void generateKeyFile(String algorithm, String privatePath, String publicPath) throws NoSuchAlgorithmException, IOException { //返回生成指定算法的 public/private 密钥对的 KeyPairGenerator 对象 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm); //生成一个密钥对 KeyPair keyPair = keyPairGenerator.generateKeyPair(); //私钥 PrivateKey privateKey = keyPair.getPrivate(); //公钥 PublicKey publicKey = keyPair.getPublic(); byte[] privateKeyEncoded = privateKey.getEncoded(); byte[] publicKeyEncoded = publicKey.getEncoded(); String privateEncodeString = Base64.encode(privateKeyEncoded); String publicEncodeString = Base64.encode(publicKeyEncoded); //需导入commons-io FileUtils.writeStringToFile(new File(privatePath), privateEncodeString, StandardCharsets.UTF_8); FileUtils.writeStringToFile(new File(publicPath), publicEncodeString, StandardCharsets.UTF_8); } }

密文(明文:===你好世界===)

ZBadyYCIck2iYV8RtsY35T1GbaYt9aLS51dcws5H4IcrOH+i6/8AIEdgtwJO3p1ccqKP6XTwQAWm
ceJ7kpsk76nvFD8Hg2pLYzH2oEE+oy07bLBdBiE+zVFkP+0DL+nrsHO4elQxc9BSslj5wGLQqbb1
Mxh9Tcpf5zJEOxdBZvE=

六、查看系统支持的算法

public static void main(String[] args) throws Exception { System.out.println("列出加密服务提供者:"); Provider[] pro=Security.getProviders(); for(Provider p:pro){ System.out.println("Provider:"+p.getName()+" - version:"+p.getVersion()); System.out.println(p.getInfo()); } System.out.println("======="); System.out.println("列出系统支持的消息摘要算法:"); for(String s:Security.getAlgorithms("MessageDigest")){ System.out.println(s); } System.out.println("======="); System.out.println("列出系统支持的生成公钥和私钥对的算法:"); for(String s:Security.getAlgorithms("KeyPairGenerator")){ System.out.println(s); } }

最推荐的方案是Hutool + Bouncy Castle。这个组合既有Bouncy Castle的强大算法支持,又有Hutool提供的简洁API

<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.40</version> </dependency> <dependency> <groupId>org.bouncycastle</groupId> <!--JDK ≤ 8:bcprov-jdk15to18 --> <!--JDK ≥ 9:优先 bcprov-jdk18on --> <artifactId>bcprov-jdk15to18</artifactId> <version>1.85.2</version> </dependency>

七、国密算法(20260831补充)

国密算法‌是由中国国家密码管理局认定的自主可控国产密码算法体系,主要用于保障国家信息安全,涵盖对称加密、非对称加密、哈希算法及流密码等类型 。它旨在减少对外部密码产品的依赖。

1.非对称加密SM2

国家标准委SM2密码算法使用规范

import cn.hutool.core.util.HexUtil; import cn.hutool.crypto.SmUtil; import cn.hutool.crypto.asymmetric.KeyType; import cn.hutool.crypto.asymmetric.SM2; import org.bouncycastle.jce.provider.BouncyCastleProvider; import java.security.Security; public class sm2Test { public static void main(String[] args) { // 注册 Bouncy Castle 安全提供者(Hutool 会自动注册,但显式注册更稳妥) Security.addProvider(new BouncyCastleProvider()); // ========== 方式一:使用 SmUtil.sm2() 生成密钥对 ========== SM2 sm2 = SmUtil.sm2(); // 获取私钥的 D 值(32字节) byte[] privateKeyD = sm2.getD(); // 获取公钥点 Q(非压缩格式,以 04 开头) byte[] publicKeyQ = sm2.getQ(false); // 打印 Hex 格式(16进制字符串) String privateKeyHex = HexUtil.encodeHexStr(privateKeyD); String publicKeyHex = HexUtil.encodeHexStr(publicKeyQ); System.out.println("========== Hex 格式 =========="); System.out.println("私钥 (Hex): " + privateKeyHex); System.out.println("私钥长度: " + privateKeyHex.length() + " 字符 (对应 " + privateKeyD.length + " 字节)"); System.out.println("公钥 (Hex): " + publicKeyHex); System.out.println("公钥长度: " + publicKeyHex.length() + " 字符 (对应 " + publicKeyQ.length + " 字节)"); // ========== 方式二:获取标准 X.509 / PKCS#8 格式 ========== // 公钥为 X.509 格式,私钥为 PKCS#8 格式 String publicKeyBase64 = sm2.getPublicKeyBase64(); String privateKeyBase64 = sm2.getPrivateKeyBase64(); System.out.println("\n========== Base64 格式 (X.509 / PKCS#8) =========="); System.out.println("公钥 (Base64): " + publicKeyBase64); System.out.println("私钥 (Base64): " + privateKeyBase64); // ========== 验证:加密和解密 ========== String plainText = "Hello, SM2!"; System.out.println("\n========== 加解密验证 =========="); System.out.println("原文: " + plainText); // 公钥加密 String encrypted = sm2.encryptHex(plainText, KeyType.PublicKey); System.out.println("密文 (Hex): " + encrypted); // 私钥解密 String decrypted = sm2.decryptStr(encrypted, KeyType.PrivateKey); System.out.println("解密后: " + decrypted); /* ========== Hex 格式 ========== 私钥 (Hex): 008c9ad32cc71375f71f9589c764e59c6f5e45a032afd0193cdbb8714e20bff304 私钥长度: 66 字符 (对应 33 字节) 公钥 (Hex): 0425aa02efe62ed52c42d83024c536ce48a4568c237521bc2cdcdcd3f0c36e1d2db68798c385660f6183650f0a6db65a6079adac14aafe178f5faa59fd89002515 公钥长度: 130 字符 (对应 65 字节) */ } }

八、一些概念

1.数字信封(Digital Envelope)

场景:A 公司要把自己的 SM2 私钥(绝密数据)安全地传输给 B 公司。
痛点:私钥本身是绝密的,不能直接在互联网上明文传输。
解决办法:A 公司使用 B 公司的公钥(B公司自己生成)给这个私钥加一层“保护壳”(数字信封)。只有 B 公司用自己的私钥才能拆开这个壳,拿到里面的私钥。

2.非对称加密、解密与签名、验签

加密与解密:保护数据机密性

加密(用公钥Q:发送方使用接收方的公钥Q来加密消息

解密(用私钥d:接收方使用自己的私钥d来解密。

签名与验签:确认身份与完整性

签名(用私钥d:签名者使用自己的私钥d对消息的哈希值进行运算,生成签名(r, s)

验签(用公钥Q:验证者使用签名者的公钥Q来验证签名。

总而言之,公钥Q和私钥d是SM2算法的一体两面。Q是公开的“身份标识”和“锁”,用于加密和验签;而d是保密的“钥匙”,用于解密和签名。

①. 厘清核心原则

请记住这个铁律:

  • 私钥 = 身份证明,只能由生成者本人持有,永不公开

  • 公钥 = 印章或锁,可以公开分发给任何人。

②. 真实的通信场景(发送方 → 接收方)

假设你是发送方(Alice),对方是接收方(Bob)。你要给Bob发一份既加密(别人看不了)又签名(证明是你发的)的数据。流程是这样的:

  • Bob(接收方)要解密数据:Bob会把自己的公钥Q_bob提前公开给你(或给你一个人)。你用Bob的公钥加密数据。数据发过去后,Bob用自己的私钥d_bob解密。Bob的私钥全程只在他自己的电脑里,绝对不会发给你。

  • Alice(发送方)要签名数据:你需要用你自己的私钥d_alice对数据进行签名。然后,你把“加密后的数据 + 你的签名”一起发给Bob。

  • Bob(接收方)要验证签名:Bob收到数据后,为了确认这确实是你发的,他会去获取你的公钥Q_alice(你提前公开在官网、名片或证书上的)。Bob用你的公钥来验证这个签名是否有效。

签名用自己的私钥(自己留着),验签用对方的公钥(对方公开);加密用对方的公钥(对方公开),解密用自己的私钥(自己留着)。整个链条中,没有任何一个环节需要你把私钥交给对方,或让对方把私钥交给你

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/1 11:58:52

MiniOS源码深度解析:从启动到任务调度的嵌入式内核学习指南

简介&#xff1a;面向操作系统学习者与底层开发者的MiniOS微操作系统完整源代码包&#xff0c;由国内技术爱好者精心设计实现。项目体量虽小&#xff0c;却覆盖操作系统核心议题&#xff0c;非常适合阅读内核源码、理解启动流程与系统调用等实践场景。压缩包共收录49个文件&…

作者头像 李华
网站建设 2026/9/1 11:58:30

维修电工理论基础:从换件到系统分析,突破职业天花板

维修电工理论基础&#xff1a;别让“换件思维”卡住你的职业天花板在工厂车间、物业配电室或设备维护一线&#xff0c;你大概率见过两种维修电工。一种人接到报修电话&#xff0c;拎着工具包赶到现场&#xff0c;先问“哪里坏了”&#xff0c;然后拆开外壳&#xff0c;凭着经验…

作者头像 李华
网站建设 2026/9/1 11:56:44

2026年8月沫清风户外用品工厂资质查询与核验指南

雨棚工程的风险&#xff0c;通常不在“能不能搭起来”&#xff0c;而在于材料规格、结构计算、施工安全、验收文件与长期售后是否形成完整证据链。查询沫清风户外用品工厂资质时&#xff0c;不能只看宣传页面上的“源头厂家”或“多年经验”&#xff0c;而应当把企业主体、生产…

作者头像 李华
网站建设 2026/9/1 11:56:03

GStreamer 2(TODO)

TODOgst-launch-1.0 -v \libcamerasrc ! \video/x-raw,formatNV12,width640,height480,framerate30/1 ! \videoconvert ! \x264enc tunezerolatency bitrate500 key-int-max30 ! \h264parse ! \mpegtsmux namemux ! \tcpserversink host0.0.0.0 port5000 syncfalseSSH 端口开放…

作者头像 李华