专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

java常用加密算法笔记

1、 BASE64
Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,可以查看RFC2045~RFC2049,上面有MIME的详细规范。Base64编码可用于在HTTP环境下传递较长的标识信息。
例如,在Java Persistence系统Hibernate中,就采用了Base64来将一个较长的唯一标识符(一般为128-bit的UUID)编码为一个字符串,用作HTTP表单和HTTP GET URL中的参数。
在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base64编码具有不可读性,即所编码的数据不会被人用肉眼所直接看到。
Java中是用”8个二进制数字”表示一个实际的字节。比如:我要用Base64编码一个字符串“abc”,实际算法如下:
‘a’,’b’,’c’的ASCII标准编码分别为(十进制)97,98,99,因此用二进制表示“abc”字符串就是:
01100001,01100010,01100011 —3组,每组8字节
Base64的原理:将这三组8字节,分成4组6字节
011000,010110, 001001,100011 —4组,每组6字节
高位补0
00011000,00010110, 00001001,00100011
这四个二进制数组对应十进制的数值分别是:24,22,9,35,RFC2045(Base64解码表)分别为:Y,W,J,j
即:”abc”经过Base64编码后,为”YWJj”。这个过程是可逆的。
-–每次Base64编码都会扩容33%
示例:

/**
 * Base64编码
 * @param message 待Base64编码的字符串
 * @return 编码后的字符串
 */
public static String encode(String message){
    if (message == null){
        return null;
    }
    byte[] bytes = message.getBytes();
    byte[] result = Base64.encodeBase64(bytes);
    return new String(result);
}

/**
 * Base64解码
 * @param message 待Base64解码的字符串
 * @return 解码后的字符串
 */
public static String decode(String message){
    if (message == null){
        return null;
    }
    byte[] bytes = message.getBytes();
    byte[] result = Base64.decodeBase64(bytes);
    return new String(result);
}

2、 MD5
MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。
将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2、MD3和MD4。广泛用于加密和解密技术,常用于文件校验。
MD5算法简单来说,就是把一段信息(明文),通过一种有损的方式压缩成定长的字符(32位密文)。因为这种压缩方式是会损失信息的,所以是无法还原出“明文”的。
虽然无法从数学上破解MD5算法,但由于现在计算机具备强大的计算能力,还是可以通过“穷举法”破解该算法。
如果想用该算法加密,还可以通过“加盐”的方式提高解密难度。该算法允许多传一个参数”salt”,指定通过MD5加密的次数,这样是能够提高解密难度的。
校验?不管文件多大,经过MD5后都能生成唯一的MD5值。好比现在的ISO校验,都是MD5校验。
怎么用?当然是把ISO经过MD5后产生MD5的值。一般下载linux-ISO的朋友都见过下载链接旁边放着MD5的串。就是用来验证文件是否一致的。
示例:

/**
 * M5加密
 * @param bytes 要加密的信息
 * @return 32位字符串
 */
