最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java對(duì)稱加密與非對(duì)稱加密區(qū)別、用途及工具類實(shí)戰(zhàn)教程

 更新時(shí)間:2025年12月02日 09:53:04   作者:帆事靠自己  
對(duì)稱加密是一種將數(shù)據(jù)加密的技術(shù),它采用一個(gè)密鑰來完成加密和解密的過程,下面這篇文章主要介紹了Java對(duì)稱加密與非對(duì)稱加密區(qū)別、用途及工具類實(shí)戰(zhàn)的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

在Java開發(fā)中,加密是保障數(shù)據(jù)安全的核心手段,常用的加密方式主要分為對(duì)稱加密非對(duì)稱加密。很多開發(fā)者剛接觸時(shí)會(huì)混淆兩者的用法,這篇文章就用通俗的語言講清它們的區(qū)別、適用場(chǎng)景,再附上可直接復(fù)用的工具類,新手也能快速上手。

一、核心區(qū)別:一張表看懂

對(duì)比維度對(duì)稱加密非對(duì)稱加密
密鑰特點(diǎn)加密和解密用同一把密鑰(密鑰需嚴(yán)格保密)公鑰+私鑰成對(duì)工作(公鑰可公開,私鑰必須保密)
加密效率速度極快(適合大數(shù)據(jù)量加密)速度較慢(數(shù)學(xué)運(yùn)算復(fù)雜,適合小數(shù)據(jù)量加密)
安全性安全性依賴密鑰保管(密鑰泄露則數(shù)據(jù)全暴露)安全性更高(私鑰不對(duì)外傳輸,僅需保管好私鑰)
密鑰分發(fā)密鑰分發(fā)困難(需安全通道傳輸,否則易被攔截)密鑰分發(fā)簡單(公鑰可公開傳播,無需保密)
典型算法AES、DES、3DESRSA、DSA、ECC

二、各自用途:什么時(shí)候用哪種?

1. 對(duì)稱加密:適合“大數(shù)據(jù)量加密”場(chǎng)景

對(duì)稱加密的核心優(yōu)勢(shì)是,所以主要用于對(duì)大量數(shù)據(jù)進(jìn)行加密,比如:

  • 數(shù)據(jù)庫中敏感字段加密(如用戶手機(jī)號(hào)、身份證號(hào));
  • 文件傳輸加密(如上傳/下載的Excel、PDF文件);
  • 接口請(qǐng)求體加密(如APP向后端傳輸?shù)挠脩粜袨閿?shù)據(jù))。

舉個(gè)實(shí)際開發(fā)場(chǎng)景:用戶在APP上提交實(shí)名認(rèn)證信息(姓名+身份證號(hào)),后端接收后需要加密存儲(chǔ)到MySQL。此時(shí)用AES對(duì)稱加密,既能保證數(shù)據(jù)安全,又不會(huì)因?yàn)榧用芎臅r(shí)影響接口響應(yīng)速度。

2. 非對(duì)稱加密:適合“密鑰交換/數(shù)字簽名”場(chǎng)景

非對(duì)稱加密的核心優(yōu)勢(shì)是安全且密鑰易分發(fā),但速度慢,所以主要用于:

  • 密鑰交換(如對(duì)稱加密的密鑰,通過非對(duì)稱加密傳輸);
  • 數(shù)字簽名(如接口防篡改、數(shù)據(jù)來源認(rèn)證);
  • 小數(shù)據(jù)加密(如加密用戶登錄密碼的驗(yàn)證碼)。

舉個(gè)實(shí)際開發(fā)場(chǎng)景:APP與后端首次建立連接時(shí),需要協(xié)商一個(gè)對(duì)稱加密的密鑰(用于后續(xù)數(shù)據(jù)傳輸加密)。此時(shí)后端生成RSA公鑰和私鑰,將公鑰傳給APP,APP用公鑰加密自己生成的AES密鑰,后端用私鑰解密得到AES密鑰,后續(xù)就用AES加密傳輸數(shù)據(jù)——既解決了對(duì)稱密鑰的安全分發(fā)問題,又保證了傳輸效率。

三、Java工具類實(shí)戰(zhàn)(可直接復(fù)制使用)

1. 對(duì)稱加密工具類(AES算法)

AES是目前最常用的對(duì)稱加密算法,安全性高、效率快,推薦優(yōu)先使用。以下工具類支持AES-128/256加密,包含加密、解密、生成密鑰功能:

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

/**
 * AES對(duì)稱加密工具類(可直接復(fù)用)
 * 說明:128位密鑰無需額外配置,256位密鑰需安裝JCE無限制權(quán)限文件
 */
