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

[工具] 数据加密和解密

作者: 巨馍蘸酱 | 来源:发表于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