欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java常見(jiàn)的五種加密算法使用方法舉例

 更新時(shí)間:2025年03月26日 09:21:52   作者:故城、  
這篇文章主要介紹了java常見(jiàn)的加密算法使用的相關(guān)資料,分別是BCrypt、MD5、RSA、AES和SM4這五種加密算法,并簡(jiǎn)要描述了它們的特點(diǎn)和應(yīng)用場(chǎng)景,給出了詳細(xì)的代碼示例,需要的朋友可以參考下

一、BCrypt加密

1.1 BCrypt簡(jiǎn)述

BCrypt是一種密碼散列函數(shù),即單向函數(shù),無(wú)法解密BCrypt哈希
是強(qiáng)哈希算法,結(jié)合了SHA-256、隨機(jī)鹽和密鑰來(lái)增強(qiáng)安全性

特點(diǎn):
唯一性:每次加密生成的鹽不一樣所以密碼的值也不一樣;
不可逆:只能驗(yàn)證兩個(gè)BCrypt哈希值是否相同,從而驗(yàn)證提供的密碼是否與原始密碼匹配

適用的場(chǎng)景:用戶密碼的加密

加密后的字符由4部分組成:

$2a$10$N9qo8uLOickxx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZmL17lhWy

標(biāo)識(shí)符:BCrypt算法的標(biāo)識(shí)符通常由$2a或$2b開(kāi)頭,2a是加密版本號(hào);

代價(jià)因子:其中10表示代價(jià)因子,這里是2的10次方,也就是1024輪;

鹽:在后面就是22位的鹽;鹽值是一個(gè)16字節(jié)(128位)的隨機(jī)值,經(jīng)過(guò)Base64編碼后變成22個(gè)字符的字符串;

哈希值:最后的31位字符串就是哈希值;通常是24字節(jié)(192位)的原始哈希值,經(jīng)過(guò)Base64編碼后變成31個(gè)字符的字符串‌;

修改密碼的話,可以向用戶發(fā)送一次性密碼重置鏈接,使用秘密問(wèn)題或其他一些方式來(lái)確認(rèn)用戶身份信息,讓他們?cè)O(shè)置新密碼

1.2 代碼示例

BCryptPasswordEncoder是一種使用BCrypt加密算法來(lái)加密密碼的方法

主要目的是為了防止密碼被明文存儲(chǔ)在數(shù)據(jù)庫(kù)中;

是Spring Security中用來(lái)加密用戶密碼的一個(gè)類

在使用時(shí)如果是springBoot項(xiàng)目需要引入依賴:

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring‐boot‐starter‐security</artifactId>
</dependency>

代碼示例:

BCryptPasswordEncoder bcryptPasswordEncoder = new BCryptPasswordEncoder();
// 加密;返回加密后字符串
bcryptPasswordEncoder.encoder(password)
// 比較;返回true或false
// rawPassword 密碼;encodedPassword加密后字符
bcrytPasswordEncoder.matches(rawPassword,encodedPassword)

二、MD5加密

2.1 MD5簡(jiǎn)述

MD5(Message-Digest Algorithm 5)是一種廣泛使用的哈希算法,將任意長(zhǎng)度的輸入轉(zhuǎn)換成一個(gè)128位的二進(jìn)制數(shù)

MD5 加密特性:

不可逆

相同的字符串內(nèi)容加密后結(jié)果相同

MD5應(yīng)用:

MD5 容易受到碰撞攻擊,不適用于安全性認(rèn)證;

存在碰撞就是指:在對(duì)兩個(gè)不同的內(nèi)容使用 MD5算法運(yùn)算的時(shí)候,有可能得到一對(duì)相同的結(jié)果值

可以用于消息或文件的完整性校驗(yàn)

2.2 代碼示例

使用 Java 內(nèi)置的 MessageDigest 類

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
 
