【java】常用加密

1. base64加密

从现在加密算法的复杂性来看Base64这种都不好意思说自己是加密,不过对于完全不懂计算机的人来说也够用了。采用Base64编码具有不可读性,即所编码的数据不会被人用肉眼所直接看到。
Base64编码一般用于url的处理,或者说任何你不想让普通人一眼就知道是啥的东西都可以用Base64编码处理后再发布在网络上。

1.1 jdk原生实现

/**
     * 使用jdk原生实现base64
     */
    @Test
    public void test1() throws UnsupportedEncodingException {
        String str = "陈彦杰";
        //编码 1.8才提供
        Base64.Encoder encoder = Base64.getEncoder();
        String encoderStr = encoder.encodeToString(str.getBytes("utf-8"));
        System.out.println("encoderStr:" + encoderStr);//6ZmI5b2m5p2w
        //解码
        Base64.Decoder decoder = Base64.getDecoder();
        byte[] decode = decoder.decode(encoderStr.getBytes());
        String decoderStr = new String(decode, "utf-8");
        System.out.println("decoderStr:" + decoderStr);

    }

1.2 commons-codec实现

/**
     * 使用commons-codec实现base64
     */
    @Test
    public void test2() throws UnsupportedEncodingException {
        String str = "陈彦杰";
        //编码
        String encoderStr = org.apache.commons.codec.binary.Base64.encodeBase64String(str.getBytes(UTF8));
        System.out.println("encoderStr:" + encoderStr);//6ZmI5b2m5p2w
        //解码
        byte[] bytes = org.apache.commons.codec.binary.Base64.decodeBase64(encoderStr.getBytes());
        String decoderStr = new String(bytes, UTF8);
        System.out.println("decoderStr:" + decoderStr);

    }

2. url加密

2.1 jdk原生实现

/**
     * 使用jdk原生实现URL编码
     */
    @Test
    public void test1() throws UnsupportedEncodingException {
        String str = "陈彦杰java";
        //编码
        String encode = URLEncoder.encode(str, UTF8);
        System.out.println("encode:" + encode);//%E9%99%88%E5%BD%A6%E6%9D%B0java
        //解码
        String decode = URLDecoder.decode(encode, UTF8);
        System.out.println("decode:" + decode);

    }

3. Hash加密/散列加密(摘要加密)

引文:

如果开发者需要保存密码(比如网站用户的密码),要考虑如何保护这些密码数据,网站用户密码的泄露是一件非常严重的事情,容易引起用户恐慌,
所以在安全方面是重中之重,直接将密码以明文写入数据库中是极不安全的,因为任何可以打开数据库的人,都将可以直接看到这些密码。
解决的办法是将密码加密后再存储进数据库,比较常用的加密方法是使用哈希函数(Hash Function),也就是摘要加密。
通过哈希函数,我们就可以将密码的哈希值存储进数据库。用户登录网站的时候,我们可以检验用户输入密码的哈希值是否与数据库中的哈希值相同。
由于哈希函数是不可逆的,即使有人打开了数据库,也无法看到用户的密码是多少。(但不意味着存储经过哈希函数加密后的密码就是绝对的安全!)

介绍:摘要加密是一种不需要密钥的加密算法,生成的密文是唯一的、定长的并且无法破解,具有不可逆性、唯一性。常见的算法有MD5、SHA

原理:通过hash算法(单向算法)对目标信息生成一段特定长度的唯一hash值。

应用场景:密码加密,数字签名,文件完整性的校验 ,版权等应用场景。

输出长度安全性计算速度常见应用
MD5128位(16字节)不安全,易受碰撞攻击文件校验、散列密码
SHA-1160位(20字节)不再安全,易受碰撞攻击中等数字签名、SSL证书
SHA-256256位(32字节)相对较安全,较难受碰撞攻击相对较慢安全存储密码、数字签名
SHA-512512位(64字节)高安全性,抗碰撞能力强更慢密码学、数字签名、数据完整性校验

3.1 md5加密

  • MessageDigestUtils
public class MessageDigestUtils {
    private static final String UTF8 = StandardCharsets.UTF_8.name();

