我是靠谱客的博主 冷静毛巾,最近开发中收集的这篇文章主要介绍行走江湖,安全第一 | 非对称加密算法介绍与实现一、非对称加密算法介绍与实现二、数字签名原理与实现,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

行走江湖,安全第一 | 非对称加密算法设计与实现

  • 一、非对称加密算法介绍与实现
    • (1) 非对称加密简介
    • (2)Java实现非对称加密
  • 二、数字签名原理与实现
    • (1) 数字签名原理介绍
    • (2) Java实现数字签名


一、非对称加密算法介绍与实现

(1) 非对称加密简介

非对称加密算法,亦称为现代加密算法,是计算机通信安全的基石,保证了加密数据不会被破解。与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey) 和私密(privatekey)。

特点:非对称加密算法中,公开密钥和私有密钥是一对。特点是公钥加密-私钥解密私钥加密-公钥解密。因为加密和解密使用的是两个不同的密钥,所以这种算法才被叫作非对称加密算法。当然,事物也有两面性,由于非对称加密安全级别较高,所以处理数据的速度相对较慢。

【通俗易懂的理解非对称加密】
以A向B发生一个敏感文件需要加密为例????

  • 对称加密就是:A用锁锁住文件,发给B,然后A再发钥匙给B,B拿到锁和钥匙,解锁文件。
  • 非对称加密是:A要向B发文件,B把自己的锁发给A,A锁好后给B,B的钥匙一直在自己手上,>用自己的钥匙(私钥)解自己的锁(公钥),这样就不用担心钥匙在传递过程中被窃取。

ECC算法 和 RSA算法的比较

RSA算法:国际标准算法,应用较早,最为普及,比ECC算法的适用范围更广,兼容性更好,一般采用 2048 位的加密长度,但是对服务端性能消耗高。

ECC算法:中文名称为椭圆加密算法,新一代算法趋势主流,一般采用 256 位加密长度,加密速度快,效率更高,对服务器资源消耗低,而且最重要的是更安全,抗攻击型更强。
在这里插入图片描述

(2)Java实现非对称加密

下面的代码演示了使用Java实现非对称加密算法,主要实现了下面这些方法:

  • 使用密钥解密数据:public static String decryptRSA(String algorithm, Key key, String encrypted)
  • 使用密钥加密数据:public static String encryptRSA(String algorithm, Key key, String input)
  • 生成密钥对并保存在本地文件中:private static void generateKeyToFile(String algorithm, String pubPath, String priPath)
  • 读取私钥:public static PrivateKey getPrivateKey(String priPath, String algorithm)
  • 读取公钥:public static PublicKey getPublicKey(String pulickPath, String algorithm)
/**
 * description: RSAdemo 生成公钥和私钥
 * @author: gql
 * @date: 2021/10
 */
public class RSAdemo {
    public static void main(String[] args) throws Exception {
        String input = "匿名攻城狮";
        System.out.println("原文内容是 = " + input);

        // 表示使用RSA加密算法
        String algorithm = "RSA";

        // 生成密钥对并保存在本地文件中
        generateKeyToFile(algorithm, "a.pub", "a.pri");
        System.out.println("密钥对保存至本地成功!");

        // 读取私钥和公钥
        PrivateKey privateKey = getPrivateKey("a.pri", algorithm);
        PublicKey publicKey = getPublicKey("a.pub", algorithm);

        //加密
        String s = encryptRSA(algorithm, privateKey, input);
        // 解密
        decryptRSA(algorithm, publicKey, s);
    }

    /**
     * 使用密钥解密数据
     *
     * @param algorithm      : 算法
     * @param encrypted      : 密文
     * @param key            : 密钥
     * @return : 原文
     * @throws Exception
     */
    public static String decryptRSA(String algorithm, Key key, String encrypted) throws Exception {
        // 创建加密对象
        // 参数表示加密算法
        Cipher cipher = Cipher.getInstance(algorithm);
        // 私钥进行解密
        cipher.init(Cipher.DECRYPT_MODE, key);
        // 由于密文进行了Base64编码, 在这里需要进行解码
        byte[] decode = Base64.decode(encrypted);
        // 对密文进行解密,不需要使用base64,因为原文不会乱码
        byte[] bytes1 = cipher.doFinal(decode);
        System.out.println("公钥解密后 = " + new String(bytes1));
        return new String(bytes1);

    }

    /**
     * 使用密钥加密数据
     *
     * @param algorithm      : 算法
     * @param input          : 原文
     * @param key            : 密钥
     * @return : 密文
     * @throws Exception
     */
    public static String encryptRSA(String algorithm, Key key, String input) throws Exception {
        // 创建加密对象
        Cipher cipher = Cipher.getInstance(algorithm);
        // 加密的模式,使用私钥或公钥加密
        cipher.init(Cipher.ENCRYPT_MODE, key);
        // 私钥加密
        byte[] bytes = cipher.doFinal(input.getBytes());
        // 对密文进行Base64编码
        System.out.println("私钥加密后 = " + Base64.encode(bytes));
        return Base64.encode(bytes);
    }