public class AesEncryptUtil {

    // 加密算法:AES,模式:ECB,填充方式:PKCS5Padding(實(shí)際開發(fā)推薦用CBC模式,需加偏移量)
    private static final String ALGORITHM = "AES/ECB/PKCS5Padding";
    private static final String KEY_ALGORITHM = "AES";
    private static final int KEY_SIZE = 128; // 密鑰長度:128/256

    /**
     * 生成AES密鑰(返回Base64編碼后的密鑰字符串,方便存儲(chǔ))
     */
    public static String generateKey() throws Exception {
        KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM);
        keyGenerator.init(KEY_SIZE);
        SecretKey secretKey = keyGenerator.generateKey();
        return Base64.getEncoder().encodeToString(secretKey.getEncoded());
    }

    /**
     * 加密:明文 -> Base64編碼的密文
     * @param plainText 明文(待加密的字符串)
     * @param keyStr Base64編碼后的密鑰
     */
    public static String encrypt(String plainText, String keyStr) throws Exception {
        // 1. 解碼密鑰
        byte[] keyBytes = Base64.getDecoder().decode(keyStr);
        SecretKeySpec secretKey = new SecretKeySpec(keyBytes, KEY_ALGORITHM);
        // 2. 初始化加密器
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        // 3. 加密并返回Base64編碼的密文
        byte[] encryptBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
        return Base64.getEncoder().encodeToString(encryptBytes);
    }

    /**
     * 解密:Base64編碼的密文 -> 明文
     * @param cipherText Base64編碼后的密文
     * @param keyStr Base64編碼后的密鑰
     */
    public static String decrypt(String cipherText, String keyStr) throws Exception {
        // 1. 解碼密鑰和密文
        byte[] keyBytes = Base64.getDecoder().decode(keyStr);
        byte[] cipherBytes = Base64.getDecoder().decode(cipherText);
        SecretKeySpec secretKey = new SecretKeySpec(keyBytes, KEY_ALGORITHM);
        // 2. 初始化解密器
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        // 3. 解密并返回明文
        byte[] decryptBytes = cipher.doFinal(cipherBytes);
        return new String(decryptBytes, "UTF-8");
    }

    // 測(cè)試方法
    public static void main(String[] args) throws Exception {
        // 1. 生成密鑰(實(shí)際開發(fā)中密鑰需妥善保管,如配置在Nacos、Vault中)
        String key = generateKey();
        System.out.println("AES密鑰(Base64編碼):" + key);

        // 2. 加密
        String plainText = "用戶身份證號(hào):110101199001011234";
        String cipherText = encrypt(plainText, key);
        System.out.println("加密后的密文:" + cipherText);

        // 3. 解密
        String decryptText = decrypt(cipherText, key);
        System.out.println("解密后的明文:" + decryptText);
    }
}

2. 非對(duì)稱加密工具類(RSA算法)

RSA是最常用的非對(duì)稱加密算法,適合密鑰交換和數(shù)字簽名。以下工具類包含密鑰對(duì)生成、公鑰加密、私鑰解密、私鑰簽名、公鑰驗(yàn)簽功能:

import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * RSA非對(duì)稱加密工具類(可直接復(fù)用)
 * 說明:密鑰長度推薦2048位(安全性足夠),4096位加密速度較慢
 */
public class RsaEncryptUtil {

    private static final String ALGORITHM = "RSA";
    private static final int KEY_SIZE = 2048; // 密鑰長度:2048/4096
    // 簽名算法:SHA256withRSA(SHA256哈希+RSA簽名,安全性更高)
    private static final String SIGN_ALGORITHM = "SHA256withRSA";

    /**
     * 生成RSA密鑰對(duì)(公鑰+私鑰),返回Base64編碼后的字符串
     * @return 數(shù)組:[0]公鑰,[1]私鑰
     */
    public static String[] generateKeyPair() throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
        keyPairGenerator.initialize(KEY_SIZE);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();