    /**
     *
     * @param str
     * @param algorithm
     * @return
     * @throws NoSuchAlgorithmException
     * @throws UnsupportedEncodingException
     */
    public   static String doGetDigest(String str, String algorithm) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        //获取消息摘要算法对象
        MessageDigest md = MessageDigest.getInstance(algorithm);
        //获取原始内容的字节数组
        byte[] originalBytes = str.getBytes(UTF8);
        //获取到摘要结果
        byte[] digest = md.digest(originalBytes);//QX�L�����-d�[�[
        //当originalBytes比较大的时候,循环的进行update()
//        md.update(originalBytes);
//        byte[] digest = md.digest();//QX�L�����-d�[�[
//        System.out.println(new String(digest,UTF8));
//        System.out.println(Arrays.toString(digest));//[81, 88, -6, 76, -107, -111, -115, -24, -73, -64, 45, 100, -84, 91, -7, 91]

        return HexUtils.convertBytes2HexStr( digest);
    }

    /**
     * 获取mac的消息摘要
     * @param str 原始内容
     * @param key mac算法的key
     * @param algorithm 算法名字,如HmacMd5,HmacSha-256
     * @return
     * @throws NoSuchAlgorithmException
     * @throws UnsupportedEncodingException
     */
    public   static String doGetDigestMac(String str,String key, String algorithm) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
        //获取消息摘要算法对象
        Mac mac = Mac.getInstance(algorithm);
        //获取key对象并初始化mac
        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(UTF8), algorithm);
        mac.init(secretKeySpec);



        //获取原始内容的字节数组
        byte[] originalBytes = str.getBytes(UTF8);
        //获取到摘要结果
        byte[] digest = mac.doFinal(originalBytes);//QX�L�����-d�[�[
        //当originalBytes比较大的时候,循环的进行update()
//        md.update(originalBytes);
//        byte[] digest = md.digest();//QX�L�����-d�[�[
//        System.out.println(new String(digest,UTF8));
//        System.out.println(Arrays.toString(digest));//[81, 88, -6, 76, -107, -111, -115, -24, -73, -64, 45, 100, -84, 91, -7, 91]

        return HexUtils.convertBytes2HexStr( digest);
    }
}
  • HexUtils
public class HexUtils {
    /**
     * 把字节数组转为16进制字符串,如果一个字节转为16进制字符后不足两位,则前面补0
     *
     * @param digest
     * @return
     */

    public static String convertBytes2HexStr(byte[] digest) {
        StringBuilder sb = new StringBuilder();
        for (byte b : digest) {
//            System.out.println(b);
            //获取b的补码的后8位
//            System.out.print((int) b+" ");
//            String hexString = Integer.toHexString(((int) b) );
            //15-->15&0xff=f
            //16-->16&0xff=10
            String hexString = Integer.toHexString(((int) b) & 0xff);
//            System.out.print(hexString);
//            System.out.println();
            if (hexString.length() == 1) {
                hexString = "0" + hexString;
            }
            sb.append(hexString);

        }
        return sb.toString();
    }

    /**
     * 把16进制字符串(一定是偶数位的,因为convertBytes2HexStr已经处理过)转为字节数组
     *
     * @param hexStr
     * @return
     */
    public static byte[] convertHex2Bytes(String hexStr) {
        //一个字节可以转化为2个16进制字符
        int length = hexStr.length() / 2;
        byte[] result = new byte[length];
        for (int i = 0; i < length; i++) {
            //hexStr:abcd
            //Integer.parseInt:把s转为10进制数,radix指定s是什么进制的数
            //获取每个字节的高4位,hexStr.substring(2,3)->c
            int high4 = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
            //获取每个字节的低4位,hexStr,substring(3,4)=>d
            int low4 = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
            result[i] = (byte) (high4 * 16 + low4);

        }
        return result;
    }
}

3.1.1 jdk原生实现

/**
     * 使用jdk原生实现Md5
     */
    @Test
    public void test3() throws UnsupportedEncodingException, NoSuchAlgorithmException {
        String str = "陈彦杰";
        String algorithm = "MD5";
        //结果32位
        String hexStr = MessageDigestUtils.doGetDigest(str, algorithm);//5158fa4c95918de8b7c02d64ac5bf95b
        System.out.println(hexStr);
    }

3.1.2 commons-codec实现