    /**
     * 生成密钥对并保存在本地文件中
     *
     * @param algorithm : 算法选型
     * @param pubPath   : 公钥保存路径
     * @param priPath   : 私钥保存路径
     * @throws Exception
     */
    private static void generateKeyToFile(String algorithm, String pubPath, String priPath) throws Exception {
        // 创建密钥对生成器对象
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
        // 生成密钥对
        KeyPair keyPair = keyPairGenerator.generateKeyPair();

        // 生成私钥和公钥
        PrivateKey privateKey = keyPair.getPrivate();
        PublicKey publicKey = keyPair.getPublic();

        // 获取私钥和公钥的字节数组
        byte[] privateKeyEncoded = privateKey.getEncoded();
        byte[] publicKeyEncoded = publicKey.getEncoded();

        // 同时对私钥和公钥进行base64编码
        String privateKeyString = Base64.encode(privateKeyEncoded);
        String publicKeyString = Base64.encode(publicKeyEncoded);

        System.out.println("生成私钥 = " + privateKeyString);
        System.out.println("生成公钥 = " + publicKeyString);

        // 保存文件
        FileUtils.writeStringToFile(new File(priPath), privateKeyString, Charset.forName("UTF-8"));
        FileUtils.writeStringToFile(new File(pubPath), publicKeyString, Charset.forName("UTF-8"));
    }

    /**
     * 读取私钥
     * @param priPath 私钥存放路径
     * @param algorithm 算法
     * @return
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(String priPath, String algorithm) throws Exception {
        // 将文件内容转为字符串
        String privateKeyString = FileUtils.readFileToString(new File(priPath), Charset.defaultCharset());
        // 获取密钥工厂
        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        // 构建密钥规范 进行Base64解码
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(Base64.decode(privateKeyString));
        // 生成私钥
        return keyFactory.generatePrivate(spec);
    }

    /**
     * 读取公钥
     * @param pulickPath 公钥存放路径
     * @param algorithm 算法
     * @return
     * @throws Exception
     */
    public static PublicKey getPublicKey(String pulickPath, String algorithm) throws Exception {
        // 将文件内容转为字符串
        String publicKeyString = FileUtils.readFileToString(new File(pulickPath), Charset.defaultCharset());
        // 获取密钥工厂
        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        // 构建密钥规范 进行Base64解码
        X509EncodedKeySpec spec = new X509EncodedKeySpec(Base64.decode(publicKeyString));
        // 生成公钥
        return keyFactory.generatePublic(spec);
    }
}

代码运行后,控制台显示了如下内容,并在项目中生成了a.pri和a.pub两个txt文件,保存了私钥和密钥。

