Java 常用加密解密算法及应用示例

摘要:在Java开发中,加密解密技术是保护数据安全的重要手段。无论是存储敏感信息(如用户密码、个人信息)还是传输加密数据,都需要用到加密算法。不同的加密算法运用的场景也不同,因此选择合适的加密解密算法也是至关重要。

一、加密算法分类

加密算法的种类繁多,主要可以归纳为以下几大类:

一、对称加密算法

  • 定义:加密和解密使用相同密钥的加密算法。
  • 特点:加密强度高,效率高,但密钥分发和管理较为复杂。
  • 常见算法:
    • DES:一种使用对称密钥加密的块算法,由IBM公司于1975年研发,是广泛应用的早期对称加密算法之一,但由于密钥长度较短(56位),安全性已逐渐降低。
    • 3DES:DES算法的一个更安全的变形,使用3条56位的密钥对数据进行三次加密,提高了安全性,是DES算法向AES算法过渡的算法。
    • AES:高级加密标准(Advanced Encryption Standard),是一种分块加密算法,用于替代原先的DES算法。AES算法由三种不同的算法组成,分别使用128、192或256位加密密钥,具有高强度、高速度和易于实现的特点。
    • RC4:一种流密码算法,由Ron Rivest于1987年创建,通过生成一个伪随机数流与明文进行异或运算来实现加密,具有速度快、简单易用、灵活性高以及适用范围广的特点。
    • 其他还包括Blowfish、IDEA、RC5、RC6等算法。

二、非对称加密算法

  • 定义:非对称加密算法是指加密和解密使用不同密钥的加密算法,通常包含公钥和私钥。公钥用于加密,私钥用于解密(或反之用于验签)。
  • 特点:加密速度慢,但强度高,适用于密钥交换和数字签名等场景。
  • 常见算法:
    • RSA:一种基于公钥加密的算法,广泛应用于SSL证书中的密钥交换和数字签名过程,助力网站实现HTTPS加密,确保网络通信安全。
    • ECC:基于椭圆曲线密码学的加密算法,相比于RSA算法,ECC算法提供了更高的安全性和更短的密钥长度。
    • 其他还包括Diffie-Hellman、El Gamal、DSA(数字签名用)等算法。

三、哈希算法

  • 定义:也叫安全散列算法、消息摘要算法、杂凑算法,是一种将任意长度的输入数据输出为固定长度数据的算法,具有单向性,即不能通过输出数据反推出输入数据。
  • 特点:可实现数据签名、数据完整性校验等功能。
  • 常见算法:
    • MD5:一种加密散列函数算法,将任意长度的信息作为输入,并转换为128位(16字节)的固定长度信息,主要用于验证文件是否被篡改。但近年来,由于其哈希值长度较短,安全性逐渐受到质疑。
    • SHA系列:包括SHA-1、SHA-2(SHA-224、SHA-256、SHA-384、SHA-512)等算法,其中SHA-1算法可以生成160位(20字节)散列值,而SHA-2算法则是SHA-1算法的继承者,提供了更高的安全性。SHA系列算法广泛应用于文件传输校验、代码签名证书等领域。
    • 其他还包括MD2、MD4、HAVAL等算法,但部分算法由于安全性问题已逐渐被淘汰。

二、加密算法实现

本文将介绍几种Java中常用的加密解密算法,并提供相应的使用示例。

对称加密算法

DES算法

DES(Data Encryption Standard)是一种古老的对称加密算法,它以64位为分组长度,密钥长度为56位,8位用于奇偶校验。
在Java中,可以使用javax.crypto.Cipher类来执行DES加密和解密。

import com.alibaba.fastjson.JSON;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

/**
 * DES算法加解密工具类
 */
public class DESUtil {

    /**
     * 生成DES密钥
     *
     * @return SecretKey DES密钥
     * @throws NoSuchAlgorithmException 当DES算法不可用时抛出
     */
    public static SecretKey generateDESKey() throws NoSuchAlgorithmException {
        KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
        keyGenerator.init(56); // DES算法密钥长度为56位,这里每次调用随机都会生成新的密钥。
        return keyGenerator.generateKey();
    }

