Java - 实现RSA加解密

1. 数据安全和加密简介

在项目的功能中,涉及密码的输入,都应该使用相应的加密算法来对传输的密码进行加密

加密的算法有很多,通常分为两种:对称加密和非对称加密

1.1 对称加密算法

DES:

  • 主要采用替换和移位的方法加密,对64位二进制数据块进行加密,密钥长度为64位
  • 过程会经历16轮编码
  • 优点:加密速度快,密钥产生容易,安全性较高(目前只有穷举法能破解)
  • 缺点:不能抵抗对密钥的穷举搜索攻击,是因为DES的密钥较短(64位密钥中,只有56位密钥用来进行加密)

3DES:

  • 在DES的基础上采用三重DES
  • 用两个56位的密钥K1、K2进行加密
  • 发送方用K1加密,K2解密,再使用K1加密
  • 接收方则使用K1解密,K2加密,再使用K1解密

IDEA:其明文和密文都是64位,密钥长度为128位,比DES的加密性好,而且对计算机功能要求也没有这么高

还有一个本人不太了解的 RC-5 算法,大家有兴趣的话,可以去了解一下

对称加密算法在电子商务交易过程中存在的问题:

  • 密钥难于传输
  • 密钥的数目难于管理
  • 对称加密算法一般不能提供信息完整性的鉴别
  • 对称密钥的管理和分发工作是一件具有潜在危险的和烦琐的过程

1.2 非对称加密算法

是指加密秘钥和解密秘钥不同

常见的非对称密钥加密算法:RSA算法,具有数字签名和验证的功能

1.3 其他

信息摘要:

  • 实际上就是一个单向散列函数,数据块经过单向散列函数得到一个固定长度的散列值
  • 攻击者不可能通过散列值而编造数据块
  • 常用的消息摘要算法:MD5(散列值为128位),SHA(散列值为160位)等,由于SGA通常采用的密钥长度较长,因此安全性高于MD5

数字签名:

  • 发送者不能否认发送的消息,接受者不能篡改接收的消息
  • 确认了文件已签署这一事实
  • 确定了文件是真的这一事实

数字时间戳技术:

  • 是数字签名技术一种变种的应用,是网上电子商务安全服务项目之一,能提供电子文件的日期和时间信息的安全保护
  • DTS解码时间戳的英文缩写,是一个计算机系统函数
  • 是一个经加密后形成的凭证文档,包括:
    • 需加时间戳的文件的摘要
    • DTS收到文件的日期和时间
    • DTS的数字签名

SSL安全协议:

  • 安全套接层,它是在传输通信协议(TCP/IP)上实现的一种安全协议,采用公开密钥技术
  • 是与应用层协议独立无关的
  • 三种安全服务:(使用公开密钥技术)
    • 信息加密
    • 信息完整性
    • 双向认证

2. 准备

因为本人在自己的一个项目中,在实现登录功能时,密码进行传输时使用了 RSA 加密算法,所以下面也是以 RSA 加密算法为主

首先要有一个生成公私钥的工具,大家可以去我的资源进行下载

支付宝平台开发助手下载:https://download.csdn.net/download/wanzijy/86268901

下载完后,运行会看到如下界面:
Java - 实现RSA加解密_第1张图片
按照图中操作,从上到下进行点击即可在电脑中生成 RSA 算法的公钥与私钥

3. 加解密代码

逻辑:

  • 从安全性进行考虑,在数据库的密码肯定是以密文进行存储的
  • 在前端输入密码,向后端进行传输时,应该要加密完后再向后端传输
  • 将从数据库取出来的密码密文和前端传来的密码密文分别解码后再进行比较

加解密的 Java 代码如下:

import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.codec.binary.Base64;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.UnsupportedEncodingException;
import java.security.*;
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;


/**
 * @author LinTao
 * @date 2022/2/13
 * RSA工具类  默认长度为2048位
 */
@Slf4j
public class RSAUtil {

    private static final int DEFAULT_RSA_KEY_SIZE = 2048;

    private static final String KEY_ALGORITHM = "RSA";

    private static final String SIGNATURE_ALGORITHM = "MD5withRSA";

    public static void main(String [] args){
        Map<String,String> result = generateRsaKey(DEFAULT_RSA_KEY_SIZE);
        System.out.println("公钥为:" + result.get("publicKey") );
        System.out.println("私钥为:" + result.get("privateKey"));
    }

    /**
     * 生成RSA 公私钥,可选长度为1025,2048位.
     */
    public static Map<String,String> generateRsaKey(int keySize) {
        Map<String,String> result = new HashMap<>(2);
        try {
            KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);

            // 初始化密钥对生成器,密钥大小为1024 2048位
            keyPairGen.initialize(keySize, new SecureRandom());

            // 生成一个密钥对,保存在keyPair中
            KeyPair keyPair = keyPairGen.generateKeyPair();

            // 得到公钥字符串
            result.put("publicKey", new String(Base64.encodeBase64(keyPair.getPublic().getEncoded())));

            // 得到私钥字符串
            result.put("privateKey", new String(Base64.encodeBase64(keyPair.getPrivate().getEncoded())));

        } catch (GeneralSecurityException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * RSA私钥解密
     * @param str  解密字符串
     * @param privateKey  私钥
     * @return 明文
     */
    public static String decrypt(String str, String privateKey) {
        //64位解码加密后的字符串
        byte[] inputByte;
        String outStr = "";
        try {
            inputByte = Base64.decodeBase64(str.getBytes("UTF-8"));
            //base64编码的私钥
            byte[] decoded = Base64.decodeBase64(privateKey);
            RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
            //RSA解密
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, priKey);
            outStr = new String(cipher.doFinal(inputByte));
        } catch (UnsupportedEncodingException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | InvalidKeySpecException | NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return outStr;
    }

    /**
     *  RSA公钥加密
     * @param str 需要加密的字符串
     * @param publicKey 公钥
     * @return 密文
     * @throws Exception 加密过程中的异常信息
     */
    public static String encrypt(String str, String publicKey) throws Exception {
        //base64编码的公钥
        byte[] decoded = Base64.decodeBase64(publicKey);
        RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
        //RSA加密
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        String outStr = Base64.encodeBase64String(cipher.doFinal(str.getBytes("UTF-8")));
        return outStr;
    }

}

上述的代码是在项目的后端使用,前端的加密可以去看我的另一篇文章

https://blog.csdn.net/wanzijy/article/details/125163500

你可能感兴趣的:(Java,java,开发语言)