原文内容是 = 匿名攻城狮
生成私钥 = MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC/AtIjVD/1uumo8rrDlXIa3eUIyxThYcXgC2Vfy7pmnM4XA6zXVciVcL9+f9hBT5lDHrl5q6j2mufnGx6M+JMyOe3ceNrhs63i0VWpZ4lWRsCBZab6uxdPwGqhMYBpdYcARo3WtN7kmZxWtJW3q22Gj6zpNOv6eHAIGSKHzQlqmnNcvLEflrc0LRbAaXDl0bAAqMVnyg33hJesiD1cwSONPEFXKC6UXoQGm1Y+bvCGFyMstWAW8oHk2ERC8ZA6OA0k9UjezW++KxhIH9J/eLKoXpGto0vAfQYyvTiaUIjUVqJuf3WROkbwlGYisf1KocbdNFJmuKgPGH057X46QqCTAgMBAAECggEASJ/z8gbYgr/ck6YmqLKrvddce+lrOP6J09PBaZj2eIlqOonlL8KoD1ndFWXafYqcRU7rSn2gMpNXVSGUjhj9Ln2kGM3Cu0or9S+OmGiLaUhhbVGPGYoFJQeOA1fk8TQEbnBlAZunm9dj//uNaVY+wIjkP48loggk4I9d97BXwjXrBkjALQmZ6LcIzKOFTkkoH+3ibISHY7PjjfmO+1KJ30rKuJlTEGLStMHvQW7rRbeJEst48JWYGy/Gg82paLHLsKXzkWaM4l5/sP3dMDRCMY9nlV1dtLFun60WFxyBhFBKH4KbLnB5TzatpO/yacE8He9mJgBmp+p9qOB2NlxtcQKBgQDoWhpEX8niNgqIASw7ZsZrsqK6ZmIDCwbtC9zj5c1HoGeLZaWIZ+LekxodHTDSVufkIAluUVsi/cttdb5DBIFmCAfcEmSu+atdp4/nvqrndft+fpMZ7DL8YKpajd8i5t4NFF7AIbM071YZCV8W3Xo5icv6HPkdctBS5aidaiLu7QKBgQDSc5X35fq+5qkBE3rp0ntzjXlPbJem5Y2jtFzjwper003g6g0Z1ojOUwNEen+taeaVI8LmCefozwLLYayPU+KeyWftJOfV8UculNWM3xNsvgf/Q/iDVxUNu9gqdlvRIrDWcsGwwrpBqFB6D4GhrYh5tinRe5ct+sSAgu5SRGpdfwKBgATlaSpJrnJi2yP0il8SElpQoFc3MxeHUvUJy/TNcd7xhV0NnkhakBBKn0E/zTiRdj97YVd+xWHeYTwEQCcfYC6rOqcriA2b2z2U+1ZR0T4hYVRQDH9+V7CzxMM1vB77KHC0Hi8ERsd1x6WtaeCMeDfgLHkvxRwWwEcO6devVd8dAoGBAII8b4lq9EKhYeM9l+oNjMJUwcbqD+uD0aSGYJm+ebgm2uIeVZ8wyZbNfo8pM8wwZjbTW7CaXr8PJM6SEoTcR7k2MK9sEGCwoPltt74m6tF3xGEvQiKdiHToU3zrpCSHUGJVwBHQYA1zyOHQqMtSJcwUdEqkLkmRD3vsCuo0VpKnAoGBAIE1HGHbnRtYJiUQx1GShBpnAOldTVNG/zkNXYviB5HqCOcXrvHEo7tZdNKPUIhIvkQ9enL00YxGxcKic1byccrR9JOCfZKpkwASfmZErK+QLt36RkluaJ3/h9EEcdLTJw8Zeb5KDeoOPtnbxlJeQ5hNp9W8OglTDUWEXOiUoXL8
生成公钥 = MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvwLSI1Q/9brpqPK6w5VyGt3lCMsU4WHF4AtlX8u6ZpzOFwOs11XIlXC/fn/YQU+ZQx65eauo9prn5xsejPiTMjnt3Hja4bOt4tFVqWeJVkbAgWWm+rsXT8BqoTGAaXWHAEaN1rTe5JmcVrSVt6ttho+s6TTr+nhwCBkih80JappzXLyxH5a3NC0WwGlw5dGwAKjFZ8oN94SXrIg9XMEjjTxBVygulF6EBptWPm7whhcjLLVgFvKB5NhEQvGQOjgNJPVI3s1vvisYSB/Sf3iyqF6RraNLwH0GMr04mlCI1Faibn91kTpG8JRmIrH9SqHG3TRSZrioDxh9Oe1+OkKgkwIDAQAB
密钥对保存至本地成功!
私钥加密后 = RD10/pSv/tnAWgereonEmobu3vxKgK6GACmUrBnaD8yj05IUvj54IN2DAyvsRdGijQDrEdbSIoIJOQen5g0UYjE6hHDhHTvuJqpNn+coJ3XcNQzQC4/ANij/hTZGFVX6AinhtqbZgpUDKoIhloJi+g9PV+MOuKgYVD7Fv96VDSbgR2bsuqFMDDIXtBCGQdR//KZmt7vKZGQTCjnP8PPcgnu68iayKFS/Ja38IYojl1F/JdrmNMM9zBJDTF/RfcHrGSAty68MZwopm1EQ8iSrpmM9DD/1y4Nr5jJmac14d57EmifqTfQH3oB+3kqvrSiyvDOof78zpcrQylyFs5epYA==
公钥解密后 = 匿名攻城狮
加密后-密文内容是 = RD10/pSv/tnAWgereonEmobu3vxKgK6GACmUrBnaD8yj05IUvj54IN2DAyvsRdGijQDrEdbSIoIJOQen5g0UYjE6hHDhHTvuJqpNn+coJ3XcNQzQC4/ANij/hTZGFVX6AinhtqbZgpUDKoIhloJi+g9PV+MOuKgYVD7Fv96VDSbgR2bsuqFMDDIXtBCGQdR//KZmt7vKZGQTCjnP8PPcgnu68iayKFS/Ja38IYojl1F/JdrmNMM9zBJDTF/RfcHrGSAty68MZwopm1EQ8iSrpmM9DD/1y4Nr5jJmac14d57EmifqTfQH3oB+3kqvrSiyvDOof78zpcrQylyFs5epYA==
解密后-原文内容是 = 匿名攻城狮

二、数字签名原理与实现

(1) 数字签名原理介绍

