常用加密算法及Java实现

1 篇文章 0 订阅

欢迎光临我的博客查看最新文章: https://river106.cn

1、概述

加密在平时开发中也会经常用到,涉及登录、支付、接口设计等方面,可能都需要考虑到加密算法,加密算法分对称加密和非对称加密,对称加密使用的密钥只有一个,发送和接收双方都使用这个密钥对数据进行加密和解密,非对称加密算法,需要两个密钥,一个是公钥 (public key),另一个是私钥 (private key),如果使用公钥对数据 进行加密,只有用对应的私钥才能进行解密。如果使用私钥对数据 进行加密,只有用对应的公钥才能进行解密。
 

2、MD5

MD5一般用于对一段信息产生信息摘要即生成数字签名,以 防止被篡改。无论是多长的输入,MD5 都会输出长度为 128bits 的一个串 (通常用 16 进制 表示为 32 个字符)。

java代码如下:

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class Md5Utils {

    private static final String UTF8 = "utf-8";

    /**
     * 加密
     *
     * @param plainText 待加密字符串
     * @return
     */
    public final static String encoder(String plainText)
            throws NoSuchAlgorithmException, UnsupportedEncodingException {
        byte[] bytes = plainText.getBytes(UTF8);
        MessageDigest mdInst = MessageDigest.getInstance("MD5");
        mdInst.update(bytes);
        byte[] md = mdInst.digest();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < md.length; i++) {
            int val = ((int) md[i]) & 0xff;
            if (val < 16) {
                sb.append("0");
            }
            sb.append(Integer.toHexString(val));
        }
        return sb.toString();
    }

}

3、SHA1

SHA1 是和 MD5 一样流行的 消息摘要算法,然而 SHA1 比 MD5 的 安全性更强。对于长度小于 2 ^ 64 位的消息,SHA1 会产生一个 160 位的 消息摘要。基于 MD5、SHA1 的信息摘要一般而言不可逆 ,可以被应用在检查 文件完整性 以及 数字签名 等场景。

java代码如下:

import java.security.MessageDigest;

public final class Sha1Utils {
    private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

    /**
     * Takes the raw bytes from the digest and formats them correct.
     * @param bytes the raw bytes from the digest.
     * @return the formatted bytes.
     */
    private static String getFormattedText(byte[] bytes) {
        int len = bytes.length;
        StringBuilder buf = new StringBuilder(len * 2);
        // 把密文转换成十六进制的字符串形式
        for (int j = 0; j < len; j++) {
            buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
            buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
        }
        return buf.toString();
    }

    public static String encode(String str) {
        if (str == null) {
            return null;
        }
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
            messageDigest.update(str.getBytes());
            return getFormattedText(messageDigest.digest());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}

4、RSA

RSA 加密算法是目前比较优秀的公钥方案。RSA是第一个能同时用于加密和数字签名的算法,它能够抵抗到目前为止已知的 所有密码攻击,已被 ISO推荐为公钥数据加密标准。RSA 加密算法 基于一个十分简单的数论事实:将两个大 素数 相乘十分容易,但想要对其乘积进行 因式分解 却极其困难,因此可以将 乘积 公开作为 加密密钥。

java代码如下:

import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class RsaUtils {

    private static final String UTF8 = "UTF-8";

    /**
     * 随机生成密钥对
     *
     * @throws NoSuchAlgorithmException
     */
    public static RsaKeyPair generateKeyPair() throws NoSuchAlgorithmException {
        // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
        // 初始化密钥对生成器,密钥大小为96-1024位
        keyPairGen.initialize(1024, new SecureRandom());
        // 生成一个密钥对,保存在keyPair中
        KeyPair keyPair = keyPairGen.generateKeyPair();
        // 得到私钥
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        // 得到公钥
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        // 得到公钥字符串
        String publicKeyString = new String(Base64.getEncoder().encode(publicKey.getEncoded()));
        // 得到私钥字符串
        String privateKeyString = new String(Base64.getEncoder().encode((privateKey.getEncoded())));
        return new RsaKeyPair(publicKeyString, privateKeyString);
    }

    /**
     * RSA公钥加密
     *
     * @param plainText 加密字符串
     * @param publicKey 公钥
     * @return 密文
     * @throws Exception
     */
    public static String encrypt(String plainText, String publicKey) throws Exception {
        //base64编码的公钥
        byte[] decoded = Base64.getDecoder().decode(publicKey.getBytes(UTF8));
        RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
        //RSA加密
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        byte[] encodeBytes = Base64.getEncoder().encode(cipher.doFinal(plainText.getBytes(UTF8)));
        return new String(encodeBytes, UTF8);
    }

    /**
     * RSA私钥解密
     *
     * @param encryptText 加密字符串
     * @param privateKey  私钥
     * @return 明文
     * @throws Exception
     */
    public static String decrypt(String encryptText, String privateKey) throws Exception {
        //64位解码加密后的字符串
        byte[] inputByte = Base64.getDecoder().decode(encryptText.getBytes(UTF8));
        //base64编码的私钥
        byte[] decoded = Base64.getDecoder().decode(privateKey.getBytes(UTF8));
        RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
        //RSA解密
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, priKey);
        String outStr = new String(cipher.doFinal(inputByte));
        return outStr;
    }