        // 公鑰編碼為Base64字符串
        String publicKey = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
        // 私鑰編碼為Base64字符串
        String privateKey = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());

        return new String[]{publicKey, privateKey};
    }

    /**
     * 公鑰加密(適合加密小數(shù)據(jù),如AES密鑰)
     * @param plainText 明文(待加密的字符串)
     * @param publicKeyStr Base64編碼后的公鑰
     */
    public static String encryptByPublicKey(String plainText, String publicKeyStr) throws Exception {
        // 1. 解碼公鑰
        byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyStr);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        PublicKey publicKey = keyFactory.generatePublic(keySpec);

        // 2. 初始化加密器
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);

        // 3. 加密(RSA加密有長度限制,需分段加密,這里簡化處理短字符串)
        byte[] encryptBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
        return Base64.getEncoder().encodeToString(encryptBytes);
    }

    /**
     * 私鑰解密
     * @param cipherText Base64編碼后的密文
     * @param privateKeyStr Base64編碼后的私鑰
     */
    public static String decryptByPrivateKey(String cipherText, String privateKeyStr) throws Exception {
        // 1. 解碼私鑰
        byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyStr);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

        // 2. 初始化解密器
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        // 3. 解密
        byte[] cipherBytes = Base64.getDecoder().decode(cipherText);
        byte[] decryptBytes = cipher.doFinal(cipherBytes);
        return new String(decryptBytes, "UTF-8");
    }

    /**
     * 私鑰簽名(用于數(shù)據(jù)防篡改、來源認(rèn)證)
     * @param data 待簽名的數(shù)據(jù)
     * @param privateKeyStr Base64編碼后的私鑰
     */
    public static String sign(String data, String privateKeyStr) throws Exception {
        // 1. 解碼私鑰
        byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyStr);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

        // 2. 生成簽名
        Signature signature = Signature.getInstance(SIGN_ALGORITHM);
        signature.initSign(privateKey);
        signature.update(data.getBytes("UTF-8"));
        byte[] signBytes = signature.sign();
        return Base64.getEncoder().encodeToString(signBytes);
    }

    /**
     * 公鑰驗(yàn)簽(驗(yàn)證數(shù)據(jù)是否被篡改、簽名是否有效)
     * @param data 原始數(shù)據(jù)
     * @param sign 簽名值(Base64編碼)
     * @param publicKeyStr Base64編碼后的公鑰
     */
    public static boolean verifySign(String data, String sign, String publicKeyStr) throws Exception {
        // 1. 解碼公鑰
        byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyStr);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        PublicKey publicKey = keyFactory.generatePublic(keySpec);

        // 2. 驗(yàn)證簽名
        Signature signature = Signature.getInstance(SIGN_ALGORITHM);
        signature.initVerify(publicKey);
        signature.update(data.getBytes("UTF-8"));
        return signature.verify(Base64.getDecoder().decode(sign));
    }

    // 測(cè)試方法
    public static void main(String[] args) throws Exception {
        // 1. 生成密鑰對(duì)
        String[] keyPair = generateKeyPair();
        String publicKey = keyPair[0];
        String privateKey = keyPair[1];
        System.out.println("RSA公鑰(Base64編碼):" + publicKey);
        System.out.println("RSA私鑰(Base64編碼):" + privateKey);

        // 2. 加密解密(加密AES密鑰示例)
        String aesKey = "1234567890abcdef"; // 假設(shè)生成的AES密鑰
        String encryptAesKey = encryptByPublicKey(aesKey, publicKey);
        System.out.println("公鑰加密后的AES密鑰:" + encryptAesKey);
        String decryptAesKey = decryptByPrivateKey(encryptAesKey, privateKey);
        System.out.println("私鑰解密后的AES密鑰:" + decryptAesKey);

        // 3. 簽名驗(yàn)簽
        String data = "接口返回?cái)?shù)據(jù):{\"code\":200,\"msg\":\"success\"}";
        String sign = sign(data, privateKey);
        System.out.println("私鑰簽名值:" + sign);
        boolean verifyResult = verifySign(data, sign, publicKey);
        System.out.println("公鑰驗(yàn)簽結(jié)果:" + verifyResult); // true表示驗(yàn)簽通過
    }
}

四、開發(fā)注意事項(xiàng)

  1. 密鑰保管:對(duì)稱加密的密鑰和非對(duì)稱加密的私鑰,不能硬編碼在代碼里,建議存儲(chǔ)在配置中心(如Nacos)或密鑰管理工具(如Vault);
  2. 算法選擇:對(duì)稱加密優(yōu)先用AES(避免用DES,安全性較低),非對(duì)稱加密優(yōu)先用RSA-2048(兼顧安全性和效率);
  3. 數(shù)據(jù)長度:RSA加密有長度限制(如2048位密鑰最多加密245字節(jié)),加密大數(shù)據(jù)需分段,或用“非對(duì)稱加密+對(duì)稱加密”組合方案;
  4. 填充方式:對(duì)稱加密推薦用PKCS5Padding(兼容性好),非對(duì)稱加密無需手動(dòng)指定填充方式(Java默認(rèn)實(shí)現(xiàn)已優(yōu)化)。