数字签名,亦称公钥数字签名。属于非对称加密技术应用之一,非对称加密技术主要有两大应用:

  • 使用 公钥加密-私钥解密 的加密通信
  • 使用 私钥加密-公钥解密 的数字签名

在这里插入图片描述

数字签名的含义:在网络中传输数据的时候,给数据添加一个数字签名,表示是谁发的数据,而且还能证明数据没有被篡改。

数字签名的作用:认证、防止抵赖、防篡改

数字签名原理图
数字签名原理

数字签名的典型应用:用于网页加密的https协议

①首先,客户端向服务器发出加密请求。
②服务器用自己的私钥加密网页以后,连同本身的数字证书,一起发送给客户端。
③客户端(浏览器)的 “证书管理器”,有 “受信任的根证书颁发机构” 列表。客户端会根据这张列表,查看解开数字证书的公钥是否在列表之内。
④如果数字证书记载的网址,与你正在浏览的网址不一致,就说明这张证书可能被冒用,浏览器会发出警告。
在这里插入图片描述
⑤如果这张数字证书不是由受信任的机构颁发的,浏览器会发出另一种警告。
在这里插入图片描述
⑥如果数字证书是可靠的,客户端就可以使用证书中的服务器公钥,对信息进行加密,然后与服务器交换加密信息。

(2) Java实现数字签名

下面的代码演示了使用Java实现数字签名,主要实现了 签名算法 和 验证算法:

  • 签名算法:private static String getSignature(String str, String algorithm, PrivateKey privateKey)
    签名算法使用 私钥加密来生成签名。
    注意:签名算法不会对文件加密,只对文件的Hash值进行了加密
  • 验证算法:private static boolean verifySignature(String str, String algorithm, PublicKey publicKey, String signaturedData)
    验证算法使用 公钥解密-校验签名。
/**
 * description: SignatureDemo 数字签名
 * @author: gql
 * @date: 2021/10
 */
public class SignatureDemo {
    public static void main(String[] args) throws Exception {
        String str = "Hudie";
        System.out.println("原文是 = " + str);

        // 从文件中获取私钥和公钥
        PrivateKey privateKey = RSAdemo.getPrivateKey("a.pri", "RSA");
        PublicKey publicKey = RSAdemo.getPublicKey("a.pub", "RSA");

        /**
         * 签名算法:
         *  输入:文件、私钥(签名Key)
         *  输出:数字签名
         */
        String signaturedData = getSignature(str, "sha256withrsa", privateKey);
        System.out.println("生成的数字签名是 = " + signaturedData);

        /**
         * 验证算法:
         *  输入:文件、数字签名、公钥(验证Key)
         *  输出:YES/NO
         */
        boolean flag = verifySignature(str, "sha256withrsa", publicKey, signaturedData);
        System.out.println("使用公钥和生成的签名进行验证: = " + flag);
    }

    /**
     * 签名算法:
     *      私钥加密-生成签名
     * 注意:签名算法不会对文件加密,只对文件的Hash值进行了加密
     * @param str      : 原文
     * @param algorithm  : 算法
     * @param privateKey : 私钥
     * @return : 数字签名
     * @throws Exception
     */
    private static String getSignature(String str, String algorithm, PrivateKey privateKey) throws Exception {
        // 获取签名对象
        Signature signature = Signature.getInstance(algorithm);
        // 初始化签名
        signature.initSign(privateKey);
        // 传入原文
        signature.update(str.getBytes());
        // 开始签名
        byte[] sign = signature.sign();
        // 对签名数据进行Base64编码
        return Base64.encode(sign);
    }

    /**
     * 验证算法:
     *      公钥解密-校验签名
     * @param str          : 原文
     * @param algorithm      : 算法
     * @param publicKey      : 公钥
     * @param signaturedData : 数字签名
     * @return : 数据是否被篡改
     * @throws Exception
     */
    private static boolean verifySignature(String str, String algorithm, PublicKey publicKey, String signaturedData) throws Exception {
        // 获取签名对象
        Signature signature = Signature.getInstance(algorithm);
        // 初始化签名
        signature.initVerify(publicKey);
        // 传入原文
        signature.update(str.getBytes());
        // 校验数据
        return signature.verify(Base64.decode(signaturedData));
    }
}

部分内容参考:b站数字签名原理

最后

以上就是冷静毛巾为你收集整理的行走江湖,安全第一 | 非对称加密算法介绍与实现一、非对称加密算法介绍与实现二、数字签名原理与实现的全部内容,希望文章能够帮你解决行走江湖,安全第一 | 非对称加密算法介绍与实现一、非对称加密算法介绍与实现二、数字签名原理与实现所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(62)

评论列表共有 0 条评论

立即
投稿
返回
顶部