美文网首页
[工具] 数据加密和解密

[工具] 数据加密和解密

作者: 巨馍蘸酱 | 来源:发表于2022-12-11 14:46 被阅读0次

数据加密和解密

数据加密 的基本过程,就是对原来为 明文 的文件或数据按 某种算法 进行处理,使其成为 不可读 的一段代码,通常称为 “密文”。通过这样的途径,来达到 保护数据 不被 非法人窃取、阅读的目的。

加密 的 逆过程 为 解密,即将该 编码信息 转化为其 原来数据 的过程

对称加密算法 (AES / DES / 3DES)

对称式加密就是加密和解密使用同一个密钥, 又称为 共享密钥加密算法

AES 本身就是为了取代 DES 的,AES 具有更好的 安全性、效率 和 灵活性。[1]

AES 加密算法是密码学中的 高级加密标准,该加密算法采用 对称分组密码体制,密钥长度的最少支持为 128 位、 192 位、256 位,分组长度 128 位,算法应易于各种硬件和软件实现。这种加密算法是美国联邦政府采用的 区块加密标准。[1]

非对称加密算法 (RSA / DSA / ECC)

非对称式加密 就是加密和解密 使用两个不同的密钥, 又称为 公开密钥加密算法, 通常有两个密钥 公钥(public key)私钥(private key)

散列算法 (MD5 / SHA1 / HMAC)

Hash算法: MD2 / MD4 / MD5 / HAVAL / SHA / SHA-1 / HMAC / HMAC-MD5 / HMAC-SHA1

MD5 用的是 哈希函数,它的典型应用是对一段信息产生 信息摘要,以 防止被篡改。严格来说,MD5 不是一种 加密算法 而是 摘要算法。无论是多长的输入,MD5 都会输出长度为 128bits 的一个串 (通常用 16 进制 表示为 32 个字符)

SHA1 是和 MD5 一样流行的 消息摘要算法,然而 SHA1 比 MD5 的 安全性更强

java 实现

AES

public class AES256Util {

    /**
     * 密钥, 256位32个字节
     */
    public static final String DEFAULT_SECRET_KEY = "iNsLseFmH82LdIz14LsMwqBcZb02xIAd";

    /**
     * 初始向量IV, 初始向量IV的长度规定为128位16个字节, 初始向量的来源为随机生成.
     */
    private static final byte[] KEY_VI = "jI46Ql9owOk0zPrN".getBytes();

    /**
     * 加密解密算法/加密模式/填充方式
     */
    private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";

    private static final String AES = "AES";

    private static java.util.Base64.Encoder base64Encoder = java.util.Base64.getEncoder();
    private static java.util.Base64.Decoder base64Decoder = java.util.Base64.getDecoder();

