Java加密与解密笔记(二) 对称加密

前面的仅仅是做了编码或者摘要,下面看看真正的加密技术。

DES

复制代码
public class DESUtil {

    static final String ALGORITHM = "DES";
    
    /**
     * 生成文本格式的DES Key
     * @return
     * @throws Exception
     */
    public static String getKey() throws Exception{
        KeyGenerator generator = KeyGenerator.getInstance(ALGORITHM);
        generator.init(new SecureRandom());//加盐 
        return Base64Util.encode(generator.generateKey().getEncoded());
    }
    
    /**
     * 从文本 格式DES Key转换成SecretKey对象
     * @param key
     * @return
     */
    public static SecretKey parseKeyFromString(String key)throws Exception{
        DESKeySpec desKeySpec = new DESKeySpec(Base64Util.decode(key));
        SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM);
        SecretKey secretKey = factory.generateSecret(desKeySpec);
        return secretKey;
    }
    
    /**
     * DES 加密
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static String encrypt(String data,String key)throws Exception{
        SecretKey secretKey = parseKeyFromString(key);
        Cipher cipher = Cipher.getInstance(ALGORITHM); 
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        byte[] bytes = cipher.doFinal(data.getBytes("UTF-8"));
        return Base64Util.encode(bytes);
    }
    
    /**
     * DES 解密
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static String decrypt(String data,String key)throws Exception{
        SecretKey secretKey = parseKeyFromString(key);
        Cipher cipher = Cipher.getInstance(ALGORITHM); 
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        byte[] bytes = cipher.doFinal(Base64Util.decode(data));
        return new String(bytes,"UTF-8");
    }
    
    public static void main(String[] args)throws Exception {
        String str = "Hello,DES";
        String key = getKey();
        System.out.println("原文:" + str);
        System.out.println("密钥:" + key);
        String encryptedStr = encrypt(str, key);
        System.out.println("加密后:" + encryptedStr);
        String decryptedStr = decrypt(encryptedStr, key);
        System.out.println("解密后:" + decryptedStr);
    }
    
}
复制代码

 

类似DESKeySpec,Java中很多*KeySpec的类都实现了KeySpec的空接口,Java只关心某个类是否是一种Key的实现,至于具体如何实现的是具体加密解密算法要关心的。

再次看到Base64的身影,由此可以看出,Base64其实充当着字符串和byte数组之间的转换器,真实的的密钥数据其实是byte类型的,但是在阅读和传输过程中字符串比较方便,所以我们能看到的很多密钥信息其实都是Base64编码。

Ciper为密文工具类,它是一个很高级的抽象类,有很多种Cipher的实现,可以通过Cipher.getInstance()方法获取到。

getInstance方法接收的算法名称非常多:

测试:

原文:Hello,DES
密钥:8ePQx0m1I4k=
加密后:bM06WR8OIL2sQOB8SUSXRA==
解密后:Hello,DES

 AES

AES是DES的升级版,解决了DES的很多不足,上述DES代码改成AES的改动很小:

复制代码
static final String ALGORITHM = "AES";    
   /**
     * 从文本 格式AES Key转换成SecretKey对象
     * @param key
     * @return
     */
    public static SecretKey parseKeyFromString(String key)throws Exception{
        SecretKey secretKey = new SecretKeySpec(Base64Util.decode(key), ALGORITHM);
        return secretKey;
    }    
复制代码

 

 PBE

PBE与DES、AES同属对称加密,不同之处在于其密钥可以由用户管理,即密钥可以不用通过KeyGenerator来生成,可以是任意字符。为了增强安全性,PBE强制必须要有参数(java.security.spec.AlgorithmParameterSpec),可以理解为强制加盐,否则将报错。

复制代码
public class PBEUtil {

    static final String ALGORITHM = "PBEWITHMD5andDES";
    
    private static SecretKey parseKeyFromString(String key) throws Exception{
        PBEKeySpec pbeKey = new PBEKeySpec(key.toCharArray());
        SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM);
        return factory.generateSecret(pbeKey);
    }
    
    /**
     * PBE 加密
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static String encrypt(String data,String key,byte[] salt)throws Exception{
        SecretKey secretKey = parseKeyFromString(key);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        PBEParameterSpec params = new PBEParameterSpec(salt, 100);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey,params);
        byte[] bytes = cipher.doFinal(data.getBytes("UTF-8"));
        return Base64Util.encode(bytes);
    }
    
    /**
     * DES 解密
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static String decrypt(String data,String key,byte[] salt)throws Exception{
        SecretKey secretKey = parseKeyFromString(key);
        Cipher cipher = Cipher.getInstance(ALGORITHM); 
        PBEParameterSpec params = new PBEParameterSpec(salt, 100);
        cipher.init(Cipher.DECRYPT_MODE, secretKey,params);
        byte[] bytes = cipher.doFinal(Base64Util.decode(data));
        return new String(bytes,"UTF-8");
    }
    
    public static void main(String[] args)throws Exception {
        String str = "Hello,PBE";
        String key = "abc";
        byte[] salt = new byte[8];
        new Random().nextBytes(salt);
        System.out.println("原文:" + str);
        System.out.println("密钥:" + key);
        String encryptedStr = encrypt(str, key,salt);
        System.out.println("加密后:" + encryptedStr);
        String decryptedStr = decrypt(encryptedStr, key,salt);
        System.out.println("解密后:" + decryptedStr);
    }
    
}
复制代码

 

 

参考资料:

http://snowolf.iteye.com/blog/380034

http://snowolf.iteye.com/blog/380761

posted @   at0x7c00  阅读(828)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
CSDN - ITeye - GitHub  |  HuQiao's Blog  |  业余经营:IT快报
点击右上角即可分享
微信分享提示