【JAVA基础】Java中常用加密算法的使用方法

加密算法小科普

常见加密算法分类

  • 对称加密 指加密和解密使用相同密钥的加密算法
    • DES、3DES、DESX、Blowfish、IDEA、RC4、RC5、RC6和AES
  • 非对称加密 指加密和解密使用不同密钥的加密算法,也称为公私钥加密
    • RSA、ECC(移动设备用)、Diffie-Hellman、El Gamal、DSA(数字签名用)
  • Hash算法 一种单向算法,通过Hash算法对目标信息生成一段特定长度的唯一的Hash值,但不能通过这个Hash值重新获得目标信息
    • MD2、MD4、MD5、HAVAL、SHA、SHA-1、HMAC、HMAC-MD5、HMAC-SHA1

简单的 Java 加密算法有

  • BASE64 严格地说,属于编码格式,而非加密算法
  • MD5(Message Digest algorithm 5,信息摘要算法)
  • SHA(Secure Hash Algorithm,安全散列算法)
  • HMAC(Hash Message Authentication Code,散列消息鉴别码)

talk is cheap, show me the code.

BASE64Encoder / BASE64Decoder

import lombok.extern.slf4j.Slf4j;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/**
 * @description:
 * @author: tanpeng
 * @date: 2020-03-24 14:34
 * @version: v1.0.0
 */
@Slf4j
public class TestBASE64 {

    private static String CHARSET_UTF8 = "UTF-8";

    public static void main(String[] args) throws Exception {
        String plaintext = "123456";
        byte[] plaintextByteArray = plaintext.getBytes(CHARSET_UTF8);

        System.out.println("=================================== BASE64Encoder / BASE64Decoder ===================================");

        String encode1 = new BASE64Encoder().encode(plaintextByteArray);
        byte[] decode1 = new BASE64Decoder().decodeBuffer(encode1);
        log.info("Base64 encode1 {}", encode1);
        log.info("Base64 decode1 {}", new String(decode1, CHARSET_UTF8));

        System.out.println("=================================== Base64.getEncoder() / Base64.getDecoder() ===================================");

        byte[] encode2 = Base64.getEncoder().encode(plaintextByteArray);
        byte[] decode2 = Base64.getDecoder().decode(encode2);
        log.info("Base64 encode2 {}", new String(encode2, CHARSET_UTF8));
        log.info("Base64 decode2 {}", new String(decode2, CHARSET_UTF8));
    }
}

输出

=================================== BASE64 ===================================
14:43:27.621 [main] INFO com.itplh.encrypt.TestBASE64 - Base64 encode MTIzNDU2
14:43:27.639 [main] INFO com.itplh.encrypt.TestBASE64 - Base64 decode 123456

MessageDigest

import lombok.extern.slf4j.Slf4j;

import java.math.BigInteger;
import java.security.MessageDigest;

/**
 * @description:
 * @author: tanpeng
 * @date: 2020-03-24 14:36
 * @version: v1.0.0
 */
@Slf4j
public class TestMessageDigest {
    private static String CHARSET_UTF8 = "UTF-8";
    private static int RADIX_16 = 1<<4;
    private static int RADIX_32 = 1<<5;