public class TestMD5 {
    public static String encryptMD5(String input) {
        try {
            // 創(chuàng)建MD5加密對(duì)象
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 執(zhí)行加密操作
            byte[] messageDigest = md.digest(input.getBytes());
            // 將字節(jié)數(shù)組轉(zhuǎn)換為16進(jìn)制字符串
            StringBuilder hexString = new StringBuilder();
            for (byte b : messageDigest) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            // 返回加密后的字符串
            return hexString.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }
 
  	/**
     * 測(cè)試
     */
    public static void main(String[] args) {
        String str = "test1";
        String encrypted = encryptMD5(str);
        System.out.println("加密后字符串: " + encrypted);
    }
}

三、RSA加密

3.1 RSA簡(jiǎn)述

RSA加密是一種非對(duì)稱加密??梢栽诓恢苯觽鬟f密鑰的情況下,完成解密;使用一對(duì)公私秘鑰,公鑰可以對(duì)外公開(kāi),私鑰保密

加密是為了防止信息泄露,保證安全通信

簽名是為了防止信息被篡改,確保消息的完整性和來(lái)源認(rèn)證

?公鑰加密、私鑰解密、私鑰簽名、公鑰驗(yàn)簽;

實(shí)際使用一般情況加密和驗(yàn)簽同時(shí)使用

RSA加密流程:

A和B有自己的公鑰和私鑰;將公鑰給對(duì)方系統(tǒng)

1、A要給B發(fā)送消息時(shí),先用B的公鑰對(duì)消息加密,再對(duì)加密的字符串使用A的私鑰進(jìn)行加簽

2、A將加密后的字符串和加簽后的字符串當(dāng)作參數(shù)傳給B

3、B先用A的公鑰進(jìn)行驗(yàn)簽,沒(méi)問(wèn)題后在使用B的私鑰解密

4、B處理完后,返回的參數(shù)用A的公鑰加密

5、A用A的私鑰解密返回參數(shù)

3.2 代碼示例

import java.io.ByteArrayOutputStream;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import org.apache.commons.codec.binary.Base64;

public class TestRSA {

    /**
     * RSA最大加密明文大小
     */
    private static final int MAX_ENCRYPT_BLOCK = 117;

    /**
     * RSA最大解密密文大小
     */
    private static final int MAX_DECRYPT_BLOCK = 128;

    /**
     * 獲取密鑰對(duì)
     * 
     * @return 密鑰對(duì)
     */
    public static KeyPair getKeyPair() throws Exception {
        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
        generator.initialize(1024);
        return generator.generateKeyPair();
    }

    /**
     * 獲取私鑰
     * 
     * @param privateKey 私鑰字符串
     * @return
     */
    public static PrivateKey getPrivateKey(String privateKey) throws Exception {
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        byte[] decodedKey = Base64.decodeBase64(privateKey.getBytes());
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
        return keyFactory.generatePrivate(keySpec);
    }

    /**
     * 獲取公鑰
     * 
     * @param publicKey 公鑰字符串
     * @return
     */
    public static PublicKey getPublicKey(String publicKey) throws Exception {
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        byte[] decodedKey = Base64.decodeBase64(publicKey.getBytes());
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);
        return keyFactory.generatePublic(keySpec);
    }
    