    /**
     * 生成固定DES密钥
     *
     * @return SecretKey DES密钥
     */
    public static SecretKey generateFixDESKey() throws UnsupportedEncodingException {
        // 定义一个8字节字符串key
        String fixedKey = "qwerasdf";

        // 使用固定的字节数组(64位)创建DES密钥
        return new SecretKeySpec(fixedKey.getBytes(StandardCharsets.UTF_8), "DES");
    }

    /**
     * 使用DES算法加密
     *
     * @param data      待加密的数据
     * @param secretKey DES密钥
     * @return 加密后的数据(Base64编码)
     * @throws Exception 加密过程中的异常
     */
    public static String encrypt(String data, SecretKey secretKey) throws Exception {
        Cipher cipher = Cipher.getInstance("DES");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        byte[] encryptedData = cipher.doFinal(data.getBytes());
        return Base64.getEncoder().encodeToString(encryptedData);
    }

    /**
     * 使用DES算法解密
     *
     * @param data      加密的数据(Base64编码)
     * @param secretKey DES密钥
     * @return 解密后的数据
     * @throws Exception 解密过程中的异常
     */
    public static String decrypt(String data, SecretKey secretKey) throws Exception {
        byte[] encryptedData = Base64.getDecoder().decode(data);
        Cipher cipher = Cipher.getInstance("DES");
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        byte[] decryptedData = cipher.doFinal(encryptedData);
        return new String(decryptedData);
    }

    // 工具类不应该有公共构造器
    private DESUtil() {
    }