    public static void main(String[] args) throws Exception {
        String plaintext = "123456";
        byte[] plaintextByteArray = plaintext.getBytes(CHARSET_UTF8);
        byte[] slatByteArray = "slat".getBytes(CHARSET_UTF8);

        System.out.println("=================================== MD5 ===================================");

        MessageDigest md5 = MessageDigest.getInstance("MD5");
        md5.update(plaintextByteArray);
        byte[] md5Encode = md5.digest(); // 调用digest方法后会重置状态为 INITIAL
        String md5MessageDigest = new BigInteger(md5Encode).toString(RADIX_16);
        log.info("MD5 encode {}", md5MessageDigest);

        md5.update(plaintextByteArray);
        md5.update(slatByteArray);
        log.info("MD5 slat encode {}", new BigInteger(md5.digest()).toString(RADIX_16));

        md5.update(plaintextByteArray);
        md5.update(slatByteArray);
        log.info("MD5 slat encode {}", new BigInteger(md5.digest()).toString(RADIX_16));

        System.out.println("=================================== SHA-1 ===================================");

        MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
        sha1.update(plaintextByteArray);
        log.info("SHA-1 encode {}", new BigInteger(sha1.digest()).toString(RADIX_32));

        sha1.update(plaintextByteArray);
        sha1.update(slatByteArray);
        log.info("SHA-1 slat encode {}", new BigInteger(sha1.digest()).toString(RADIX_32));

        sha1.update(plaintextByteArray);
        sha1.update(slatByteArray);
        log.info("SHA-1 slat encode {}", new BigInteger(sha1.digest()).toString(RADIX_32));

        System.out.println("=================================== SHA-256 ===================================");

        MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
        sha256.update(plaintextByteArray);
        log.info("SHA-256 encode {}", new BigInteger(sha256.digest()).toString(RADIX_32));

        sha256.update(plaintextByteArray);
        sha256.update(slatByteArray);
        log.info("SHA-256 slat encode {}", new BigInteger(sha256.digest()).toString(RADIX_32));

        sha256.update(plaintextByteArray);
        sha256.update(slatByteArray);
        log.info("SHA-256 slat encode {}", new BigInteger(sha256.digest()).toString(RADIX_32));
        
    }
}

输出

=================================== MD5 ===================================
14:44:38.581 [main] INFO com.itplh.encrypt.TestMessageDigest - MD5 encode -1ef523c6b645a65441a91fa80df077c2
14:44:38.597 [main] INFO com.itplh.encrypt.TestMessageDigest - MD5 slat encode 7d991ee60623856907a6baffc15164da
14:44:38.597 [main] INFO com.itplh.encrypt.TestMessageDigest - MD5 slat encode 7d991ee60623856907a6baffc15164da
=================================== SHA-1 ===================================
14:44:38.598 [main] INFO com.itplh.encrypt.TestMessageDigest - SHA-1 encode fh58q2ea6thauof5ikg98fe2ciafh50r
14:44:38.598 [main] INFO com.itplh.encrypt.TestMessageDigest - SHA-1 slat encode bvs54f4a210bmpm9ecb6dg9s508lgl7q
14:44:38.598 [main] INFO com.itplh.encrypt.TestMessageDigest - SHA-1 slat encode bvs54f4a210bmpm9ecb6dg9s508lgl7q
=================================== SHA-256 ===================================
14:44:38.599 [main] INFO com.itplh.encrypt.TestMessageDigest - SHA-256 encode -sj9c4892d9c7lisb7bdfscnic7jo2haauag1gqurvfjdn2i74re
14:44:38.599 [main] INFO com.itplh.encrypt.TestMessageDigest - SHA-256 slat encode r498dqrlfo7649m7ausnpnvsf7ueb9kp89oq2301ne6lkeashg8
14:44:38.600 [main] INFO com.itplh.encrypt.TestMessageDigest - SHA-256 slat encode r498dqrlfo7649m7ausnpnvsf7ueb9kp89oq2301ne6lkeashg8

KeyGenerator

支持的算法有

  • AES
  • ARCFOUR
  • Blowfish
  • DES
  • DESede
  • HmacMD5
  • HmacSHA1 HmacSHA256 HmacSHA384 HmacSHA512
  • RC2
import lombok.extern.slf4j.Slf4j;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.annotation.adapters.HexBinaryAdapter;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;

/**
 * @description:
 * @author: tanpeng
 * @date: 2020-03-24 14:51
 * @version: v1.0.0
 */
@Slf4j
public class TestKeyGenerator {

    private static String CHARSET_UTF8 = "UTF-8";

    public static void main(String[] args) throws Exception {

        String plaintext = "1234.56.78";

        System.out.println("=================================== HmacMD5 ===================================");
        encodeMac("HmacMD5", plaintext);

        System.out.println("=================================== HmacSHA1 ===================================");
        encodeMac("HmacSHA1", plaintext);

        System.out.println("=================================== HmacSHA256 ===================================");
        encodeMac("HmacSHA256", plaintext);

        System.out.println("=================================== HmacSHA384 ===================================");
        encodeMac("HmacSHA384", plaintext);

        System.out.println("=================================== HmacSHA512 ===================================");
        encodeMac("HmacSHA512", plaintext);

        System.out.println("=================================== AES ===================================");
        decodeAES("12345678ABCDEFGH", encodeAES("12345678ABCDEFGH", plaintext));

    }

