Java中的加解密

一、Base64编码

Base64,它是一种编码方式,算不上一种加密算法。它就是使用64个可打印字符来表示二进制数据的方法。Base64一般用于在HTTP协议下传输二进制数据,由于HTTP协议是文本协议,所以在HTTP协议下传输二进制数据需要将二进制数据转换为字符数据。然而直接转换是不行的,此时可以将子节序列用Base64编码。

Java提供了Base64的编解码器,直接使用即可。

public class Base64Test {
    public static final Base64.Encoder encoder = Base64.getEncoder();
    public static final Base64.Decoder decoder = Base64.getDecoder();

    public static void main(String[] args) {
        String data = "你好吗?我很好";
        //编码
        String base64EncodeString = encoder.encodeToString(data.getBytes());
        //解码
        byte[] bytes = decoder.decode(base64EncodeString);
        System.out.println(new String(bytes));
    }
}

二、单向加密

我们都知道哈希算法(Hash,又称摘要算法Digest),它可以对任意一组输入数据进行计算,并得到一个固定长度的输出摘要,它是不可逆的。单向加密即只能加密,无法通过加密后的密文加密还原数据,所以被称为单向加密,也是不可逆的,单向加密可用于做数据加签验签,效验数据是否被篡改。常见的单向加密算法有:

  • MD5:message-digest algorithm 5 (信息-摘要算法)一种哈希算法。
  • SHA:Secure Hash Algorithm,安全散列算法,一种哈希算法。SHA算法实际上是一个系列,包括SHA-0(已废弃)、SHA-1、SHA-256、SHA-512等。
  • HMAC:Hash Message Authentication Code, Hmac算法就是一种基于密钥的消息认证码算法,是一种更安全的消息摘要算法。Hmac算法总是和某种哈希算法配合起来用的,常见的有HmacMD5,HmacSHA1,HmacSHA256,HmacSHA384,HmacSHA512。(HMAC相当于hash(密钥+input)
public class OneWayEncryptUtils {
    private static final char[] HEX_CHARS = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
    private static final String MD5 = "MD5";
    private static final String SHA256 = "SHA-256";
    private static final String MAC_MD5 = "HmacMD5";

    private static void checkSrcString(String src){
        if(src == null || "".equals(src)){
            throw new IllegalArgumentException("源数据不能为空");
        }
    }

    private static String encrypt(byte[] src,String algorithm) throws NoSuchAlgorithmException {
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
        byte[] bytes = messageDigest.digest(src);
        return encodeHex(bytes);
    }

    /**
     * MD5进行单向加密
     */
    public static String MD5Encrypt(String src){
        try {
            checkSrcString(src);
            return encrypt(src.getBytes(),MD5);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * SHA256进行单向加密
     */
    public static String SHA256Encrypt(String src){
        try {
            checkSrcString(src);
            return encrypt(src.getBytes(),SHA256);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * HamcMD5使用随机生成的密钥进行单向加密,返回密钥和密文
     */
    public static Map<String,byte[]> HmacEncrypt(String src) throws Exception {
        checkSrcString(src);
        Map<String,byte[]> hmacInfoMap = new HashMap<>(2);
        //1.获取HmacMD5的密钥生成器
        KeyGenerator keyGenerator = KeyGenerator.getInstance(MAC_MD5);
        //2.随机生成一个密钥
        SecretKey key = keyGenerator.generateKey();
        Mac mac = Mac.getInstance(MAC_MD5);
        //3.初始化密钥
        mac.init(key);
        //4.加密
        hmacInfoMap.put("encryptCode",mac.doFinal(src.getBytes()));
        hmacInfoMap.put("encryptKey",key.getEncoded());
        return hmacInfoMap;
    }

    /**
     * HamcMD5使用外部提供的密钥进行单向加密,返回密文
     */
    public static byte[] HmacEncrypt(String src, byte[] sKey) throws Exception {
        checkSrcString(src);
        SecretKey secretKey = new SecretKeySpec(sKey, MAC_MD5);
        Mac mac = Mac.getInstance(MAC_MD5);
        mac.init(secretKey);
        return mac.doFinal(src.getBytes());
    }

    private static String encodeHex(byte[] bytes) {
        char[] chars = new char[32];
        for(int i = 0; i < chars.length; i += 2) {
            byte b = bytes[i / 2];
            chars[i] = HEX_CHARS[b >>> 4 & 15];
            chars[i + 1] = HEX_CHARS[b & 15];
        }
        return new String(chars);
    }
}

三、双向加密

可逆加密,根据密文可解析出原文,一般用于网络数据传输前后对数据加解密。双向加密又分对称加密和非对称加密。

  • 对称加密又叫单密钥加密,是通过单个密钥进行加解密的算法。
  • 非对称加密是用公钥和私钥来加解密的算法,私钥可以用来解密公钥加密的密文,公钥无法揭秘私钥加密的密文。

1.对称加密

常见的对称加密算法有如下几种:

算法密钥长度工作模式填充模式
AES128/192/256ECB/CBC/PCBC/CTR/…NoPadding/PKCS5Padding/PKCS7Padding/…
DES56/64ECB/CBC/PCBC/CTR/…NoPadding/PKCS5Padding/…
IDEA128ECBPKCS5Padding/PKCS7Padding/…

密钥长度直接决定加密强度,而 工作模式和填充模式可以看成是对称加密算法的参数和格式选择 。Java标准库提供的算法实现并不包括所有的工作模式和所有填充模式,但是通常我们只需要挑选常用的使用就可以了。

Java提供了一些用于对称加密的类,常用的如下:

  1. KeyGenerator:对称加密的密钥生成器。支持的加密算法有:AES、ARCFOUR、Blowfish、DES、DESede、Hmac、RC2。(其中init(int keySize)可用于设置密钥生成器生成的密钥长度)
  2. SecretKey:代表密钥。
  3. Cipher:Java提供的用于做对称加密算法中加解密的工具。
    1. Cipher.ENCRYPT_MODE表示加密模式
    2. Cipher.DECRYPT_MODE表示解密模式
  4. SecureRandom:安全的随机种子。可用于生成指定长度且随机的子节数组。
  5. IvParameterSpec:代表算法参数规范,里面封装了向量Iv,使用CBC 有向量模式时,必须传入,如果是ECB(无向量模式)则可以不传。

Java对称加密编程流程如下:

  1. 根据算法名称和密钥实例化SecretKey对象实例;
  2. 根据算法名称/工作模式/填充模式获取Cipher实例;
  3. 初始化Cipher实例,需要指定SecretKey、加解密模式、CBC模式需要传入向量;
  4. 加/解密。

AES加解密实现

public class AesUtils {
    private static final String CIPHER_VALUE = "AES/CBC/PKCS5Padding";
    private static final String algorithm = "AES";
    
    public static byte[] encrypy(byte[] sKey, byte[] srcBytes) throws Exception {
        SecretKey secretKey = new SecretKeySpec(sKey, algorithm);
        Cipher cipher = Cipher.getInstance(CIPHER_VALUE);
        //CBC模式需要生成一个16子节的向量,此处使用SecureRandom生成
        SecureRandom sr = SecureRandom.getInstanceStrong();
        byte[] Iv = sr.generateSeed(16);
        IvParameterSpec IvPS = new IvParameterSpec(Iv);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, IvPS);
        return mergeByteArray(Iv,cipher.doFinal(srcBytes));
    }

    public static byte[] decrypy(byte[] sKey, byte[] targetBytes) throws Exception {
        //获取Iv
        byte[] Iv = new byte[16];
        System.arraycopy(targetBytes,0,Iv,0,16);
        //获取密文
        byte[] encryptBytes = new byte[targetBytes.length - 16];
        System.arraycopy(targetBytes,16,encryptBytes,0,targetBytes.length - 16);
        SecretKey secretKey = new SecretKeySpec(sKey, algorithm);
        Cipher cipher = Cipher.getInstance(CIPHER_VALUE);
        cipher.init(Cipher.DECRYPT_MODE,secretKey,new IvParameterSpec(Iv));
        return cipher.doFinal(encryptBytes);
    }

    private static byte[] mergeByteArray(byte[] bytes1, byte[] bytes2){
        byte[] result = new byte[bytes1.length + bytes2.length];
        System.arraycopy(bytes1,0,result,0,bytes1.length);
        System.arraycopy(bytes2,0,result,bytes1.length,bytes2.length);
        return result;
    }
}

生成密钥进行测试

public static void main(String[] args) throws Exception {
	String src = "你好吗,我很好";
	KeyGenerator keyGenerator = KeyGenerator.getInstance(algorithm);
	keyGenerator.init(128);
	byte[] sKey = keyGenerator.generateKey().getEncoded();
	byte[] encryptBytes = AesUtils.encrypy(sKey,src.getBytes());
	System.out.println(new String(AesUtils.decrypy(sKey, encryptBytes)));
	//你好吗,我很好
}

参考:https://blog.csdn.net/wangmx1993328/article/details/106170060

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值