public static String encrypt(byte[] bytes){
    try {
        MessageDigest messageDigest = MessageDigest.getInstance("MD5");
        byte[] resultBytes = messageDigest.digest(bytes);
        return Hex.encodeHexString(resultBytes);
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    return null;
}

3、SHA
安全哈希算法(Secure Hash Algorithm)主要适用于数字签名标准(Digital Signature Standard DSS)里面定义的数字签名算法(Digital Signature Algorithm DSA)。
对于长度小于2^64位的消息,SHA1会产生一个160位的消息摘要。
该算法经过加密专家多年来的发展和改进已日益完善,并被广泛使用。思想是接收一段明文,然后以一种不可逆的方式将它转换成一段(通常更小)密文,也可以简单的理解为取一串输入码(称为预映射或信息),并把它们转化为长度较短、位数固定的输出序列即散列值(也称为信息摘要或信息认证代码)的过程。
散列函数值可以说是对明文的一种”指纹”或是”摘要”所以对散列值的数字签名就可以视为对此明文的数字签名。
SHA与MD5均有MD4导出,因此强度和特性比较相似的,都是不可逆的算法。
SHA与MD5的不同:
1、对强行攻击的安全性,SHA-1摘要比MD5摘长,对强行攻击有更大的强度。
2、对密码分析的安全性,由于MD5的设计,易受密码分析的攻击,SHA-1显得不易受这样的攻击。
3、在相同的硬件上,SHA-1的运行速度比MD5慢。
示例:

/**
 * SHA加密,即安全散列算法加密
 * @param bytes 要加密的信息
 * @return 40位字符串
 */
public static String encrypt(byte[] bytes){
    try {
        MessageDigest messageDigest = MessageDigest.getInstance("SHA");
        byte[] resultBytes = messageDigest.digest(bytes);
        return Hex.encodeHexString(resultBytes);
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    return null;
}

4、HMAC
HMAC(Hash Message Authentication Code,散列消息鉴别码,基于密钥的Hash算法的认证协议。
消息鉴别码实现鉴别的原理是,用公开函数和密钥产生一个固定长度的值作为认证标识,用这个标识鉴别消息的完整性。
使用一个密钥生成一个固定大小的小数据块,即MAC,并将其加入到消息中,然后传输。接收方利用与发送方共享的密钥进行鉴别认证等。
示例:

import java.security.MessageDigest;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class HMACUtil {

    public static final String KEY_SHA = "SHA";
    public static final String KEY_MD5 = "MD5";

    /**
     * MAC算法可选以下多种算法
     *
     * <pre>
     * HmacMD5
     * HmacSHA1
     * HmacSHA256
     * HmacSHA384
     * HmacSHA512
     * </pre>
     */
    public static final String KEY_MAC = "HmacMD5";

    /**
     * BASE64解密
     *
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decryptBASE64(String key) throws Exception {
        return (new BASE64Decoder()).decodeBuffer(key);
    }

    /**
     * BASE64加密
     *
     * @param key
     * @return
     * @throws Exception
     */
    public static String encryptBASE64(byte[] key) throws Exception {
        return (new BASE64Encoder()).encodeBuffer(key);
    }

    /**
     * MD5加密
     *
     * @param data
     * @return
     * @throws Exception
     */
    public static byte[] encryptMD5(byte[] data) throws Exception {
        MessageDigest md5 = MessageDigest.getInstance(KEY_MD5);
        md5.update(data);
        return md5.digest();
    }

    /**
     * SHA加密
     *
     * @param data
     * @return
     * @throws Exception
     */
    public static byte[] encryptSHA(byte[] data) throws Exception {
        MessageDigest sha = MessageDigest.getInstance(KEY_SHA);
        sha.update(data);
        return sha.digest();
    }

    /**
     * 初始化HMAC密钥
     *
     * @return
     * @throws Exception
     */
    public static String initMacKey() throws Exception {
        KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_MAC);
        SecretKey secretKey = keyGenerator.generateKey();
        return encryptBASE64(secretKey.getEncoded());
    }

    /**
     * HMAC加密
     *
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] encryptHMAC(byte[] data, String key) throws Exception {
        SecretKey secretKey = new SecretKeySpec(decryptBASE64(key), KEY_MAC);
        Mac mac = Mac.getInstance(secretKey.getAlgorithm());
        mac.init(secretKey);
        return mac.doFinal(data);
    }
}

5、AES算法
AES是高级加密标准,采用对称算法。
它的原理是:加密方和解密方保有同一个16位长的密钥,使用AES算法加解密时需要传入该密钥参数,通过Java实现AES算法提供的工具包加密后返回的是一个Base64格式的字节数组。
因此为保证密文“可读性”,需要在加密后对密文进行Base64编码,解密前进行Base64解码成密文。
AES算法的安全性,取决于密钥的安全性。因此一定不要在加解密的URL中传入该密钥参数,不然没有意义。一般的做法是:前后端协商好密钥,或者通过不对称加密的方式传递密钥。
AES加密算法作为新一代的数据加密标准汇聚了强安全性、高性能、高效率、易用和灵活等优点。
AES设计有三个密钥长度:128,192,256 位。
相对而言,AES的128密钥比DES的56密钥强了1021倍
示例:

public class AESUtil {
    /**
     * 用户自定义的密钥,由前后端协商确定
     * (不要在加解密方法的参数中暴露),AES的安全性,取决于密钥的安全性。
     */
    private static final String AES_KEY = "asdfghjkl";
    /**
     * AES:算法,ECB:模式,PKCS5Padding:补码方式
     */
    private static final String ALGORITHM = "AES/ECB/PKCS5Padding";

    /**
     * AES加密
     * @param message 要加密的信息
     * @return 加密后的字符串
     */
    public static String encrypt(String message){
        return doAES(message,AES_KEY,Cipher.ENCRYPT_MODE);
    }

    /**
     * AES解密
     * @param message 要解密的信息
     * @return 解密后的字符串
     */
    public static String decrypt(String message){
        return doAES(message,AES_KEY,Cipher.DECRYPT_MODE);
    }

    /**
     * 加密或解密的实际操作过程
     * @param message 待处理的信息
     * @param key AES加解密过程需要的密钥
     * @param mode 加解密mode
     * @return 加密或解密后的信息
     */
    private static String doAES(String message,String key, int mode){
        try {
            if (StringUtils.isBlank(message) || StringUtils.isBlank(key)){
                return null;
            }
            // 由于AES算法要求密钥的长度为16的倍数,(1,2,3,4)步的目的: 把用户自定义的密钥替换成16位的密钥

            // 1. 构造密钥生成器,指定为AES算法
            KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
            // 2. 根据用户自定义密钥对应的字节数组,生成一个128位的随机源(只能是128 or 192 or 256中的一个)
            keyGenerator.init(128, new SecureRandom(key.getBytes()));
            // 3. 生成AES算法的原始对称密钥
            SecretKey secretKey = keyGenerator.generateKey();
            // 4. 获取原始对称密钥的字节数组
            byte[] enCodeFormat = secretKey.getEncoded();

            // 5. 根据字节数组生成AES密钥
            SecretKeySpec secretKeySpec = new SecretKeySpec(enCodeFormat,"AES");
            // 6.根据指定算法AES自成密码器
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            // 7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密(Decrypt_mode)操作,第二个参数为使用的KEY
            cipher.init(mode, secretKeySpec);

            if (mode == Cipher.ENCRYPT_MODE) {
                byte[] content = message.getBytes();
                byte[] result = cipher.doFinal(content);
                // 加密,AES加密后的结果默认是Base64格式的字节数组
                return Base64.encodeBase64String(result);
            } else {
                byte[] content = Base64.decodeBase64(message);
                byte[] result = cipher.doFinal(content);
                return new String(result);
            }
        } catch (NoSuchAlgorithmException | BadPaddingException | IllegalBlockSizeException | NoSuchPaddingException | InvalidKeyException e) {
            e.printStackTrace();
        }
        return null;
    }
}

6、RSA算法
RSA算法,是一种非常常用的不对称加密算法。不对称加密算法指的是:需要两个密钥来进行加密和解密,分别是公钥和私钥(公钥和私钥必须是一对)。
如果用公钥对数据进行加密,那么只有使用对应的私钥才能解密,反之亦然。由于加密和解密使用的是两个不同的密钥,因此,这种算法叫做非对称加密算法。
其算法具体实现基于一个十分简单的数论事实:将两个大素数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。
示例:

import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import org.apache.commons.codec.binary.Hex;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class RSAUtil {

    /**
     * 生成公钥和私钥
     *
     * @return
     */
    public static Map<String, Object> generateKey() {
        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            // initialize(512)表示生成的是128位字符
            keyPairGenerator.initialize(512);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
            RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
            Map<String, Object> keyPairs = new HashMap<>();
            keyPairs.put("publicKey", rsaPublicKey);
            keyPairs.put("privateKey", rsaPrivateKey);
            return keyPairs;
        } catch (NoSuchAlgorithmException e) {
            log.error("", e);
        }
        return null;
    }

    /**
     * RSA私钥加密
     *
     * @param message 要加密的信息
     * @return 加密后的字符串
     */
    public static String encrypt(String message, RSAPrivateKey rsaPrivateKey) {
        try {
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            byte[] resultBytes = cipher.doFinal(message.getBytes());
            return Hex.encodeHexString(resultBytes);
        } catch (NoSuchAlgorithmException | InvalidKeySpecException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
            log.error("", e);
        }
        return null;
    }

    /**
     * RSA公钥解密
     *
     * @param message 要解密的信息
     * @return 解密后的字符串
     */
    public static String decrypt(String message, RSAPublicKey rsaPublicKey) {
        try {
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            byte[] resultBytes = cipher.doFinal(Hex.decodeHex(message.toCharArray()));
            return new String(resultBytes);
        } catch (Exception e) {
            log.error("", e);
        }
        return null;
    }
}

文章永久链接:https://tech.souyunku.com/24919

未经允许不得转载:搜云库技术团队 » java常用加密算法笔记

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们