    private static String encodeMac(String algorithm, String plaintext) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
        // 产生摘要算法的密钥key
        byte[] key = KeyGenerator.getInstance(algorithm)
                .generateKey()
                .getEncoded();
        key = Base64.getEncoder().encode(key); // 使用base64对秘钥进行编码
        log.info("{} key {}", algorithm, new String(key, CHARSET_UTF8));
        // 摘要算法
        key = Base64.getDecoder().decode(key);// 使用base64对秘钥进行解码
        SecretKey key2 = new SecretKeySpec(key, algorithm); // 还原密钥
        Mac mac = Mac.getInstance(key2.getAlgorithm()); // 实例化Mac
        mac.init(key2); // 初始化mac
        mac.update(plaintext.getBytes(CHARSET_UTF8)); // 计算消息摘要
        byte[] digest = mac.doFinal(); // 获取消息摘要
        String result = new HexBinaryAdapter().marshal(digest); // //转为十六进制的字符串
        log.info("{} encode {}", algorithm, result);
        return result;
    }

    private static String encodeAES(String encodeRules, String plaintext) throws Exception {
        String AES = "AES";
        // 产生摘要算法的密钥key
        byte[] raw = generateAESKey(encodeRules);
        // AES摘要算法
        //5.根据字节数组生成AES密钥
        SecretKey key = new SecretKeySpec(raw, AES);
        //6.根据指定算法AES自成密码器
        Cipher cipher = Cipher.getInstance(AES);
        //7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密解密(Decrypt_mode)操作,第二个参数为使用的KEY
        cipher.init(Cipher.ENCRYPT_MODE, key);
        //8.获取加密内容的字节数组(这里要设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码
        byte[] byte_encode = plaintext.getBytes(CHARSET_UTF8);
        //9.根据密码器的初始化方式--加密:将数据加密
        byte[] byte_AES = cipher.doFinal(byte_encode);
        //10.将加密后的数据转换为字符串
        String ciphertext = new BASE64Encoder().encode(byte_AES);
        //11.将字符串返回
        log.info("AES encode {}", ciphertext);
        return ciphertext;
    }

    private static String decodeAES(String encodeRules, String ciphertext) throws Exception {
        String AES = "AES";
        // 产生摘要算法的密钥key
        byte[] raw = generateAESKey(encodeRules);
        // 解密AES摘要
        //5.根据字节数组生成AES密钥
        SecretKey key = new SecretKeySpec(raw, AES);
        //6.根据指定算法AES自成密码器
        Cipher cipher = Cipher.getInstance(AES);
        //7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密解密(Decrypt_mode)操作,第二个参数为使用的KEY
        cipher.init(Cipher.DECRYPT_MODE, key);
        //8.BASE64解码密文
        byte[] byteCiphertext = new BASE64Decoder().decodeBuffer(ciphertext);
        //9.解密
        byte[] byteDecode = cipher.doFinal(byteCiphertext);
        //10.将字节数组转为明文字符串
        String plaintext = new String(byteDecode, CHARSET_UTF8);
        log.info("AES decode {}", plaintext);
        return plaintext;
    }

    // javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
    // 实现generateAESKey方法时不使用SecureRandom生成SecretKey
    //
    // java.security.NoSuchAlgorithmException: AES SecretKeyFactory not available
    // 使用 SecretKeySpec 直接生成一个密钥
    //
    // Exception java.security.InvalidKeyException: Invalid AES key length: 3 bytes?
    // AES allows 128, 192 or 256 bit key length. That is 16, 24 or 32 byte. Try taking just the first 16 bytes of your encodeRules as the keyAsBytes.
    private static byte[] generateAESKey(String encodeRules) throws Exception {
        String AES = "AES";

//        //1.构造密钥生成器,指定为AES算法,不区分大小写
//        KeyGenerator keygen = KeyGenerator.getInstance(AES);
//        //2.根据ecnodeRules规则初始化密钥生成器
//        //生成一个128位的随机源,根据传入的字节数组
//        keygen.init(128, new SecureRandom(encodeRules.getBytes()));
//        //3.产生原始对称密钥
//        SecretKey originalKey = keygen.generateKey();
//        //4.获得原始对称密钥的字节数组
//        byte[] keyEncoded = originalKey.getEncoded();
//        return keyEncoded;

//        SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(AES);
//        SecretKey originalKey = secretKeyFactory.generateSecret(new SecretKeySpec(encodeRules.getBytes(CHARSET_UTF8), AES));
//        return originalKey.getEncoded();

        SecretKey originalKey = new SecretKeySpec(encodeRules.getBytes(CHARSET_UTF8), AES);
        return originalKey.getEncoded();
    }
}