    public static void main(String[] args) throws Exception {
        // 生成公钥和私钥
        RsaKeyPair rsaKeyPair = generateKeyPair();
        // 加密字符串
        String message = "river106";
        System.out.println("随机生成的公钥为:" + rsaKeyPair.getPublicKey());
        System.out.println("随机生成的私钥为:" + rsaKeyPair.getPrivateKey());
		System.out.println("原始内容: "+message);
        String encryptText = encrypt(message, rsaKeyPair.getPublicKey());
        System.out.println("加密后的字符串为:" + encryptText);
        String messageDe = decrypt(encryptText, rsaKeyPair.getPrivateKey());
        System.out.println("解密后的字符串为:" + messageDe);
    }

    private static class RsaKeyPair {
        private String publicKey;
        private String privateKey;

		public RsaKeyPair() {
		}

		public RsaKeyPair(String publicKey, String privateKey) {
            this.publicKey = publicKey;
            this.privateKey = privateKey;
        }

        public String getPublicKey() {
            return publicKey;
        }

        public void setPublicKey(String publicKey) {
            this.publicKey = publicKey;
        }

        public String getPrivateKey() {
            return privateKey;
        }

        public void setPrivateKey(String privateKey) {
            this.privateKey = privateKey;
        }
    }

}


5、DES

DES是对称的块加密算法,加解密的过程是可逆的。

DES 加密算法是一种 分组密码,以 64 位为 分组对数据 加密,它的 密钥长度 是 56 位,加密解密 用 同一算法。

DES 加密算法是对 密钥 进行保密,而 公开算法,包括加密和解密算法。这样,只有掌握了和发送方 相同密钥 的人才能解读由 DES加密算法加密的密文数据。因此,破译 DES 加密算法实际上就是 搜索密钥的编码。对于 56 位长度的 密钥 来说,如果用 穷举法 来进行搜索的话,其运算次数为 2 ^ 56 次。

java代码如下:

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;


public class DesUtils {

    private static final String UTF8 = "UTF-8";
    private static byte[] iv = {1, 2, 3, 4, 5, 6, 7, 8};

    /**
     * DES加密
     * @param plainText   待加密内容
     * @param encryptKey  加密key
     * @return
     * @throws Exception
     */
    public static String encrypt(String plainText, String encryptKey) throws Exception {
        IvParameterSpec zeroIv = new IvParameterSpec(iv);
        SecretKeySpec key = new SecretKeySpec(encryptKey.getBytes(), "DES");
        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, key, zeroIv);
        byte[] encryptedData = cipher.doFinal(plainText.getBytes(UTF8));
        return new String(Base64.getEncoder().encode(encryptedData), UTF8);
    }

    /**
     * DES解密
     * @param encryptedText  已加密内容
     * @param decryptKey     解密key
     * @return
     * @throws Exception
     */
    public static String decrypt(String encryptedText, String decryptKey) throws Exception {
        IvParameterSpec zeroIv = new IvParameterSpec(iv);
        SecretKeySpec key = new SecretKeySpec(decryptKey.getBytes(UTF8), "DES");
        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, key, zeroIv);
        byte decryptedData[] = cipher.doFinal(Base64.getDecoder().decode(encryptedText.getBytes(UTF8)));
        return new String(decryptedData, UTF8);
    }


}