/**
     * 使用codec来实现md5
     */
    @Test
    public void test4() throws UnsupportedEncodingException, NoSuchAlgorithmException {
        String str = "陈彦杰";
        //结果32位
        String hexStr= DigestUtils.md5Hex(str.getBytes("utf-8"));//5158fa4c95918de8b7c02d64ac5bf95b
        System.out.println(hexStr);
    }

3.2 SHA-1/SHA-256/SHA-512加密

3.2.1 jdk原生实现

 /**
     * 使用jdk原生实现Sha256
     */
    @Test
    public void test3() throws UnsupportedEncodingException, NoSuchAlgorithmException {
        String str = "陈彦杰";
        String algorithm = "SHA-1";
        //结果64位
        String hexStr = MessageDigestUtils.doGetDigest(str, algorithm);//38f9d59c4d89375e5c557616a1ea29a8db09776a44cfe703344a12f762aa3236
        System.out.println(hexStr);
    }

3.2.2 commons-codec实现

/**
     * 使用codec来实现Sha256
     */
    @Test
    public void test4() throws UnsupportedEncodingException, NoSuchAlgorithmException {
        String str = "陈彦杰";
        //结果64位
        String hexStr= DigestUtils.sha1Hex(str.getBytes("utf-8"));//38f9d59c4d89375e5c557616a1ea29a8db09776a44cfe703344a12f762aa3236
        System.out.println(hexStr);
    }

3.3 mac加密

mac摘要和digest算法(md5,sha)不同的地方就是加盐

3.3.1 jdk原生实现

/**
     * 使用jdk原生实现Mac
     */
    @Test
    public void test3() throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
        String str = "陈彦杰";
        String algorithm = "HmacMd5";
        //指定密钥,mac摘要和digest算法那(md5,sha)不同的地方就是加盐
        String key = "123";
        String hexStr = MessageDigestUtils.doGetDigestMac(str, key, algorithm);//71302a2865ad442bd45d3f1bebf76de3
        System.out.println(hexStr);

        algorithm = "HmacSHA256";
        //指定密钥,mac摘要和digest算法那(md5,sha)不同的地方就是加盐
        hexStr = MessageDigestUtils.doGetDigestMac(str, key, algorithm);//9b2d5ac948bf14a61f758c181cf4360987ae603654d9308c5a8a3b5746be287c
        System.out.println(hexStr);

        algorithm = "HmacSHA512";
        //指定密钥,mac摘要和digest算法那(md5,sha)不同的地方就是加盐
        hexStr = MessageDigestUtils.doGetDigestMac(str, key, algorithm);//e34c61875231f13aa7bf5ef74d6d1dd87c8d105395c0ceb32ca58a7141701ea0ddb2c1d0ccf64bdcf1fddfacf508225dd3463ed341e09c3b0ae47285890e8f84
        System.out.println(hexStr);
    }

3.3.2 commons-codec实现

/**
     * 使用codec来实现Mac
     */
    @Test
    public void test4() throws UnsupportedEncodingException, NoSuchAlgorithmException {
        String str = "陈彦杰";
        //指定密钥,mac摘要和digest算法那(md5,sha)不同的地方就是加盐
        String key = "123";

        String hmacMd5Hex = new HmacUtils(HmacAlgorithms.HMAC_MD5, key.getBytes("utf-8")).hmacHex(str.getBytes("utf-8"));
        System.out.println(hmacMd5Hex);//71302a2865ad442bd45d3f1bebf76de3

        String hmacSHA256Hex = new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key.getBytes("utf-8")).hmacHex(str.getBytes("utf-8"));
        System.out.println(hmacSHA256Hex);//9b2d5ac948bf14a61f758c181cf4360987ae603654d9308c5a8a3b5746be287c

        String hmacSHA512Hex = new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key.getBytes("utf-8")).hmacHex(str.getBytes("utf-8"));
        System.out.println(hmacSHA512Hex);//e34c61875231f13aa7bf5ef74d6d1dd87c8d105395c0ceb32ca58a7141701ea0ddb2c1d0ccf64bdcf1fddfacf508225dd3463ed341e09c3b0ae47285890e8f84

    }

4. 对称加密

采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密。

4.1 AES加密

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值