非对称加密(RSA、DSA、ECC)

news/2024/7/8 4:32:39 标签: spring cloud

RSA

  • 目前最优秀的公钥方案,第一个能同时用于加密和数字签名的算法,能够抵抗到目前为止已知的所有密码攻击
  • 基于一个十分简单的数论事实:将两个大素数相乘十分容易,但对其进行因式分解却十分困难,所以可以将其乘积公开作为加密密钥
  • 密钥生成算法简述:
    (1)随机选择两个不相等的质数p和q(这两个质数越大,就越难被破解)
    (2)计算p和q的乘积n,n的二进制长度就是密钥的长度(实际应用中,RSA密钥1024位,重要场合为2048位)
    (3)计算n的欧拉函数φ(n)【φ(n) = (p-1)(q-1)】
    (4)随机选择一个整数e,条件是1< e < φ(n),且e与φ(n) 互质
    (5)计算e对于φ(n)的模反元素d(模反元素是指有一个整数d,可以使ed被φ(n)除的余数为1)
    (6)将n和e封装成公钥,n和d封装成私钥
  • 使用公钥(n,e)加密
    假设明文为m(m必须为整数,且m必须小于n),根据公式计算密文c: m^e ≡ c (mod n)
  • 使用私钥(n,d)解密
    c^d ≡ m (mod n),依次代入值后就可以计算出明文m

java使用Cipher进行RSA加密

import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