6、AES

AES是对称的块加密算法,加解密的过程是可逆的。

AES 加密算法是密码学中的高级加密标准,该加密算法采用 对称分组密码体制,密钥长度的最少支持为 128 位、 192 位、256 位,分组长度 128 位,算法应易于各种硬件和软件实现。这种加密算法是美国联邦政府采用的 区块加密标准。

AES 本身就是为了取代 DES 的,AES 具有更好的 安全性、效率 和 灵活性。

java代码如下:

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;

public class AesUtils {


    /**
     * 加密
     *
     * @param content  需要加密的内容
     * @param password 加密密码
     * @return
     */
    public static String encrypt(String content, String password) throws Exception {
        StringBuilder sb = new StringBuilder();
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
        secureRandom.setSeed(password.getBytes());
        kgen.init(128, secureRandom);
        SecretKey secretKey = kgen.generateKey();
        byte[] enCodeFormat = secretKey.getEncoded();
        SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
        // 创建密码器
        Cipher cipher = Cipher.getInstance("AES");
        byte[] byteContent = content.getBytes("utf-8");
        // 初始化
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] result = cipher.doFinal(byteContent);
        //将10进制字节数组转化为16进制字符串
        for (int i = 0; i < result.length; i++) {
            String hex = Integer.toHexString(result[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    /**
     * 解密
     *
     * @param content  待解密内容
     * @param password 解密密钥
     * @return
     */
    public static String decrypt(String content, String password) throws Exception {
        //将16进制字符创转为10进制字节数组
        byte[] result = new byte[content.length() / 2];
        for (int i = 0; i < content.length() / 2; i++) {
            int high = Integer.parseInt(content.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(content.substring(i * 2 + 1, i * 2 + 2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
        secureRandom.setSeed(password.getBytes());
        kgen.init(128, secureRandom);
        SecretKey secretKey = kgen.generateKey();
        byte[] enCodeFormat = secretKey.getEncoded();
        SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
        // 创建密码器
        Cipher cipher = Cipher.getInstance("AES");
        // 初始化
        cipher.init(Cipher.DECRYPT_MODE, key);
        byte[] data = cipher.doFinal(result);
        return new String(data);
    }

}


 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java提供了许多对称加密算法实现,下面是一种常见的实现方式: ```java import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.util.Base64; public class SymmetricEncryption { public static void main(String[] args) throws Exception { String plainText = "Hello, world!"; String secretKey = "ThisIsASecretKey"; // Create the key SecretKey key = new SecretKeySpec(secretKey.getBytes(), "AES"); // Create the cipher Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, key); // Encrypt the plaintext byte[] encryptedText = cipher.doFinal(plainText.getBytes()); String encryptedBase64 = Base64.getEncoder().encodeToString(encryptedText); System.out.println("Encrypted text: " + encryptedBase64); // Decrypt the encrypted text cipher.init(Cipher.DECRYPT_MODE, key); byte[] decryptedText = cipher.doFinal(Base64.getDecoder().decode(encryptedBase64)); System.out.println("Decrypted text: " + new String(decryptedText)); } } ``` 在上面的代码中,我们使用了AES算法进行加密和解密。首先,我们创建了一个SecretKey对象,该对象是由密钥字符串构造而成的。然后,我们创建了一个Cipher对象,该对象用于加密或解密数据。我们将加密模式设置为ENCRYPT_MODE,以便它知道我们要加密数据。我们使用doFinal方法对明文进行加密,并将结果转换为Base64编码的字符串。最后,我们使用相同的密钥和Cipher对象将加密后的文本解密,并打印出解密后的明文。 需要注意的是,这里我们使用了ECB模式和PKCS5Padding填充。这些是常见的模式和填充方式,但在实际应用中,可能需要根据具体需求选择不同的模式和填充方式。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值