總結(jié)

到此這篇關(guān)于Java對(duì)稱加密與非對(duì)稱加密區(qū)別、用途及工具類的文章就介紹到這了,更多相關(guān)Java對(duì)稱加密與非對(duì)稱加密內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java MD5加密(實(shí)例講解)

    Java MD5加密(實(shí)例講解)

    下面小編就為大家?guī)硪黄狫ava MD5加密(實(shí)例講解)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-08-08
  • Springboot?注解EqualsAndHashCode詳解

    Springboot?注解EqualsAndHashCode詳解

    注解@EqualsAndHashCode主要用于自動(dòng)生成equals方法和hashCode方法,callSuper屬性為true時(shí),生成的方法會(huì)包括父類字段,為false則只包含當(dāng)前類字段,IDEA工具中有檢查提示并可自動(dòng)修復(fù)相關(guān)代碼,確保注解正確使用,更多詳解可查閱相關(guān)文檔
    2024-10-10
  • SpringSecurity攔截器鏈的使用詳解

    SpringSecurity攔截器鏈的使用詳解

    這篇文章主要介紹了SpringSecurity攔截器鏈的使用詳解,webSecurity的build方法最終調(diào)用的是doBuild方法,doBuild方法調(diào)用的是webSecurity的performBuild方法,webSecurity完成所有過濾器的插件,最終返回的是過濾器鏈代理類filterChainProxy,需要的朋友可以參考下
    2023-11-11
  • Java?OpenCV圖像處理之背景切換

    Java?OpenCV圖像處理之背景切換

    這篇文章主要介紹了利用Java?OpenCV實(shí)現(xiàn)圖像背景的切換,文中的示例代碼講解詳細(xì)。對(duì)我們學(xué)習(xí)OpenCV有一定幫助,感興趣的同學(xué)可以了解一下
    2022-01-01
  • MyBatis?動(dòng)態(tài)SQL使用及原理

    MyBatis?動(dòng)態(tài)SQL使用及原理

    這篇文章主要為大家介紹了MyBatis動(dòng)態(tài)SQL使用及原理的學(xué)習(xí)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • 全面解析JTA 深度歷險(xiǎn)

    全面解析JTA 深度歷險(xiǎn)

    本文介紹了利用 JTA 深度歷險(xiǎn)的相關(guān)內(nèi)容,充分舉例說明JTA的原理和事務(wù)處理等相關(guān)內(nèi)容,十分詳細(xì),需要的朋友可以參考下。
    2017-09-09
  • Spring Boot 配置和使用多線程池的實(shí)現(xiàn)

    Spring Boot 配置和使用多線程池的實(shí)現(xiàn)

    這篇文章主要介紹了Spring Boot 配置和使用多線程池的實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-06-06
  • Vue實(shí)現(xiàn)驗(yàn)證碼登錄的超詳細(xì)步驟

    Vue實(shí)現(xiàn)驗(yàn)證碼登錄的超詳細(xì)步驟

    這篇文章主要給大家介紹了關(guān)于Vue實(shí)現(xiàn)驗(yàn)證碼登錄的超詳細(xì)步驟,我們?cè)谑褂胿ue進(jìn)行前端開發(fā)時(shí)都需要登錄驗(yàn)證,文中通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下
    2023-09-09
  • Java二叉樹的四種遍歷方式詳解

    Java二叉樹的四種遍歷方式詳解

    這篇文章主要介紹了Java二叉樹的四種遍歷,二叉樹的遍歷可以分為前序、中序、后序、層次遍歷,需要的朋友可以參考下
    2021-11-11
  • Java異常處理之try...catch...finally詳解

    Java異常處理之try...catch...finally詳解

    今天小編就為大家分享一篇關(guān)于Java異常處理之try...catch...finally詳解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-01-01

最新評(píng)論

昌江| 沙河市| 遂溪县| 祁门县| 大关县| 普兰县| 崇明县| 库伦旗| 沧州市| 襄垣县| 永和县| 邮箱| 渭源县| 武山县| 天镇县| 宁陕县| 湘乡市| 涟水县| 和硕县| 德保县| 抚顺县| 喜德县| 孟州市| 灵丘县| 兴文县| 武清区| 冷水江市| 乌拉特前旗| 伊通| 汕头市| 洛南县| 达拉特旗| 筠连县| 新宾| 广州市| 绥阳县| 台中市| 天等县| 镇远县| 班戈县| 麻江县|