    /**
     * AES加密
     */
    public static String encode(String key, String content) {
        try {
            javax.crypto.SecretKey secretKey = new javax.crypto.spec.SecretKeySpec(key.getBytes(), AES);
            javax.crypto.spec.IvParameterSpec iv = new javax.crypto.spec.IvParameterSpec(KEY_VI);

            javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance(CIPHER_ALGORITHM);
            cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, secretKey, iv);

            // 获取加密内容的字节数组(这里要设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码
            byte[] byteEncode = content.getBytes(java.nio.charset.StandardCharsets.UTF_8);
            // 根据密码器的初始化方式加密
            byte[] byteAES = cipher.doFinal(byteEncode);

            // 将加密后的数据转换为字符串
            return base64Encoder.encodeToString(byteAES);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * AES解密
     */
    public static String decode(String key, String content) {
        try {
            javax.crypto.SecretKey secretKey = new javax.crypto.spec.SecretKeySpec(key.getBytes(), AES);
            javax.crypto.spec.IvParameterSpec iv = new javax.crypto.spec.IvParameterSpec(KEY_VI);

            javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance(CIPHER_ALGORITHM);
            cipher.init(javax.crypto.Cipher.DECRYPT_MODE, secretKey, iv);

            // 将加密并编码后的内容解码成字节数组
            byte[] byteContent = base64Decoder.decode(content);
            // 解密
            byte[] byteDecode = cipher.doFinal(byteContent);

            return new String(byteDecode, java.nio.charset.StandardCharsets.UTF_8);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {
        String dbPassword = "abc123def456";
        String encryptDbPwd = AES256Util.encode(DEFAULT_SECRET_KEY, dbPassword);
        System.out.println("encrypt: " + encryptDbPwd);

        String decrypt = AES256Util.decode(DEFAULT_SECRET_KEY, encryptDbPwd);
        System.out.println("decrypt: " + decrypt);
    }
}

RSA


import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;


public class RSAUtil {
    private String algorithm = "RSA";
    private Integer keySize = 1024;
    private String publicKeyFile = "/var/tmp/temp_key_pub";
    private String privateKeyFile = "/var/tmp/temp_key_pri";

    public static void main(String[] args) {
        RSAUtil rsaUtil = new RSAUtil();

        Map<String, String> keyPairMap = rsaUtil.initKeyPair();
        String publicKey = keyPairMap.get("publicKey");
        String privateKey = keyPairMap.get("privateKey");
        System.out.println("公钥:");
        System.out.println(publicKey);
        System.out.println();

        System.out.println("私钥:");
        System.out.println(privateKey);
        System.out.println();

        String source = "Hello World";
        System.out.println("待加密字符串:" + source);
        System.out.println();

        String strEncrypt = rsaUtil.encrypt(source);
        System.out.println("加密后的字符串:");
        System.out.println(strEncrypt);
        System.out.println();

        String strDecrypt = rsaUtil.decrypt(strEncrypt);
        System.out.println("解密后的字符串:");
        System.out.println(strDecrypt);
    }

    // MARK: 私有方法

    /**
     * 生成密钥对
     *
     * @return 返回map集合,其中包含publicKey与privateKey
     * @throws NoSuchAlgorithmException
     */
    private Map<String, Key> generateKeyPair() throws NoSuchAlgorithmException {
        /**
         * RSA算法要求有一个可信任的随机数源
         */
        SecureRandom secureRandom = new SecureRandom();

        /**
         * 为RSA算法创建一个KeyPairGenerator对象
         */
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);

        /**
         * 利用上面的随机数据源初始化这个KeyPairGenerator对象
         */
        keyPairGenerator.initialize(keySize, secureRandom);

        /**
         * 生成密匙对
         */
        KeyPair keyPair = keyPairGenerator.generateKeyPair();

        /**
         * 得到公钥
         */
        Key publicKey = keyPair.getPublic();

        /**
         * 得到私钥
         */
        Key privateKey = keyPair.getPrivate();

        Map<String, Key> keyPairMap = new HashMap<>();
        keyPairMap.put("publicKey", publicKey);
        keyPairMap.put("privateKey", privateKey);

        return keyPairMap;
    }

    /**
     * 获取文件中获取密钥对象
     *
     * @param fileName 文件名
     * @return 密钥对象
     */
    private Key getKeyFromFile(String fileName) {
        Key key = null;
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(new FileInputStream(fileName));
            key = (Key) ois.readObject();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                ois.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return key;
    }

    /**
     * 将密钥对生成到文件中
     */
    private void generateKeyPairToFiles() {
        ObjectOutputStream oosPublicKey = null;
        ObjectOutputStream oosPrivateKey = null;
        try {
            oosPublicKey = new ObjectOutputStream(new FileOutputStream(publicKeyFile));
            oosPrivateKey = new ObjectOutputStream(new FileOutputStream(privateKeyFile));

            Map<String, Key> keyPairMap = generateKeyPair();
            Key publicKey = keyPairMap.get("publicKey");
            Key privateKey = keyPairMap.get("privateKey");

            oosPublicKey.writeObject(publicKey);
            oosPrivateKey.writeObject(privateKey);

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                /**
                 * 清空缓存,关闭文件输出流
                 */
                oosPublicKey.close();
                oosPrivateKey.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    // MARK: 公有方法

    /**
     * 初始化密钥对文件
     *
     * @return 返回密钥对信息【publicKey(公钥字符串)、、privateKey(私钥字符串)】
     */
    public Map<String, String> initKeyPair() {
        Map<String, String> keyPairMap = new HashMap<>();
        File publicFile = new File(publicKeyFile);
        File privateFile = new File(privateKeyFile);

        /**
         * 判断是否存在公钥和私钥文件
         */
        if (!publicFile.exists() || !privateFile.exists()) {
            generateKeyPairToFiles();
        }

        Key publicKey = getKeyFromFile(publicKeyFile);
        Key privateKey = getKeyFromFile(privateKeyFile);

        byte[] publicKeyBytes = publicKey.getEncoded();
        byte[] privateKeyBytes = privateKey.getEncoded();

        String publicKeyBase64 = Base64.getEncoder().encodeToString(publicKeyBytes);
        String privateKeyBase64 = Base64.getEncoder().encodeToString(privateKeyBytes);

        /**
         * 公钥字符串
         */
        keyPairMap.put("publicKey", publicKeyBase64);
        /**
         * 私钥字符串
         */
        keyPairMap.put("privateKey", privateKeyBase64);


        return keyPairMap;
    }

    /**
     * 加密方法
     *
     * @param source 源数据
     * @return 加密后的字符串
     */
    public String encrypt(String source) {
        Key publicKey = getKeyFromFile(publicKeyFile);

        String encryptSource = null;
        try {
            /**
             * 得到Cipher对象来实现对源数据的RSA加密
             */
            Cipher cipher = Cipher.getInstance(algorithm);
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] bytes = source.getBytes();

            /**
             * 执行加密操作
             */
            encryptSource = Base64.getEncoder().encodeToString(cipher.doFinal(bytes));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return encryptSource;
    }

    /**
     * 解密方法
     *
     * @param source 密文
     * @return 解密后的字符串
     */
    public String decrypt(String source) {
        Key privateKey = getKeyFromFile(privateKeyFile);

        String decryptSource = null;
        try {
            /**
             * 得到Cipher对象对已用公钥加密的数据进行RSA解密
             */
            Cipher cipher = Cipher.getInstance(algorithm);
            cipher.init(Cipher.DECRYPT_MODE, privateKey);

            /**
             * 执行解密操作
             */
            byte[] bytes = Base64.getDecoder().decode(source);
            decryptSource = new String(cipher.doFinal(bytes), "UTF-8");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return decryptSource;
    }
}

鸣谢


  1. https://zhuanlan.zhihu.com/p/347114235

相关文章

网友评论

      本文标题:[工具] 数据加密和解密

      本文链接:https://www.haomeiwen.com/subject/acpfqdtx.html