- 対称暗号化アルゴリズムは、非対称暗号化アルゴリズムを区別するためのものです。特徴は
加密是加密解密使用相同的密钥
、非対称暗号化加密和解密时使用的密钥不一样
です。- 非対称暗号化は、対称暗号化の鍵交換で使用できます。これにより、鍵のセキュリティが効果的に保護されます。
- 非対称暗号化暗号化と復号化キーは異なり、セキュリティは高いですが、暗号化と復号化の速度が非常に遅いため、ビッグデータの暗号化には適していません。対称暗号化は高速であるため、組み合わせて使用することをお勧めします。
一般的に使用される対称暗号化アルゴリズムは、AESとDESです。
- DES:
比较老的算法
3つのパラメータエントリ(元のテキスト、キー、暗号化モード)があります。3DESは、DESの単なるモードであり、DESに基づくより安全なバリアントであり、データを3回暗号化し、AESの移行アルゴリズムとしても指定されています。 - AES:Advanced Encryption Standard、新世代の標準、
加密速度更快,安全性更高(优先选择)
import org.junit.Test;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Base64;
public class SymmetricEncryptionUtil {
private static final String AES = "AES";
private static final String DES = "DES";
/**
* AES密钥
*/
private static final String AES_KEY = "FFC22E80F61AB7295C02493856B4C520";
/**
* AES模式
*/
private static final String AES_MODE = "AES/ECB/PKCS5Padding";
/**
* DES密钥: 加解密用到的秘钥-getBytes().length即字节的长度必须大于等于8,否则报异常java.security.InvalidKeyException: Wrong key size
*/
private static final String DES_KEY = "*%#@()^&";
/**
* DES模式
* "AES/ECB/PKCS5Padding"在加密和解密时必须相同,可以直接写”AES”,这样就是使用默认模式分别的意思为:AES是加密算法,ECB是工作模式,PKCS5Padding是填充方式。
*/
private static final String DES_MODE = "DES/ECB/PKCS5Padding";
/**
* 使用AES对字符串加密
*
* @param str utf8编码的字符串
* @param key 密钥(16字节)
* @return 加密结果
* @throws Exception
*/
public static String aesEncrypt(String str, String key) throws Exception {
if (str == null || key == null) {
return null;
}
//AES/ECB/PKCS5Padding在加密和解密时必须相同
Cipher cipher = Cipher.getInstance(AES_MODE);
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), AES));
byte[] bytes = cipher.doFinal(str.getBytes(StandardCharsets.UTF_8));
//使用base64编码
return Base64.getEncoder().encodeToString(bytes);
}
/**
* 使用AES对数据解密
*
* @param base64Encoder base64编码后的字符串
* @param key 密钥(16字节)
* @return 解密结果
* @throws Exception
*/
public static String aesDecrypt(String base64Encoder, String key) throws Exception {
if (base64Encoder == null || key == null) {
return null;
}
SecureRandom random = new SecureRandom();
Cipher cipher = Cipher.getInstance(AES_MODE);
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), AES), random);
//使用base64解码
byte[] base64DecoderByte = Base64.getDecoder().decode(base64Encoder);
return new String(cipher.doFinal(base64DecoderByte), StandardCharsets.UTF_8);
}
/**
* 使用DES对字符串加密
*
* @param str utf8编码的字符串
* @param key 密钥(56位,7字节)
* @return 加密结果
* @throws Exception
*/
public static String desEncrypt(String str, String key) throws Exception {
if (str == null || key == null) {
return null;
}
SecureRandom random = new SecureRandom();
Cipher cipher = Cipher.getInstance(DES_MODE);
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), DES), random);
byte[] bytes = cipher.doFinal(str.getBytes(StandardCharsets.UTF_8));
//使用base64编码
return Base64.getEncoder().encodeToString(bytes);
}
/**
* 使用DES对数据解密
*
* @param base64Encoder base64编码后的字符串
* @param key 密钥(16字节)
* @return 解密结果
* @throws Exception
*/
public static String desDecrypt(String base64Encoder, String key) throws Exception {
if (base64Encoder == null || key == null) {
return null;
}
Cipher cipher = Cipher.getInstance(DES_MODE);
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), DES));
//使用base64解码
byte[] base64DecoderByte = Base64.getDecoder().decode(base64Encoder);
return new String(cipher.doFinal(base64DecoderByte), StandardCharsets.UTF_8);
}
/**
* 测试AES算法
*
* @throws Exception
*/
@Test
public void main1() throws Exception {
String str = "你好,张三!";
System.out.println("原文:" + str);
System.out.println("密钥:" + AES_KEY);
String aesEncrypt = aesEncrypt(str, AES_KEY);
System.out.println("加密后:" + aesEncrypt);
String aesDecrypt = aesDecrypt(aesEncrypt, AES_KEY);
System.out.println("解密后:" + aesDecrypt);
}
/**
* 测试DES算法
*
* @throws Exception
*/
@Test
public void main2() throws Exception {
String str = "你好,张三!";
System.out.println("原文:" + str);
System.out.println("密钥:" + DES_KEY);
String aesEncrypt = desEncrypt(str, DES_KEY);
System.out.println("加密后:" + aesEncrypt);
String aesDecrypt = desDecrypt(aesEncrypt, DES_KEY);
System.out.println("解密后:" + aesDecrypt);
}
}
执行结果
```java
//main1
原文:你好,张三!
密钥:FFC22E80F61AB7295C02493856B4C520
加密后:Vlm7AY5VxhiOc5QSZe5Szga2oN2+AMpMDyHU9tYktFw=
解密后:你好,张三!
//main2
原文:你好,张三!
密钥:*%#@()^&
加密后:STDcjuovhcYOwV/tFmrvPH25wWw6o48M
解密后:你好,张三!
AESアルゴリズムのすべてのパラメーターはバイトコード(キーを含む)です。したがって、文字列文字はバイトコードに変換された後に暗号化する必要があります
- パラメータ:
”AES/ECB/PKCS5Padding”
で暗号化と復号化が同じである必要があります。直接「AES」と書き込むことができます。これがデフォルトのモードです。それぞれの意味は次のとおりです。AESは加密算法
、ECBは工作模式
、PKCS5Paddingは填充方式
です。
AESは、ブロック暗号化アルゴリズムとも呼ばれるブロック暗号化アルゴリズムです。各グループは16バイトです。このようにして、平文は複数の部分に分割されます。16バイト未満のブロックがある場合、それは埋められます。4つの動作モードがあります:
- ECB電子コードブックモード:同じ平文ブロックが同じ暗号文ブロックを生成します。これは並列操作が簡単ですが、平文を攻撃することも可能です。
- CBC暗号化パケットリンクモード:プレーンテキストのブロックは暗号化され、前の暗号文のブロックとリンクされます。これは並列処理に役立ちませんが、セキュリティはSSLおよびIPSecの標準であるECBよりも優れています。
- CFB暗号化フィードバックモード:キーを使用して最後の暗号文を計算し、それを暗号化します。平文モードを非表示にすることは、並列処理とエラー送信を助長しません。
- OFB出力フィードバックモード:前回キーで処理されたキーを計算し、暗号化します。平文モードを非表示にすることは並列処理を助長せず、平文攻撃やエラー送信を引き起こす可能性があります。
PKCS5Paddingのパディング方法は、バイト単位の差と同じ数を入力することです。それぞれが16バイト未満の場合、パディングのセットが16に追加されます。他のパディングモードがあります[Nopadding、ISO10126Padding](アルゴリズムに影響を与えず、暗号化と復号化の時間は一定です)。