public class RSA {
    public static void main(String[] args) {
        try {
            //随机生成密钥对
            genKeyPair();
            System.out.println("随机生成的公钥为:" + keyMap.get(0));
            System.out.println("随机生成的私钥为:" + keyMap.get(1));
            //明文
            String message = "RSA是最好的非对称加密算法";
            System.out.println("待加密字符串:" + message);
            String encrypted = encrypt(message, keyMap.get(0));
            System.out.println("密文为:" + encrypted);

            //解密
            String decrypted = decrypt(encrypted, keyMap.get(1));
            System.out.println("解密后:" + decrypted);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private static final String ALGORITHM = "RSA";
    private static Map<Integer, String> keyMap = new HashMap<>();

    /**
     * 随机生成密钥对
     */
    public static void genKeyPair() throws Exception {
        //基于RSA使用KeyPairGenerator生成密钥对
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(ALGORITHM);
        //初始化密钥对生成器,密钥大小为96-1024位
        keyPairGen.initialize(1024, new SecureRandom());

        //生成一个密钥对,保存在keyPair中
        KeyPair keyPair = keyPairGen.generateKeyPair();
        //获取私钥
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        //获取公钥
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        //得到公钥字符串
        String publicKeyString = Base64.getEncoder().encodeToString(publicKey.getEncoded());
        //得到私钥字符串
        String privateKeyString = Base64.getEncoder().encodeToString(privateKey.getEncoded());

        //将公钥和私钥保存到map
        keyMap.put(0, publicKeyString);
        keyMap.put(1, privateKeyString);
    }

    /**
     * 加密
     */
    public static String encrypt(String str,String publicKeyString) throws Exception{
        //base64编码的公钥
        byte[] decoded = Base64.getDecoder().decode(publicKeyString);
        RSAPublicKey publicKey = (RSAPublicKey) KeyFactory.getInstance(ALGORITHM).generatePublic(new X509EncodedKeySpec(decoded));
        //RSA加密
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        String outStr = Base64.getEncoder().encodeToString(cipher.doFinal(str.getBytes(StandardCharsets.UTF_8)));
        return outStr;
    }

    /**
     * 解密
     */
    public static String decrypt(String str, String privateKeyString) throws Exception {
        byte[] inputBytes = Base64.getDecoder().decode(str.getBytes(StandardCharsets.UTF_8));
        //base64编码的私钥
        byte[] decoded = Base64.getDecoder().decode(privateKeyString);
        RSAPrivateKey privateKey = (RSAPrivateKey) KeyFactory.getInstance(ALGORITHM).generatePrivate(new PKCS8EncodedKeySpec(decoded));
        //RSA解密
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        String outStr = new String(cipher.doFinal(inputBytes));
        return outStr;
    }
}

DSA

  • DSA是一种更高级的验证方式,用作数字签名
  • 该算法不单单只有公钥、私钥还有数字签名,私钥加密生成数字签名,公钥验证数据及签名,如果数据和签名不匹配则认为验证失败
  • 数字签名的作用就是为了校验数据在传输过程中不被修改
  • DSA算法简述:
    (1)使用消息摘要算法将发送数据加密成数字摘要
    (2)发送方将数字摘要用自己的私钥加密,生成数字签名
    (3)将原文和加密的摘要同时传送给接收方
    (4)接收方用发送方的公钥对摘要解密,同时对收到的数据用消息摘要算法计算生成同一摘要
    (5)比对解密后的摘要和接收方自己生成的摘要,如果两者一致,则说明信息在传送过程中没有被破坏和篡改,否则,则说明信息已经失去了安全性和保密性
  • 可以看到的是DSA算法并不适合加密通信(因为它把原文未加密就直接发出去了),而是适用于验证信息是否被篡改过。

java使用DSA完成数字签名验证

import java.security.*;
import java.security.interfaces.DSAPrivateKey;
import java.security.interfaces.DSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

public class DSA {
    public static void main(String[] args) {
        try {
            //生成密钥对
            initKey();
            //公钥
            byte[] publicKey = getPublicKey();
            //私钥
            byte[] privateKey = getPrivateKey();
            //待加密密文
            String originalStr = "DSA是最好的数字签名算法";
            System.out.println("待加密字符串:" + originalStr);
            //发送方通过私钥进行数字签名
            byte[] sign = sign(originalStr.getBytes(), privateKey);
            String signString = Base64.getEncoder().encodeToString(sign);
            System.out.println("签名为:" + signString);
            //接收方使用公钥验证签名
            boolean status = verify(originalStr.getBytes(), publicKey, Base64.getDecoder().decode(signString));
            System.out.println("状态:" + status);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //密钥算法
    public static final String KEY_ALGORITHM = "DSA";
    //数字签名算法
    public static final String SIGNATURE_ALGORITHM = "SHA1withDSA";
    //DSA密钥长度(必须是64的倍数)
    private static final int KEY_SIZE = 1024;
    //存储密钥的map
    private static Map<Integer, Object> keyMap = new HashMap<>();

    /**
     * 初始化密钥对
     */
    public static void initKey() throws Exception {
        //实例化密钥生成器
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        //初始化密钥生成器
        keyPairGenerator.initialize(KEY_SIZE, new SecureRandom());
        //生成密钥对
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        //公钥
        DSAPublicKey publicKey = (DSAPublicKey) keyPair.getPublic();
        //私钥
        DSAPrivateKey privateKey = (DSAPrivateKey) keyPair.getPrivate();
        //将密钥放入map
        keyMap.put(0, publicKey);
        keyMap.put(1, privateKey);
    }

    /**
     * 生成数字签名
     */
    public static byte[] sign(byte[] data,byte [] privateKey) throws Exception{
        //取得私钥
        PKCS8EncodedKeySpec pkcs8 = new PKCS8EncodedKeySpec(privateKey);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        //生成私钥
        PrivateKey priKey = keyFactory.generatePrivate(pkcs8);
        //实例化签名
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        //初始化签名
        signature.initSign(priKey);
        //更新
        signature.update(data);
        return signature.sign();
    }

    /**
     * 校验数字签名
     */
    public static boolean verify(byte[] data, byte[] publicKey, byte[] sign) throws Exception {
        //转换公钥
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        //初始化公钥
        X509EncodedKeySpec x509 = new X509EncodedKeySpec(publicKey);
        //产生公钥
        PublicKey pubKey = keyFactory.generatePublic(x509);
        //实例化签名
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        //初始化签名
        signature.initVerify(pubKey);
        //更新
        signature.update(data);
        //验证
        return signature.verify(sign);
    }

    /**
     * 获取私钥
     */
    public static byte[] getPrivateKey() {
        Key key = (Key) keyMap.get(1);
        return key.getEncoded();
    }

    /**
     * 获取公钥
     */
    public static byte[] getPublicKey(){
        Key key = (Key) keyMap.get(0);
        return key.getEncoded();
    }
}

ECC

  • ECC相比其他非对称加密算法的优势在于它的密钥更小,RSA虽然安全级别高,但缺点也很明显,即加解密的耗时较长
  • 算法简述:
    (1)发送者选定一个椭圆曲线Ep(a,b),并取曲线上一点作为基点G
    (2)发送方选择一个d作为私钥,并生成公钥Q=dG
    (3)发送方将曲线Ep(a,b)和点G,Q一并发送给接收方
    (4)接收方收到消息后,将待传输的明文编码到曲线Ep(a,b)上的一点M,后随机选择一个整数k(k<n)
    (5)接收方计算点C1=M+kQ;C2=kG
    (6)接收方将C1,C2发给发送者
    (7)发送方接收到消息后,计算C1-dC2=M+kQ-d(kG)=M+k(dG)-d(kG)=M,得到点M,再对点M进行解码就得到明文。

由于Cipher不支持ECC代码,所以无了。


http://www.niftyadmin.cn/n/1756369.html

相关文章

接口加密(TokenSpringCloud项目中进行token认证)

文章目录接口加密常见加密算法消息摘要算法常用摘要算法&#xff08;MD5、SHA、CRC&#xff09;对称加密常用对称加密算法&#xff08;DES、3DES、AES&#xff09;非对称加密常用的非对称加密算法&#xff08;RSA、DSA、ECC&#xff09;数字签名Web认证机制HTTP Basic AuthCook…

MongoDB精简入门(体系结构、Docker安装MangoDB、常用命令)

文章目录什么样的场景会需要MongoDB什么是MongoDB特点MongoDB的体系结构MongoDB数据类型Docker安装MongoDBMongoDB的常用命令可视化工具什么样的场景会需要MongoDB 首先&#xff0c;我们已经学了很多数据库了&#xff0c;Redis、Mysql、Oracle&#xff0c;那为什么还需要Mongo…

Java链接MongoDB进行CRUD

文章目录Mongo-Driver开干创建一个maven工程&#xff0c;pom文件中添加依赖编写crud代码Mongo-Driver Mongo支持多种语言&#xff0c;mongo-driver是mongo官方推出的java连接mongoDB的驱动包&#xff0c;相当于JDBC驱动&#xff0c;通过mongo-driver完成对MongoDB的操作Mongo …

SpringBoot整合MongoDB完成增删改查(入门级)

文章目录开干整体文件结构如下创建springBoot项目&#xff0c;pom文件中添加相关依赖yaml文件中配置mongo地址准备一个实体类通过MongoTemplate查询通过MongoRepository的方式查询所有新增数据修改数据分页查询自定义的条件查询一些废话&#xff1a; 上一篇写了java链接MongoDB…

MySQL进阶_1 (体系结构、存储引擎、SQL优化、索引使用)

文章目录MySQL体系结构术语浅解一些缩写Mysql系统自带的数据库元数据MySQL数据库文件存储引擎Mysql存储引擎的特性概览MyISAMInnoDBMEMORYMERGE存储引擎怎么选SQL优化步骤查询SQL的执行效率定位低效率的SQLexplain命令分析执行计划show profile的使用优化器trace工具的使用索引…

MySQL进阶_2(应用优化、缓存优化、内存优化、锁)

文章目录一点前言应用优化连接池减少数据库的访问负载均衡缓存优化概述操作流程查询缓存参数设置查询缓存的使用缓存失效的情况内存优化优化原则内存优化说明MySQL并发度调整锁&#xff08;浅了解一下&#xff09;一点前言 Mysql可以通过调整参数进行调优&#xff0c;所以本篇…

关于打代码的一些些心得

些许废话 零零散散也正式以打代码为生快一年半了&#xff0c;从代码写的稀碎到稍微能总结出一点东西&#xff0c;也算是一个一直在向上缓慢行走的状态了 很难说我喜欢代码这件事&#xff0c;原本选择也只是为了糊口&#xff0c;但从面向百度编程&#xff0c;到一点点写出带着…

VMware Workstation中安装Centos 7,使用NAT模式连接网络

VMware Workstation有三种方式连接网络&#xff0c;其他两种请自行百度&#xff0c;这里着重讲解NAT方式。 从大学开始学Linux&#xff0c;装的Ubuntu&#xff0c;瞎jb地搞了下&#xff0c;就稀里糊涂联网了&#xff0c;后来换成Centos&#xff0c;又重新设置联网&#xff0c;…