    /**
     * RSA加密
     * 
     * @param data 待加密數(shù)據(jù)
     * @param publicKey 公鑰
     * @return
     */
    public static String encrypt(String data, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        int inputLen = data.getBytes().length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offset = 0;
        byte[] cache;
        int i = 0;
        // 對(duì)數(shù)據(jù)分段加密
        while (inputLen - offset > 0) {
            if (inputLen - offset > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(data.getBytes(), offset, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(data.getBytes(), offset, inputLen - offset);
            }
            out.write(cache, 0, cache.length);
            i++;
            offset = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();
        // 獲取加密內(nèi)容使用base64進(jìn)行編碼,并以UTF-8為標(biāo)準(zhǔn)轉(zhuǎn)化成字符串
        // 加密后的字符串
        return new String(Base64.encodeBase64String(encryptedData));
    }

    /**
     * RSA解密
     * 
     * @param data 待解密數(shù)據(jù)
     * @param privateKey 私鑰
     * @return
     */
    public static String decrypt(String data, PrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] dataBytes = Base64.decodeBase64(data);
        int inputLen = dataBytes.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offset = 0;
        byte[] cache;
        int i = 0;
        // 對(duì)數(shù)據(jù)分段解密
        while (inputLen - offset > 0) {
            if (inputLen - offset > MAX_DECRYPT_BLOCK) {
                cache = cipher.doFinal(dataBytes, offset, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(dataBytes, offset, inputLen - offset);
            }
            out.write(cache, 0, cache.length);
            i++;
            offset = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        // 解密后的內(nèi)容 
        return new String(decryptedData, "UTF-8");
    }

    /**
     * 簽名
     * 
     * @param data 待簽名數(shù)據(jù)
     * @param privateKey 私鑰
     * @return 簽名
     */
    public static String sign(String data, PrivateKey privateKey) throws Exception {
        byte[] keyBytes = privateKey.getEncoded();
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey key = keyFactory.generatePrivate(keySpec);
        Signature signature = Signature.getInstance("MD5withRSA");
        signature.initSign(key);
        signature.update(data.getBytes());
        return new String(Base64.encodeBase64(signature.sign()));
    }

    /**
     * 驗(yàn)簽
     * 
     * @param srcData 原始字符串
     * @param publicKey 公鑰
     * @param sign 簽名
     * @return 是否驗(yàn)簽通過(guò)
     */
    public static boolean verify(String srcData, PublicKey publicKey, String sign) throws Exception {
        byte[] keyBytes = publicKey.getEncoded();
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey key = keyFactory.generatePublic(keySpec);
        Signature signature = Signature.getInstance("MD5withRSA");
        signature.initVerify(key);
        signature.update(srcData.getBytes());
        return signature.verify(Base64.decodeBase64(sign.getBytes()));
    }

    public static void main(String[] args) {
        try {
            // 生成密鑰對(duì)
            KeyPair keyPair = getKeyPair();
            String privateKey = new String(Base64.encodeBase64(keyPair.getPrivate().getEncoded()));
            String publicKey = new String(Base64.encodeBase64(keyPair.getPublic().getEncoded()));
            System.out.println("私鑰:" + privateKey);
            System.out.println("公鑰:" + publicKey);
            // RSA加密
            String data = "待加密的文字內(nèi)容";
            String encryptData = encrypt(data, getPublicKey(publicKey));
            System.out.println("加密后內(nèi)容:" + encryptData);
            // RSA解密
            String decryptData = decrypt(encryptData, getPrivateKey(privateKey));
            System.out.println("解密后內(nèi)容:" + decryptData);
            
            // RSA簽名
            String sign = sign(data, getPrivateKey(privateKey));
            // RSA驗(yàn)簽
            boolean result = verify(data, getPublicKey(publicKey), sign);
            System.out.print("驗(yàn)簽結(jié)果:" + result);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.print("加解密異常");
        }
    }
}

// 這部分代碼轉(zhuǎn)自https://www.cnblogs.com/pcheng/p/9629621.html

四、AES加密

4.1 AES簡(jiǎn)述

屬于對(duì)稱加密;對(duì)稱加密算法中,加密與解密的密鑰是相同的,密鑰為接收方與發(fā)送方協(xié)商產(chǎn)生

AES標(biāo)準(zhǔn)支持三種不同的密鑰長(zhǎng)度:128位、192位和256位

AES加密以16個(gè)字節(jié)為一組進(jìn)行分組加密,要求明文的長(zhǎng)度一定是16個(gè)字節(jié)的整數(shù)倍,如果不夠16個(gè)字節(jié)的倍數(shù),需要按照填充模式進(jìn)行填充

常見(jiàn)的填充模式包括NoPadding、ZeroPadding、PKCS#7

加密模式:ECB、CBC

CBC工作模式使用最廣泛

每一塊的加密依賴于前一塊的密文,提供了良好的保密性和抗重播攻擊能力

隨機(jī)數(shù)作為IV參數(shù),對(duì)于同一份明文,每次生成的密文都不同

4.2 代碼示例

引入依賴

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.26</version>
</dependency>

實(shí)現(xiàn)代碼

@Test
public static void testAes(String data) {
    // 密鑰,長(zhǎng)度必須是16、24或32
    byte[] key = "1234567898765432".getBytes();
    // 初始化向量,CBC模式長(zhǎng)度必須是16
    byte[] iv = "1234567898765432".getBytes();

    // 創(chuàng)建AES對(duì)象,指定密鑰和初始化向量
    SymmetricCrypto aes = new AES(Mode.CBC, Padding.PKCS5Padding, key, iv);

    // 加密并進(jìn)行Base轉(zhuǎn)碼
    String encrypt = aes.encryptBase64(data);
    System.out.println(encrypt);
    
    // 解密為字符串
    String decrypt = aes.decryptStr(encrypt);
    System.out.println(decrypt);
}

五、商用密碼算法

5.1 算法分類

SM1、SM2、SM3、SM4、SM9、ZUC等一系列商用密碼算法構(gòu)成了我國(guó)完整的密碼算法體系
SM1 對(duì)稱 電子政務(wù)、硬件等加密
SM2 非對(duì)稱 數(shù)字簽名、密鑰交換
SM3 摘要算法 數(shù)字簽名、完整性驗(yàn)證
SM4 對(duì)稱 電子政務(wù)、無(wú)線局域網(wǎng)加密
SM9 非對(duì)稱 數(shù)據(jù)加密、身份認(rèn)證

5.2 SM4加密算法

5.2.1 SM4簡(jiǎn)述

SM4算法的特點(diǎn)是:

(1)屬于對(duì)稱密碼算法,加解密的密鑰相同;

(2)明密文和密鑰均為128比特,分組長(zhǎng)度為128比特;

(3)SM4密碼算法加解密算法的輪數(shù)為32輪,每輪的輪結(jié)構(gòu)相同,只是輪密鑰使用相反

金融行業(yè)國(guó)內(nèi)通用標(biāo)準(zhǔn)為SM4,對(duì)應(yīng)國(guó)際標(biāo)準(zhǔn)SM4

有兩種模式ECB和CBC

區(qū)別是前者只需要一個(gè)key,而后者不僅需要一個(gè)key還需要一個(gè)iv值

SM4的CBC模式‌和AES的CBC模式類似;安全性與AES-128基本一致,但是實(shí)現(xiàn)更簡(jiǎn)單、效率更高

SM4的CBC模式通過(guò)引入鏈?zhǔn)揭蕾噥?lái)提高安全性。它將每個(gè)明文塊與前一個(gè)密文塊進(jìn)行異或后再進(jìn)行加密。在這種方法中,每個(gè)密文塊都依賴于它前面的所有明文塊。同時(shí),為了保證每條消息的唯一性,在第一個(gè)塊中需要使用初始化向量IV‌

5.2.2 代碼示例

用工具類來(lái)實(shí)現(xiàn)CBC模式

引入依賴

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.26</version>
</dependency>
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.68</version>
</dependency>

代碼實(shí)現(xiàn)

public class TestSm4 {
 	/**
     * 密鑰 長(zhǎng)度必須是16
     */
    private static String SECRET_KEY = "";
    /**
     * IV是初始向量,它的作用是使相同的明文每次加密得到的密文都不同。 長(zhǎng)度必須是16
     */
    private static String IV= "";
 