输出

=================================== HmacMD5 ===================================
17:37:51.467 [main] INFO com.itplh.encrypt.TestKeyGenerator - HmacMD5 key 5Q+yQ+icsqC2qS5CR3TULslTE4b3bsMS2q/xpjnbx4DAz76OQ/4IgpjPP2w2UNxCDx46uWMy+wbJXGFmYzar+w==
17:37:51.484 [main] INFO com.itplh.encrypt.TestKeyGenerator - HmacMD5 encode 3EC9DD765FDE7CCDF51F33512EBEC06B
=================================== HmacSHA1 ===================================
17:37:51.484 [main] INFO com.itplh.encrypt.TestKeyGenerator - HmacSHA1 key XfSINYU99W3E7dLZbvycTPA5A8TAlgFMSsI3AV/pMC7QPq8M51mThv1Yp9cxPv/Uxlq2j9ViW8h1bWBjPQcbWg==
17:37:51.485 [main] INFO com.itplh.encrypt.TestKeyGenerator - HmacSHA1 encode 323E5241DAE5484FE25FFA4BCF27C4E2B4FB6EBD
=================================== HmacSHA256 ===================================
17:37:51.486 [main] INFO com.itplh.encrypt.TestKeyGenerator - HmacSHA256 key 7/ctQyvQ8ddwmHe+v7DyQSU+lejGmWXlwCx01kFOeWI=
17:37:51.487 [main] INFO com.itplh.encrypt.TestKeyGenerator - HmacSHA256 encode FAA343D654681A07E2F4828AF263BC4C33444581968589C26803C91066C8F15A
=================================== HmacSHA384 ===================================
17:37:51.487 [main] INFO com.itplh.encrypt.TestKeyGenerator - HmacSHA384 key 11SpITSJisQQqV4IVUnfUhKzWu4ge2S1XDtL+remqexnxOmXE0ImD75pYINIzImy
17:37:51.488 [main] INFO com.itplh.encrypt.TestKeyGenerator - HmacSHA384 encode 143EB582223E887BE0A7F11C0B71846DC5A17FD2B9B216D24138C30E6C85F4B5D510BB15E4A36D1BC37F73659844A47E
=================================== HmacSHA512 ===================================
17:37:51.489 [main] INFO com.itplh.encrypt.TestKeyGenerator - HmacSHA512 key PfMIrHMdrjJ7Laxytp6LZXVWA7bHaij7Jb1dBpm3bCAWTT1neS76YgHMug536cf1bytqSz75Go4FsdpHTEYtJA==
17:37:51.490 [main] INFO com.itplh.encrypt.TestKeyGenerator - HmacSHA512 encode DE1D7C852C5A96958DF2C420E9CE9623B1759EDDE3CDE6190FA111D9CC1891141E2AA6BC225D4C82B5DA333AF65E6CD21A4C6134AF83513261ACF96CB153A3AE
=================================== AES ===================================
17:37:51.521 [main] INFO com.itplh.encrypt.TestKeyGenerator - AES encode IUEleZreAU0tk6ewY9aGUA==
17:37:51.522 [main] INFO com.itplh.encrypt.TestKeyGenerator - AES decode 1234.56.78

参考

Java中4大基本加密算法解析

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值