• 非对称加密算法RSA


    RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。1987年首次公布,当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。

    RSA算法晚于DH算法,这五个字母全都是人名首字母.DH算法是第一个非对称密码体系.

    RSA算法运算速度慢,不适宜加密大量数据.一种解决方案是,将RSA跟对称加密方式混合使用,将数据使用对称加密方式加密,对称加密的密钥使用RSA算法加密,因为密钥很短,所以时间费不了太多.实际上,对称加密方式唯一的弊端就是密钥不好传递,对称加密方式也很难破解.

    RSA的适用情景一:

    (1)服务器生成一个公钥和一个私钥,把公钥公开了.

    (2)客户端使用公钥把数据进行加密,上交服务器.别人是没法理解加密后的数据的.

    (3)服务器使用私钥将数据解密,查看用户提交的数据.

    这种情景下,公钥像是一个信箱,每个人都可以往这个信箱里面放信,但是这个信箱里面的信只有掌握信箱钥匙的人才能开箱查看.

    RSA适用情景二:

    (1)皇上生成一个公钥和一个密钥,把公钥公开了.

    (2)皇上发布了一封诏书,昭告天下.诏书右下角有两串数字,第一串数字是一个随机串,第二串数字是用私钥加密第一串数字所得的结果.

    (3)有人不相信这诏书是皇上写的,就把第二串数字使用公钥解密,解密之后发现跟第一串数字一样,说明确实是皇上写的,因为一般人没有密钥,也就没法加密那些能够用公钥解密的数据.

    这种情境下,公钥用于解密,私钥用于加密,这可以用于发布公告时,证明这个公告确实是某个人发的.相当于签名.

    实际上,签名没有必要特别长,一般情况下,签名是定长的,要想定长,可以使用MessageDigest算法,如MD5和SHA系列.所以就有了多种签名算法,如MD5withRSA等.

    下面给出java库中RSA的用法,这个程序包括六部分:公钥加密解密,私钥加密解密,私钥签名公钥验证.

    public class RSA {
        /**
         * 定义加密方式
         */
        private final static String KEY_RSA = "RSA";
        /**
         * 定义签名算法
         */
        private final static String KEY_RSA_SIGNATURE = "MD5withRSA";
        static PrivateKey toPrivateKey(byte[] b)
                throws NoSuchAlgorithmException, InvalidKeySpecException {
            // 构造PKCS8EncodedKeySpec对象
            PKCS8EncodedKeySpec pkcs = new PKCS8EncodedKeySpec(b);
            // 指定的加密算法
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            // 取私钥对象
            return factory.generatePrivate(pkcs);
        }
        static PublicKey toPublicKey(byte[] b) throws Exception {
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(b);
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            return factory.generatePublic(keySpec);
        }
        // 用私钥对data签名
        public static byte[] sign(byte[] data, byte[] privateKey) throws Exception {
            Signature signature = Signature.getInstance(KEY_RSA_SIGNATURE);
            signature.initSign(toPrivateKey(privateKey));
            signature.update(data);
            return signature.sign();
        }
        // 公钥解密数据
        public static boolean verify(byte[] data, byte[] publicKey, byte[] sign)
                throws Exception {
            Signature signature = Signature.getInstance(KEY_RSA_SIGNATURE);
            signature.initVerify(toPublicKey(publicKey));
            signature.update(data);
            return signature.verify(sign);
        }
        public static byte[] decryptByPrivateKey(byte[] data, byte[] key)
                throws Exception {
            Cipher cipher = Cipher.getInstance(KEY_RSA);
            cipher.init(Cipher.DECRYPT_MODE, toPrivateKey(key));
            return cipher.doFinal(data);
        }
        public static byte[] decryptByPublicKey(byte[] data, byte[] key)
                throws Exception {
            Cipher cipher = Cipher.getInstance(KEY_RSA);
            cipher.init(Cipher.DECRYPT_MODE, toPublicKey(key));
            return cipher.doFinal(data);
        }
        public static byte[] encryptByPublicKey(byte[] data, byte[] key)
                throws Exception {
            Cipher cipher = Cipher.getInstance(KEY_RSA);
            cipher.init(Cipher.ENCRYPT_MODE, toPublicKey(key));
            return cipher.doFinal(data);
        }
        public static byte[] encryptByPrivateKey(byte[] data, byte[] key)
                throws Exception {
            Cipher cipher = Cipher.getInstance(KEY_RSA);
            cipher.init(Cipher.ENCRYPT_MODE, toPrivateKey(key));
            return cipher.doFinal(data);
    
        }
        static String tos(byte[] b) {
            String ans = "";
            for (int i = 0; i < b.length; i++) {
                ans += String.format("%02X", b[i]);
            }
            return ans;
        }
        public static void main(String[] args) throws Exception {
            KeyPairGenerator generator = KeyPairGenerator.getInstance(KEY_RSA);
            // generator.initialize(1024);//默认为1024
            KeyPair keyPair = generator.generateKeyPair();
            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
            RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
            System.out.println("公钥:" + tos(publicKey.getEncoded()));
            System.out.println("私钥:" + tos(privateKey.getEncoded()));
            byte[] data = "你好,世界!".getBytes();
            System.out.println("公钥加密-------私钥解密");
            byte[] enc = encryptByPublicKey(data, publicKey.getEncoded());
            byte[] dec = decryptByPrivateKey(enc, privateKey.getEncoded());
            System.out.println("加密前:" + tos(data));
            System.out.println("解密后:" + tos(dec));
            System.out.println("私钥加密--------公钥解密");
            enc = encryptByPrivateKey(data, privateKey.getEncoded());
            dec = decryptByPublicKey(enc, publicKey.getEncoded());
            System.out.println("加密前:" + tos(data));
            System.out.println("解密后:" + tos(dec));
            System.out.println("私钥签名--------公钥验证签名");
            byte[] sign = sign(data, privateKey.getEncoded());
            boolean status = verify(data, publicKey.getEncoded(), sign);
            System.out.println("签名:" + tos(sign));
            System.out.println("状态:" + status);
        }
    }
  • 相关阅读:
    laravel如何自定义一个路由文件
    RGAC-laravel权限管理
    导航栏下划线跟随
    php简单的判断用户登陆
    php判断文件上传的类型
    git 如何删除仓库中的文件
    laravle中config( )函数的使用
    [leetcode] Count and Say
    [leetcode] Sudoku Solver
    [leetcode] Search Insert Position
  • 原文地址:https://www.cnblogs.com/weiyinfu/p/5923475.html
Copyright © 2020-2023  润新知