开箱即用系列-工具包-非对称加密算法-RSA

加密算法种类:

  1. 对称加密
    对称加密,意味着加密和解密使用同一个秘钥,安全级别相对于非对称加密要低.
  2. 非对称加密
    非对称加密,意味着加密和解密使用不同的秘钥,安全级别相对于对称加密要高.
  3. hash算法
    hash算法是一种单向算法,不可还原成加密之前的元字符.
    常用的加密算法
    常见的对称加密算法
    DES、3DES、DESX、Blowfish、IDEA、RC4、RC5、RC6和AES
    常见的非对称加密算法
    RSA、ECC、Diffie-Hellman、El Gamal、DSA
    常见的Hash算法
    MD2、MD4、MD5、HAVAL、SHA、SHA-1、HMAC、HMAC-MD5、HMAC-SHA1
    非对称加密算法-RSA实现
依赖的POM:
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
实现代码:
import com.bruce.tool.common.exception.ExceptionUtils;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Objects;

@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class RSA {

    private static final String KEY_ALGORITHM = "RSA";
    private static final String RSA_SIGNATURE_ALGORITHM = "SHA1withRSA";

    /**
     * 初始化密钥
     */
    public static KeyPair init() {
        try {
            KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
            keyPairGen.initialize(1024);
            return keyPairGen.generateKeyPair();
        } catch (Exception e) {
            ExceptionUtils.printStackTrace(e);
        }
        return null;
    }

    /**
     * 取得公钥
     */
    public static String publicKey(KeyPair keyPair) {
        if(Objects.isNull(keyPair) ){ return null; }
        return Base64.encode(keyPair.getPublic().getEncoded());
    }

    /**
     * 取得私钥
     */
    public static String privateKey(KeyPair keyPair) {
        if(Objects.isNull(keyPair)){ return null; }
        return Base64.encode(keyPair.getPrivate().getEncoded());
    }

    /**
     * 用公钥加密
     * @param data 元数据字节码
     * @param base64PublicKey base64编码过的公钥(publicKey)
     * @return 加密结果
     */
    public static byte[] encrypt(byte[] data, String base64PublicKey) {
        try {
            // 对公钥解密
            byte[] keyBytes = Base64.decode(base64PublicKey);
            // 取得公钥
            X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            Key publicKey = keyFactory.generatePublic(x509KeySpec);
            // 对数据加密
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);

            return cipher.doFinal(data);
        } catch (Exception e) {
            ExceptionUtils.printStackTrace(e);
        }
        return new byte[0];
    }

    /**
     * 用私钥解密
     * @param data 元数据字节码
     * @param base64PrivateKey base64编码过的私钥(privateKey)
     * @return 解码结果
     */
    public static byte[] decrypt(byte[] data, String base64PrivateKey) {
        try {
            // 对密钥解密
            byte[] keyBytes = Base64.decode(base64PrivateKey);

            // 取得私钥
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);

            // 对数据解密
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, privateKey);

            return cipher.doFinal(data);
        } catch (Exception e) {
            ExceptionUtils.printStackTrace(e);
        }
        return new byte[0];
    }

    /**
     * 签名-私钥签名
     * @param data 元数据字节码
     * @param base64PrivateKey base64编码过的私钥
     * @return 签名结果
     */
    public static byte[] sign(byte[] data, String base64PrivateKey){
        try {
            // Base64 --> Key
            byte[] bytes = Base64.decode(base64PrivateKey);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
            // Sign
            Signature signature = Signature.getInstance(RSA_SIGNATURE_ALGORITHM);
            signature.initSign(privateKey);
            signature.update(data);
            return signature.sign();
        } catch (Exception e) {
            ExceptionUtils.printStackTrace(e);
        }
        return new byte[0];
    }

    /**
     * 验签-公钥验签
     *
     * @param data 需要验签的字符串
     * @param base64PublicKey base64编码之后的公钥
     * @param sign 需要验证的签名
     * @return
     */
    public static boolean verify(byte[] data, String base64PublicKey, String sign) {
        try {
            // Base64 --> Key
            byte[] bytes = Base64.decode(base64PublicKey);
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            PublicKey publicKey = keyFactory.generatePublic(keySpec);
            // verify
            Signature signature = Signature.getInstance(RSA_SIGNATURE_ALGORITHM);
            signature.initVerify(publicKey);
            signature.update(data);
            return signature.verify(Base64.decode(sign));
        } catch (Exception e) {
            ExceptionUtils.printStackTrace(e);
        }
        return false;
    }

}
测试类:

import com.bruce.tool.common.util.LogUtils;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.security.KeyPair;

@Slf4j
public class RSATest {

    /**生成签名**/
    @Test
    public void createKeys() {
        KeyPair keyPair = RSA.init();
        LogUtils.info(log,RSA.publicKey(keyPair));
        LogUtils.info(log,RSA.privateKey(keyPair));
    }

    /**签名和验签**/
    @Test
    public void signAndVerify() {
    	KeyPair keyPair = RSA.init();
        String publicKey = RSA.publicKey(keyPair));
        String privateKey = RSA.privateKey(keyPair));
        String payload = "a=1&b=2&c=3";
        byte[] sign = RSA.sign(payload.getBytes(),privateKey);
        LogUtils.info(log,Base64.encode(sign));
        boolean verify = RSA.verify(payload.getBytes(),publicKey,Base64.encode(sign));
        LogUtils.info(log,verify);
    }

    /**加密解密**/
    @Test
    public void encryptAndDecrypt() {
        KeyPair keyPair = RSA.init();
        String publicKey = RSA.publicKey(keyPair));
        String privateKey = RSA.privateKey(keyPair));
        String payload = "123456";
        byte[] encrypts = RSA.encrypt(payload.getBytes(),publicKey);
        LogUtils.info(log,Base64.encode(encrypts));
        byte[] decrypts = RSA.decrypt(Base64.decode(Base64.encode(encrypts)),privateKey);
        LogUtils.info(log,new String(decrypts));
    }
}

补充说明

  1. 在做计算算法概念确定的时候,最初给加密算法想当然的给列了如下的种类:

    1.不可逆加密(不可解密)
    	不可逆,意味着加密之后,不能被解密.
    2.可逆加密(可解密)
    	A.对称加密
       		对称加密,意味着加密和解密使用同一个秘钥,安全级别相对于非对称加密要低.
    	B.非对称加密
       		非对称加密,意味着加密和解密使用不同的秘钥,安全级别相对于对称加密要高.
    

    在想说明一下MD5的时候,觉着不太精确,怕误导大家,于是,到CSDN首页查了一下,发现一篇文章MD5到底是不是加密算法,于是修改了关于算法的种类说明.

  2. 关于加密算法,还有许多知识点,在此并没有细说,因为这片文章的目的是"开箱即用".

  3. 文章里边使用到lombok,使用ide的童鞋,请安装对应的lombok插件.

  4. 文章里边使用到ExceptionUtils以及LogUtils是我自己封装的工具类,大家用的时候,可以替换成自己的.

参考文献
1.百度百科-算法种类说明
2.百度百科-RSA算法说明
3.博客园-常用加密算法概述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值