 	/**
     * 加密成base64/字節(jié)數(shù)組
     */
    public static String encrypt(String plainTxt){
        String cipherTxt = "";
        SymmetricCrypto sm4Cbc = new SM4(Mode.CBC, Padding.PKCS5Padding, SECRET_KEY.getBytes(CharsetUtil.CHARSET_UTF_8), IV.getBytes(CharsetUtil.CHARSET_UTF_8));
        byte[] encrypHex = sm4Cbc.encrypt(plainTxt);
        cipherTxt = Base64.encode(encrypHex);
        return cipherTxt;
    }
 
 	/**
     * 解密
     */
    public static String decrypt(String cipherTxt){
    	String plainTxt = "";
        try {
	        SymmetricCrypto sm4 = new SM4(Mode.CBC, Padding.PKCS5Padding, SECRET_KEY.getBytes(CharsetUtil.CHARSET_UTF_8), IV.getBytes(CharsetUtil.CHARSET_UTF_8));
	        byte[] cipherHex = Base64.decode(cipherTxt);
	        plainTxt = sm4.decryptStr(cipherHex, CharsetUtil.CHARSET_UTF_8);
        } catch(Exception e) {
        	log.error(e.getMessage());
        }
        return plainTxt;
    }
 
 	/**
     * 測(cè)試
     */
    public static void main(String[] argc){
        String originTxt = "加密測(cè)試";
        String cipherTxt = encrypt(originTxt);
        System.out.println("加密后密文: " + cipherTxt);
        String plainTxt = decrypt(cipherTxt);
        System.out.println("解密后結(jié)果: " + plainTxt);
    }
}

使用SmUtil實(shí)現(xiàn)