    // 主方法用于测试工具类
    public static void main(String[] args) {
        try {
            // 生成DES密钥
            SecretKey secretKey = generateFixDESKey();

            System.out.println(JSON.toJSONString(secretKey));

            // 加密数据
            String originalString = "Hello, World!";
            String encryptedString = encrypt(originalString, secretKey);
            System.out.println("Encrypted: " + encryptedString);

            // 解密数据
            String decryptedString = decrypt(encryptedString, secretKey);
            System.out.println("Decrypted: " + decryptedString);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

AES算法

AES(Advanced Encryption Standard)是一种高级加密标准,是目前广泛使用的加密算法之一,提供多种密钥长度(如128位、192位、256位)。
在Java中,可以使用javax.crypto.Cipher类来执行AES加密和解密。

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

public class AESUtil {

    // AES算法名称
    private static final String AES_ALGORITHM = "AES";

    /**
     * 生成AES密钥
     *
     * @return SecretKey AES密钥
     * @throws NoSuchAlgorithmException 当AES算法不可用时抛出
     */
    public static SecretKey generateAESKey() throws NoSuchAlgorithmException {
        KeyGenerator keyGenerator = KeyGenerator.getInstance(AES_ALGORITHM);
        keyGenerator.init(128); // 设置密钥长度为128位
        return keyGenerator.generateKey();
    }

    /**
     * 生成AES特定密钥
     *
     * @return SecretKey AES密钥
     * @throws NoSuchAlgorithmException 当AES算法不可用时抛出
     */
    public static SecretKey generateFixAESKey() throws NoSuchAlgorithmException {
        // 定义一个16字节字符串key
        String fixedKey = "qwerasdfzxcvbnml";

        // 使用固定的字节数组(128位)创建DES密钥
        return new SecretKeySpec(fixedKey.getBytes(StandardCharsets.UTF_8), "AES");
    }

    /**
     * 使用AES算法加密
     *
     * @param data      待加密的数据
     * @param secretKey AES密钥
     * @return 加密后的数据(Base64编码)
     * @throws Exception 加密过程中的异常
     */
    public static String encrypt(String data, SecretKey secretKey) throws Exception {
        Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        byte[] encryptedData = cipher.doFinal(data.getBytes());
        return Base64.getEncoder().encodeToString(encryptedData);
    }

    /**
     * 使用AES算法解密
     *
     * @param data       加密的数据(Base64编码)
     * @param secretKey AES密钥
     * @return 解密后的数据
     * @throws Exception 解密过程中的异常
     */
    public static String decrypt(String data, SecretKey secretKey) throws Exception {
        byte[] encryptedData = Base64.getDecoder().decode(data);
        Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        byte[] decryptedData = cipher.doFinal(encryptedData);
        return new String(decryptedData);
    }

    // 工具类不应该有公共构造器
    private AESUtil() {
    }

    // 主方法用于测试工具类
    public static void main(String[] args) {
        try {
            // 生成AES密钥
            SecretKey secretKey = generateFixAESKey();

            // 加密数据
            String originalString = "Hello, World!";
            String encryptedString = encrypt(originalString, secretKey);
            System.out.println("Encrypted: " + encryptedString);

            // 解密数据
            String decryptedString = decrypt(encryptedString, secretKey);
            System.out.println("Decrypted: " + decryptedString);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

我们也可以使用组合算法来进行进一步的加密

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Base64;

public class AESUtil {

    // AES密钥的key,用来生成密钥。长度可以为128,192,256
    private static final String AES_KEY = "qwerasdfzxcvbnml";
    // AES算法名称
    private static final String AES_ALGORITHM = "AES";
    /**
     * 组合算法,它由三个部分组成:
     * AES:这是一个对称加密算法,用于加密和解密数据。
     * CBC:这是块密码的密码块链模式(Cipher Block Chaining),它使用一个初始化向量(IV)来混淆加密的数据。在CBC模式下,每个加密块都是基于前一个块的密文,这意味着如果加密了多个块,每个块的加密都会依赖于之前的加密结果。
     * PKCS5Padding:这是一种填充模式,用于将明文填充到下一个加密块的大小。在AES中,每个块的大小是128位(16字节),因此PKCS5Padding会根据块的大小来填充明文,以确保明文大小总是块大小的整数倍。
     * */
    private static final String AES_CBC_PKCS5_PADDING = "AES/CBC/PKCS5Padding";

    /**
     * 生成特定AES密钥
     *
     * @return SecretKey AES密钥
     */
    public static SecretKey generateAESKey() {
        // 使用固定的字节数组(128位)创建DES密钥
        return new SecretKeySpec(AES_KEY.getBytes(StandardCharsets.UTF_8), AES_ALGORITHM);
    }

    /**
     * 生成CBC初始化向量
     *
     * @return AlgorithmParameterSpec CBC初始化向量
     */
    public static AlgorithmParameterSpec generateIvParam() {
        return new IvParameterSpec(AES_KEY.getBytes());
    }

    /**
     * 使用AES算法加密
     *
     * @param data      待加密的数据
     * @param secretKey AES密钥
     * @return 加密后的数据(Base64编码)
     * @throws Exception 加密过程中的异常
     */
    public static String encrypt(String data, SecretKey secretKey, AlgorithmParameterSpec parameterSpec) throws Exception {
        Cipher cipher = Cipher.getInstance(AES_CBC_PKCS5_PADDING);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, parameterSpec);
        byte[] encryptedData = cipher.doFinal(data.getBytes());
        return Base64.getEncoder().encodeToString(encryptedData);
    }

    /**
     * 使用AES算法解密
     *
     * @param data       加密的数据(Base64编码)
     * @param secretKey AES密钥
     * @return 解密后的数据
     * @throws Exception 解密过程中的异常
     */
    public static String decrypt(String data, SecretKey secretKey, AlgorithmParameterSpec parameterSpec) throws Exception {
        byte[] encryptedData = Base64.getDecoder().decode(data);
        Cipher cipher = Cipher.getInstance(AES_CBC_PKCS5_PADDING);
        cipher.init(Cipher.DECRYPT_MODE, secretKey, parameterSpec);
        byte[] decryptedData = cipher.doFinal(encryptedData);
        return new String(decryptedData);
    }

    // 工具类不应该有公共构造器
    private AESUtil2() {
    }

    // 主方法用于测试工具类
    public static void main(String[] args) {
        try {
            // 生成AES密钥
            SecretKey secretKey = generateAESKey();
            // 生成CBC初始化向量
            AlgorithmParameterSpec ivParam = generateIvParam();

            // 加密数据
            String originalString = "Hello, World!";
            String encryptedString = encrypt(originalString, secretKey, ivParam);
            System.out.println("Encrypted: " + encryptedString);

            // 解密数据
            String decryptedString = decrypt(encryptedString, secretKey, ivParam);
            System.out.println("Decrypted: " + decryptedString);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

非对称加密算法

RSA算法

RSA(Rivest-Shamir-Adleman)是一种非对称加密算法,它包含公钥和私钥。公钥用于加密,私钥用于解密。
Java的KeyPairGenerator和Cipher类可以用来生成密钥对和执行加密解密操作。

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

/**
 * Rsa算法工具类
 * */
public class RSAUtil {

    //签名算法名称
    private static final String RSA_KEY_ALGORITHM = "RSA";

    //标准签名算法名称
    private static final String RSA_SIGNATURE_ALGORITHM = "SHA1withRSA";
    private static final String RSA2_SIGNATURE_ALGORITHM = "SHA256withRSA";

    //RSA密钥长度,默认密钥长度是1024,密钥长度必须是64的倍数,在512到65536位之间,不管是RSA还是RSA2长度推荐使用2048
    private static final int KEY_SIZE = 2048;

    /**
     * 生成密钥对
     *
     * @return 返回包含公私钥的map
     */
    public static Map<String, String> generateKey() {
        KeyPairGenerator keygen;
        try {
            keygen = KeyPairGenerator.getInstance(RSA_KEY_ALGORITHM);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("RSA初始化密钥出现错误,算法异常");
        }
        SecureRandom secrand = new SecureRandom();
        //初始化随机产生器
        secrand.setSeed("Alian".getBytes());
        //初始化密钥生成器
        keygen.initialize(KEY_SIZE, secrand);
        KeyPair keyPair = keygen.genKeyPair();
        //获取公钥并转成base64编码
        byte[] pub_key = keyPair.getPublic().getEncoded();
        String publicKeyStr = Base64.getEncoder().encodeToString(pub_key);
        //获取私钥并转成base64编码
        byte[] pri_key = keyPair.getPrivate().getEncoded();
        String privateKeyStr = Base64.getEncoder().encodeToString(pri_key);
        //创建一个Map返回结果
        Map<String, String> keyPairMap = new HashMap<>();
        keyPairMap.put("publicKeyStr", publicKeyStr);
        keyPairMap.put("privateKeyStr", privateKeyStr);
        return keyPairMap;
    }

    /**
     * 公钥加密(用于数据加密)
     *
     * @param data         加密前的字符串
     * @param publicKeyStr base64编码后的公钥
     * @return base64编码后的字符串
     * @throws Exception
     */
    public static String encryptByPublicKey(String data, String publicKeyStr) throws Exception {
        //Java原生base64解码
        byte[] pubKey = Base64.getDecoder().decode(publicKeyStr);
        //创建X509编码密钥规范
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pubKey);
        //返回转换指定算法的KeyFactory对象
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
        //根据X509编码密钥规范产生公钥对象
        PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
        //根据转换的名称获取密码对象Cipher(转换的名称:算法/工作模式/填充模式)
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        //用公钥初始化此Cipher对象(加密模式)
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        //对数据加密
        byte[] encrypt = cipher.doFinal(data.getBytes());
        //返回base64编码后的字符串
        return Base64.getEncoder().encodeToString(encrypt);
    }

    /**
     * 私钥解密(用于数据解密)
     *
     * @param data          解密前的字符串
     * @param privateKeyStr 私钥
     * @return 解密后的字符串
     * @throws Exception
     */
    public static String decryptByPrivateKey(String data, String privateKeyStr) throws Exception {
        //Java原生base64解码
        byte[] priKey = Base64.getDecoder().decode(privateKeyStr);
        //创建PKCS8编码密钥规范
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(priKey);
        //返回转换指定算法的KeyFactory对象
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
        //根据PKCS8编码密钥规范产生私钥对象
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        //根据转换的名称获取密码对象Cipher(转换的名称:算法/工作模式/填充模式)
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        //用私钥初始化此Cipher对象(解密模式)
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        //对数据解密
        byte[] decrypt = cipher.doFinal(Base64.getDecoder().decode(data));
        //返回字符串
        return new String(decrypt);
    }

    /**
     * 私钥加密(用于数据签名)
     *
     * @param data          加密前的字符串
     * @param privateKeyStr base64编码后的私钥
     * @return base64编码后后的字符串
     * @throws Exception
     */
    public static String encryptByPrivateKey(String data, String privateKeyStr) throws Exception {
        //Java原生base64解码
        byte[] priKey = Base64.getDecoder().decode(privateKeyStr);
        //创建PKCS8编码密钥规范
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(priKey);
        //返回转换指定算法的KeyFactory对象
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
        //根据PKCS8编码密钥规范产生私钥对象
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        //根据转换的名称获取密码对象Cipher(转换的名称:算法/工作模式/填充模式)
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        //用私钥初始化此Cipher对象(加密模式)
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        //对数据加密
        byte[] encrypt = cipher.doFinal(data.getBytes());
        //返回base64编码后的字符串
        return Base64.getEncoder().encodeToString(encrypt);
    }

    /**
     * 公钥解密(用于数据验签)
     *
     * @param data         解密前的字符串
     * @param publicKeyStr base64编码后的公钥
     * @return 解密后的字符串
     * @throws Exception
     */
    public static String decryptByPublicKey(String data, String publicKeyStr) throws Exception {
        //Java原生base64解码
        byte[] pubKey = Base64.getDecoder().decode(publicKeyStr);
        //创建X509编码密钥规范
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pubKey);
        //返回转换指定算法的KeyFactory对象
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
        //根据X509编码密钥规范产生公钥对象
        PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
        //根据转换的名称获取密码对象Cipher(转换的名称:算法/工作模式/填充模式)
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        //用公钥初始化此Cipher对象(解密模式)
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
        //对数据解密
        byte[] decrypt = cipher.doFinal(Base64.getDecoder().decode(data));
        //返回字符串
        return new String(decrypt);
    }

    /**
     * RSA签名
     *
     * @param data     待签名数据
     * @param priKey   私钥
     * @param signType RSA或RSA2
     * @return 签名
     * @throws Exception
     */
    public static String sign(byte[] data, byte[] priKey, String signType) throws Exception {
        //创建PKCS8编码密钥规范
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(priKey);
        //返回转换指定算法的KeyFactory对象
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
        //根据PKCS8编码密钥规范产生私钥对象
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        //标准签名算法名称(RSA还是RSA2)
        String algorithm = RSA_KEY_ALGORITHM.equals(signType) ? RSA_SIGNATURE_ALGORITHM : RSA2_SIGNATURE_ALGORITHM;
        //用指定算法产生签名对象Signature
        Signature signature = Signature.getInstance(algorithm);
        //用私钥初始化签名对象Signature
        signature.initSign(privateKey);
        //将待签名的数据传送给签名对象(须在初始化之后)
        signature.update(data);
        //返回签名结果字节数组
        byte[] sign = signature.sign();
        //返回Base64编码后的字符串
        return Base64.getEncoder().encodeToString(sign);
    }

    /**
     * RSA校验数字签名
     *
     * @param data     待校验数据
     * @param sign     数字签名
     * @param pubKey   公钥
     * @param signType RSA或RSA2
     * @return boolean 校验成功返回true,失败返回false
     */
    public static boolean verify(byte[] data, byte[] sign, byte[] pubKey, String signType) throws Exception {
        //返回转换指定算法的KeyFactory对象
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
        //创建X509编码密钥规范
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pubKey);
        //根据X509编码密钥规范产生公钥对象
        PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
        //标准签名算法名称(RSA还是RSA2)
        String algorithm = RSA_KEY_ALGORITHM.equals(signType) ? RSA_SIGNATURE_ALGORITHM : RSA2_SIGNATURE_ALGORITHM;
        //用指定算法产生签名对象Signature
        Signature signature = Signature.getInstance(algorithm);
        //用公钥初始化签名对象,用于验证签名
        signature.initVerify(publicKey);
        //更新签名内容
        signature.update(data);
        //得到验证结果
        return signature.verify(sign);
    }

    public static void main(String[] args) throws Exception {
        Map<String, String> keyMap = RSAUtil2.generateKey();
        String publicKeyStr = keyMap.get("publicKeyStr");
        String privateKeyStr = keyMap.get("privateKeyStr");
        System.out.println("-----------------生成的公钥和私钥------------------------------");
        System.out.println("获取到的公钥:" + publicKeyStr);
        System.out.println("获取到的私钥:" + privateKeyStr);
        // 待加密数据
        String data = "tranSeq=1920542585&amount=100&payType=wechat";
        // 公钥加密
        System.out.println("-----------------加密和解密------------------------------");
        System.out.println("待加密的数据:" + data);
        String encrypt = RSAUtil2.encryptByPublicKey(data, publicKeyStr);
        System.out.println("加密后数据:" + encrypt);
        // 私钥解密
        String decrypt = RSAUtil2.decryptByPrivateKey(encrypt, privateKeyStr);
        System.out.println("解密后数据:" + decrypt);

        // 数字签名
        System.out.println("待签名的数据:" + data);
        String sign = RSAUtil2.sign(data.getBytes(), Base64.getDecoder().decode(privateKeyStr), "RSA");
        System.out.println("数字签名结果:" + sign);
        boolean verify = RSAUtil2.verify(data.getBytes(), Base64.getDecoder().decode(sign), Base64.getDecoder().decode(publicKeyStr), "RSA");
        System.out.println("数字签名验证结果:" + verify);

    }
}

使用RSA进行加密和解密时,由于RSA算法的性能问题,通常不直接用于加密大量数据,而是用于加密对称加密算法的密钥(如AES密钥),然后使用该对称密钥加密实际数据。

注意事项:

  • 密钥对的生成、存储和传输需要特别小心,以避免私钥泄露。
  • 在实际应用中,密钥对可能需要持久化存储到文件系统或数据库中,但应确保存储的安全性。
  • 加密和解密过程中,数据编码(如getBytes())应使用统一的字符集(如UTF-8),以避免乱码问题。

哈希算法

MD5算法

MD5(Message-Digest Algorithm 5)是一种常用的哈希算法,它可以接受任意长度的输入(信息),并输出一个128位的哈希值,通常以32位十六进制数表示。

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class MD5Util {

    /**
     * 获取字符串的MD5哈希值
     *
     * @param data 输入字符串
     * @return 32位十六进制MD5哈希值
     * @throws NoSuchAlgorithmException 当MD5算法不可用时抛出
     */
    public static String getMD5(String data) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(data.getBytes());
        byte[] digest = md.digest();
        return bytesToHex(digest);
    }

    /**
     * 将字节数组转换为十六进制字符串
     *
     * @param bytes 字节数组
     * @return 十六进制字符串
     */
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
	
	// 工具类不应该有公共构造器
    private MD5Util() {
    }

    // 主方法用于测试工具类
    public static void main(String[] args) {
        try {
            String originalString = "Hello, World!";
            String md5String = MD5Util.getMD5(originalString);
            System.out.println("Original: " + originalString);
            System.out.println("MD5 Hash: " + md5String);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }
}

SHA-1算法

SHA-1(Secure Hash Algorithm 1)是一种加密哈希函数,它接收一个输入(信息)并输出一个160位的哈希值,通常以40位十六进制数表示。

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class SHA1Util {

    /**
     * 获取字符串的SHA-1哈希值
     *
     * @param data 输入字符串
     * @return 40位十六进制SHA-1哈希值
     * @throws NoSuchAlgorithmException 当SHA-1算法不可用时抛出
     */
    public static String getSHA1(String data) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("SHA-1");
        md.update(data.getBytes());
        byte[] digest = md.digest();
        return bytesToHex(digest);
    }

    /**
     * 将字节数组转换为十六进制字符串
     *
     * @param bytes 字节数组
     * @return 十六进制字符串
     */
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

	// 工具类不应该有公共构造器
    private SHA1Util() {
    }

    // 主方法用于测试工具类
    public static void main(String[] args) {
        try {
            String originalString = "Hello, World!";
            String sha1String = SHA1Util.getSHA1(originalString);
            System.out.println("Original: " + originalString);
            System.out.println("SHA-1 Hash: " + sha1String);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }
}

SHA-256算法

它生成数据的固定长度(如256位)摘要,用于验证数据的完整性。

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class SHA256Util {

    /**
     * 获取字符串的SHA-256哈希值
     *
     * @param data 输入字符串
     * @return 64位十六进制SHA-256哈希值
     * @throws NoSuchAlgorithmException 当SHA-256算法不可用时抛出
     */
    public static String getSHA256(String data) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        md.update(data.getBytes());
        byte[] digest = md.digest();
        return bytesToHex(digest);
    }

    /**
     * 将字节数组转换为十六进制字符串
     *
     * @param bytes 字节数组
     * @return 十六进制字符串
     */
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
    
	// 工具类不应该有公共构造器
    private SHA256Util() {
    }

	// 主方法用于测试工具类
    public static void main(String[] args) {
        try {
            String originalString = "Hello, World!";
            String sha256String = SHA256Util.getSHA256(originalString);
            System.out.println("Original: " + originalString);
            System.out.println("SHA-256 Hash: " + sha256String);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }
}

参考文章:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值