 public void testSm4(String text) {
    SymmetricCrypto sm4 = SmUtil.sm4();
	
	// 加密后密文
    String encryptHex = sm4.encryptHex(text);
    // 解密后結(jié)果
    String decryptStr = sm4.decryptStr(encryptHex, CharsetUtil.CHARSET_UTF_8);
}

5.2 SM2簽名算法

5.2.1 SM2簡(jiǎn)述

SM2算法是一種非對(duì)稱加密算法,SM2算法主要用于數(shù)字簽名、密鑰交換和數(shù)據(jù)加密。在使用SM2算法時(shí),需要生成一個(gè)私鑰,一個(gè)公鑰。私鑰用于簽名和解密,公鑰用于驗(yàn)證簽名和加密。是一種更先進(jìn)安全的算法

5.2.2 代碼實(shí)現(xiàn)

引入依賴:

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.26</version>
</dependency>
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.68</version>
</dependency>

實(shí)現(xiàn):

// 加密
public static String encrypt(String data, String publicKey,String privateKey) {
    SM2 sm2 = SmUtil.sm2(publicKey,privateKey);
    return Arrays.toString(sm2.encrypt(data, KeyType.PublicKey));
}

// 解密
public static String decrypt(String data, String publicKey,String privateKey) {
    SM2 sm2 = SmUtil.sm2(publicKey,privateKey);
    return sm2.decryptStr(data, KeyType.PrivateKey);
}

public static void main(String[] args) {
    String data = "text";
    // 公鑰;公鑰長(zhǎng)度為64字節(jié)(512位)
    String publicKey = "";
    // 私鑰;私鑰長(zhǎng)度為32字節(jié)(256位)
    String privateKey = "";

    // 加密
    String encryptedData = encrypt(data, publicKey,privateKey);
    // 解密
    String decryptedData = decrypt(encryptedData,publicKey, privateKey);
}

5.3 SM3摘要算法

5.3.1 SM3簡(jiǎn)述

SM3算法是中國(guó)國(guó)家密碼管理局發(fā)布的消息摘要算法,用于生成消息的哈希值

SM3算法采用Merkle-Damgård結(jié)構(gòu),消息分組長(zhǎng)度為512位,摘要值長(zhǎng)度為256位(即32字節(jié))。其輸入可以是任意長(zhǎng)度數(shù)據(jù),但加密結(jié)果始終是256位數(shù)據(jù)。

應(yīng)用場(chǎng)景:

數(shù)字簽名:使用SM3算法生成的哈希值作為簽名的一部分,確保簽名的真實(shí)性和完整性。

消息完整性驗(yàn)證:通過(guò)比較消息的哈希值來(lái)驗(yàn)證消息在傳輸過(guò)程中是否被篡改。

流程簡(jiǎn)述:

‌1、消息填充:

將輸入消息填充至長(zhǎng)度為512位的倍數(shù)。

2、消息分組:

將填充后的消息按512位(64字節(jié))進(jìn)行分組

3、消息擴(kuò)展:

對(duì)每個(gè)512位的分組進(jìn)行擴(kuò)展,每個(gè)分組稱為一個(gè)消息塊,對(duì)每個(gè)消息塊進(jìn)行擴(kuò)展,形成132個(gè)字(每個(gè)字為32位)的擴(kuò)展消息

4、迭代壓縮:

將132個(gè)消息字,通過(guò)64輪的迭代壓縮計(jì)算,最終得到256位的哈希值。

在每一輪迭代中,都會(huì)使用8個(gè)32位的寄存器(A、B、C、D、E、F、G、H),這些寄存器在迭代開(kāi)始時(shí)被初始化為固定的常數(shù)值。

通過(guò)一系列操作,更新這些寄存器的值。

在完成64輪迭代后,將8個(gè)寄存器的值進(jìn)行異或運(yùn)算,得到最終的256位哈希值。

5.3.2 代碼實(shí)現(xiàn)

public static void main(String[] args) {
    String input = "Hello";
    String output = sm3Encrypt(input);
    System.out.println("SM3 Result: " + output);
}

public static String sm3Encrypt(String input) {
    try {
        MessageDigest md = MessageDigest.getInstance("SM3");
        byte[] digest = md.digest(input.getBytes());
        return bytesToHex(digest);
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

// 轉(zhuǎn)為16進(jìn)制字符串
public static String bytesToHex(byte[] bytes) {
    StringBuilder result = new StringBuilder();
    for (byte b : bytes) {
        result.append(String.format("%02x", b));
    }
    return result.toString();
}

5.4 HMAC-SM3

5.4.1 HMAC-SM3簡(jiǎn)述

HMAC-SM3是一種基于SM3的帶密鑰的哈希算法認(rèn)證技術(shù),使用SM3算法生成哈希值,引入密鑰來(lái)增強(qiáng)安全性

應(yīng)用場(chǎng)景:

消息認(rèn)證:通過(guò)比較發(fā)送方和接收方生成的消息認(rèn)證碼來(lái)驗(yàn)證消息的真實(shí)性和完整性。

數(shù)據(jù)完整性保護(hù):在數(shù)據(jù)傳輸和存儲(chǔ)過(guò)程中,使用HMAC-SM3算法來(lái)確保數(shù)據(jù)不被篡改。

5.4.2 代碼實(shí)現(xiàn)

引入依賴

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.69</version> <!-- 使用最新版本 -->
</dependency>

代碼實(shí)現(xiàn)

public static String hmacSM3(byte[] key, byte[] data) {
    // 創(chuàng)建一個(gè) SM3Digest 對(duì)象,用于進(jìn)行 SM3 哈希運(yùn)算
    SM3Digest sm3Digest = new SM3Digest();
    // 創(chuàng)建一個(gè) HMac 對(duì)象,使用 SM3Digest 作為底層哈希算法
    HMac hmac = new HMac(sm3Digest);
    // 使用密鑰初始化 HMac 對(duì)象
    hmac.init(new KeyParameter(key));
    // 更新 HMac 對(duì)象的數(shù)據(jù)
    hmac.update(data, 0, data.length);
    // 計(jì)算 HMAC-SM3 值,并將結(jié)果存儲(chǔ)在 result 數(shù)組中
    byte[] result = new byte[hmac.getMacSize()];
    // 執(zhí)行最終的哈希運(yùn)算,并將結(jié)果填充到 result 數(shù)組中
    hmac.doFinal(result, 0);
    return bytesToHex(result);
}

public static void main(String[] args) {
    // 示例密鑰
    byte[] key = "123456789".getBytes();
    byte[] data = "Hello".getBytes();
    // 計(jì)算HMAC-SM3值
    String hmac = hmacSM3(key, data);
    System.out.println("HMAC-SM3: " + hmac);
}

// 轉(zhuǎn)為16進(jìn)制字符串
public static String bytesToHex(byte[] bytes) {
    StringBuilder sb = new StringBuilder();
    for (byte b : bytes) {
        // 將每個(gè)字節(jié)轉(zhuǎn)換為16進(jìn)制字符串,并拼接到 StringBuilder 中
        sb.append(String.format("%02x", b));
    }
    return sb.toString();
}

總結(jié) 

到此這篇關(guān)于java常見(jiàn)的五種加密算法使用方法的文章就介紹到這了,更多相關(guān)java加密算法使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java內(nèi)存映射 大文件輕松處理

    Java內(nèi)存映射 大文件輕松處理

    這篇文章主要介紹了Java內(nèi)存映射 大文件輕松處理,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-08-08
  • java calendar 日期實(shí)現(xiàn)不斷加一天的代碼

    java calendar 日期實(shí)現(xiàn)不斷加一天的代碼

    這篇文章主要介紹了java calendar 日期實(shí)現(xiàn)不斷加一天的代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-10-10
  • Java中dubbo+zookeeper微服務(wù)架構(gòu)簡(jiǎn)介

    Java中dubbo+zookeeper微服務(wù)架構(gòu)簡(jiǎn)介

    Apache Dubbo是一款高性能的 Java RPC 框架,這篇文章主要介紹了Java中dubbo+zookeeper微服務(wù)架構(gòu),需要的朋友可以參考下
    2021-09-09
  • Spring中的AOP動(dòng)態(tài)代理源碼詳解

    Spring中的AOP動(dòng)態(tài)代理源碼詳解

    這篇文章主要介紹了Spring中的AOP動(dòng)態(tài)代理源碼詳解,AOP即面向切面編程也稱面向方面編程,它是面向?qū)ο缶幊蘋OP的一種補(bǔ)充,目前已成為一種比較成熟的編程方式,本文就其源碼進(jìn)行解析,需要的朋友可以參考下
    2023-09-09
  • java開(kāi)發(fā)ExecutorService監(jiān)控實(shí)現(xiàn)示例詳解

    java開(kāi)發(fā)ExecutorService監(jiān)控實(shí)現(xiàn)示例詳解

    這篇文章主要為大家介紹了java開(kāi)發(fā)ExecutorService監(jiān)控實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • 詳解關(guān)于Windows10 Java環(huán)境變量配置問(wèn)題的解決辦法

    詳解關(guān)于Windows10 Java環(huán)境變量配置問(wèn)題的解決辦法

    這篇文章主要介紹了關(guān)于Windows10 Java環(huán)境變量配置問(wèn)題的解決辦法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • java學(xué)習(xí)之JVM運(yùn)行時(shí)常量池理解

    java學(xué)習(xí)之JVM運(yùn)行時(shí)常量池理解

    這篇文章主要介紹了java學(xué)習(xí)之JVM運(yùn)行時(shí)常量池理解,對(duì)常量池的好處以及基本類型的包裝類常量池等作了簡(jiǎn)要分析,有需要的朋友可以借鑒參考下
    2021-09-09
  • Java實(shí)現(xiàn)任務(wù)管理器性能網(wǎng)絡(luò)監(jiān)控?cái)?shù)據(jù)的方法詳解

    Java實(shí)現(xiàn)任務(wù)管理器性能網(wǎng)絡(luò)監(jiān)控?cái)?shù)據(jù)的方法詳解

    在現(xiàn)代操作系統(tǒng)中,任務(wù)管理器是一個(gè)非常重要的工具,用于監(jiān)控和管理計(jì)算機(jī)的運(yùn)行狀態(tài),包括CPU使用率、內(nèi)存占用等,對(duì)于開(kāi)發(fā)者和系統(tǒng)管理員來(lái)說(shuō),了解這些性能數(shù)據(jù)有助于優(yōu)化應(yīng)用程序和系統(tǒng)性能,本文將介紹如何使用Java編寫一個(gè)簡(jiǎn)單的程序來(lái)監(jiān)控網(wǎng)絡(luò)性能數(shù)據(jù)
    2025-01-01
  • MyBatis之一級(jí)緩存和二級(jí)緩存問(wèn)題

    MyBatis之一級(jí)緩存和二級(jí)緩存問(wèn)題

    這篇文章主要介紹了MyBatis之一級(jí)緩存和二級(jí)緩存問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • ExpressionUtil工具類的應(yīng)用實(shí)例

    ExpressionUtil工具類的應(yīng)用實(shí)例

    這篇文章主要給大家介紹了關(guān)于ExpressionUtil工具類的應(yīng)用實(shí)例,常用的工具類有很多,這是其中一個(gè),了解基本的API可以幫助我們更好的開(kāi)發(fā),文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-04-04

最新評(píng)論