精华内容
下载资源
问答
  • 非对称加密算法

    2020-03-16 09:50:02
    非对称加密 通常我们说的签名就是数字签名,它基于...简单说一下常用的非对称加密算法 RSA 的数学原理,理解简单的数学原理,就可以理解非对称加密怎么做到的,为什么安全的: 1. 选两个质数 p 和...

    非对称加密

    通常我们说的签名就是数字签名,它是基于非对称加密算法实现的。对称加密是通过同一份密钥加密和解密数据,而非对称加密则有两份密钥,分别是公钥和私钥,用公钥加密的数据,要用私钥才能解密,用私钥加密的数据,要用公钥才能解密。

    简单说一下常用的非对称加密算法 RSA 的数学原理,理解简单的数学原理,就可以理解非对称加密是怎么做到的,为什么会是安全的:
    1. 选两个质数 p 和 q,相乘得出一个大整数n,例如 p=61,q=53,n=pq=3233
    2. 选 1-n 间的随便一个质数 e,例如 e = 17
    3. 经过一系列数学公式,算出一个数字 d,满足:
    a. 通过 n 和 e 这两个数据一组数据进行数学运算后,可以通过 n 和 d 去反解运算,反过来也可以。
    b. 如果只知道 n 和 e,要推导出 d,需要知道 p 和 q,也就是要需要把 n 因数分解。

    上述的 (n,e) 这两个数据在一起就是公钥,(n,d) 这两个数据就是私钥,满足用公钥加密,私钥解密,或反过来公钥加密,私钥解密,也满足在只暴露公钥(只知道 n 和 e)的情况下,要推导出私钥 (n,d),需要把大整数 n 因数分解。目前因数分解只能靠暴力穷举,而n数字越大,越难以用穷举计算出因数 p 和 q,也就越安全,当 n 大到二进制 1024 位或 2048 位时,以目前技术要破解几乎不可能,所以非常安全。

    展开全文
  • *本文只讨论一个问题,在非对称加密算法RSA中,什么是公钥什么是私钥 非对称加密算法 非对称加密算法有很多,例如RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)。 在在这些算法中,RSA最为常用,...

    *本文只讨论一个问题,在非对称加密算法RSA中,什么是公钥什么是私钥

    非对称加密算法

    非对称加密算法有很多,例如RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)。

    在在这些算法中,RSA最为常用,因此,在没有特殊说明的情况下,常说的公钥、私钥都指的的RAS的公钥、私钥。

    这里也是以RSA算法为例,来讨论非对称加密中的公钥和私钥

    RSA加密算法

    要想了解公钥和私钥的区别,就要从它们的产生开始。
    这里我默认读者已经了解了RSA算法。如果还不了解,请先去看这两篇文章。
    RSA算法原理(一)
    RSA算法原理(二)
    特别是 RSA算法原理(二)一定要仔细看一遍,不然下面的内容你将看不懂。

    RSA加密算法中的公钥和私钥

    看过上面两篇文章的人应该已经知道了,在RSA加密算法中有6个非常关键数字,他们是算法的核心。
    这6个数字分别是

    • 大质数p
    • 另一个大质数q
    • p和q的乘积n
    • n的欧拉函数φ(n)  注:φ(n) = (p-1)(q-1)
    • 一个随机整数e,1< e < φ(n),且e与φ(n) 互质
    • e对于φ(n)的模反元素d  注:所谓"模反元素"就是指有一个整数d,可以使得ed被φ(n)除的余数为1。

    其中(n,e)在一起组成了公钥,(n,d)在一起组成了私钥。

    现在让我们来回答最开始提出是问题,什么是公钥,什么是私钥。
    答:公钥为(n,e) 私钥为(n,d)

    文章到此结束,谢谢大家的阅读!

    番外1

    其实我们仔细想想就会发现,(n,e) 和 (n,d) 根本没什么区别。为什么一个叫公钥一个叫私钥呢?反过来行不行?

    答案是可以的,根据算法原理我们知道,只有 (n,e) 是算不出 (n,d) 的,反过来只有 (n,d) 也是算不出 (n,e) 的。所以反过来也是安全的。

    那我们就不经思考了,既然反过来也可以,那公钥私钥还有什么区别,为什么一个叫公钥,一个叫私钥呢。

    我想了很久,最终想到了一个合理的解释,被公开的秘钥就叫公钥,没有被公开的秘钥就叫私钥。网上多数的回答也证实了我的想法。

    原来 公钥和私钥并不是根据 (n,e) 和 (n,d) 区分的,而是根据使用上的不同来区分的

    番外2

    让我们再思考一个问题。
    在工作中,我们经常会用到各种生成秘钥的工具。这些工具一般会为我们生成两个文件。一个公钥文件,假设叫public.key。一个私钥文件,假设叫private.key。

    根据上文的结论,我们是否能将private.key当做公钥公开,将public.key当做私钥,保留呢?

    答案是 不可以!!!大家千万别去这么做!

    为什么,按照上文的结论 “被公开的秘钥就叫公钥,未被公开的秘钥就叫私钥”,不应该是可以吗?为什么不可以?

    除非,上面的结论是错的!!!

    是的,上面的结论是错的,公钥和私钥并不是根据使用上的不同来区分的,也不是根据(n,e) 和 (n,d) 来区分的。

    那公钥和私钥是通过什么来区分的,到底有没有区别。
    别着急,让我们先来看一个有趣的现象

    根据私钥推导出公钥

    在一些秘钥生成工具中,有一个功能叫做 根据私钥推导出公钥 ,这个功能可以根据私钥文件,推导出公钥文件来。 比如蚂蚁金服的秘钥生成工具

    学习了RSA算法原理的人肯定想说,这不可能,不管私钥是(n,d)还是(n,e) ,只有 (n,e) 是算不出 (n,d) 的,只有 (n,d) 也是算不出 (n,e) 的。

    难道是阿里的人太nb了,可以算出来吗?

    当然不是!要真是这样,这种加密算法就不安全了。

    那这个功能是怎么实现的了!
    答案是私钥中包含了公钥信息!!!

    私钥中包含公钥信息

    让我们做个实验,随便用什么秘钥生成工具,生成一对秘钥,然后以文本的方式打开,你会发现,私钥的内容总是比公钥的多! 再仔细观察你会发现 公钥中的部分内容在私钥中也存在!

    这里最好用文本对比工具,这样看的比较清楚,我知道你们懒得去动手,所以我帮你们做好了!

    左边是公钥的内容,右边是私钥的内容,可以看到中间有一行内容是一样的!

    为什么会这样, 公钥难道不是(n,e) 私钥难道不是(n,d) 吗!


    按照RSA算法的定义,公钥确实是(n,e) 私钥也确实的(n,d)。

    但是,实际应用中,人们发现,这样做的话,公钥和私钥的重要性和地位就一样了,但其实我们最关心的是私钥,私钥才是最重要的。

    于是
    在pkcs标准中,pkcs#1规定,私钥包含(n,e,d,p,q),公钥包含(n,e)
    在pkcs标准中,pkcs#1规定,私钥包含(n,e,d,p,q),公钥包含(n,e)
    在pkcs标准中,pkcs#1规定,私钥包含(n,e,d,p,q),公钥包含(n,e)

    重要的话说三遍

    (pkcs全称Public-Key Cryptography Standards (公开秘钥加密标准),旗下包含十几个子标准,每个子标准负责一个领域。)

    这样做有两个好处

    1. 公钥和私钥的重要性和地位不再一样,私钥的重要性和地位远高于公钥,这有利于私钥的持有者。
    2. 拥有了私钥,就相当于拥有了公钥,使用起来特别方便,就算公钥弄丢了,还可以通过私钥生成出来。

    (从上文我们了解到,理论和实现还是有区别的,理论跟偏向原理,而实现更偏向使用,所以实际中的私钥会比理论中的私钥多几个参数。)


    现在我们可以回答最开始提出的问题了,在非对称加密算法RSA中,什么是公钥什么是私钥。

    1. 公钥首先是一种秘钥,它包含(n,e),可以被公开,不能推导出私钥
    2. 私钥首先也是一种秘钥,他有两种语法格式,pkcs#8标准语法格式的和pkcs#1标准语法格式,其中pkcs#1规定,私钥包含(n,e,d,p,q),不可以被公开,可以推导出公钥。

    在实际应用中,绝大多数对RSA的实现,都遵循pkcs的标准,即私钥能推出公钥,但公钥不能推出私钥

    总结

    通过上面的文章我们至少要知道以下几点

    • 公钥和私钥不一样
    • 私钥可以推导出公钥,但公钥无法推导出私钥(私钥包含公钥)
    • 理论和实现 是有出入的,所以只学习理论是无法为我们解惑的,必须联系实际进行思考才能解答我们的疑问。

    番外3

    秘钥格式

    生成的秘钥一般会通过PEM编码成文本来存储。具体如下:

    • PKCS1语法格式私钥:传统格式,PHP、.NET一般使用此格式
    • PKCS8语法格式私钥:java一般使用此格式
    • PKCS1格式和PKCS8格式的私钥,导出的公钥内容是一摸一样的

    公钥是不分 pkcs1 格式和 pkcs8格式的,因为公钥就只有一种语法格式。

    RSA密钥语法

    RSA公钥在PKCS#1标准中定义的语法

    RSAPublicKey ::= SEQUENCE {
        modulus           INTEGER,  -- n
        publicExponent    INTEGER   -- e
    }
    (n,e)
    复制代码

    RSA私钥在PKCS#1标准中定义的语法

    RSAPrivateKey ::= SEQUENCE { 
    version	Version,	//版本 
    modulus	INTEGER,	// RSA合数模 n 
    publicExponent	INTEGER,	//RSA公开幂 e 
    privateExponent	INTEGER,	//RSA私有幂 d 
    prime1	INTEGER,	//n的素数因子p 
    prime2	INTEGER,	//n的素数因子q 
    exponent1	INTEGER,	//值 d mod (p-1) 
    exponent2	INTEGER,	//值 d mod (q-1) 
    coefficient	INTEGER,	//CRT系数 (inverse of q) mod p 
    otherPrimeInfos	OtherPrimeInfos OPTIONAL 
    }
    (n,e,d,p,q)
    复制代码

    RSA私钥在PKCS#8标准中定义的语法

    pkcs#8 全称 Private-Key Information Syntax Standard 私钥信息语法标准,是专门为私钥而设计的规范,所以是不存在PKCS#8格式的公钥这一说

    PrivateKeyInfo ::= SEQUENCE {  
    version	Version,	//版本 
    privateKeyAlgorithm	PrivateKeyAlgorithmIdentifier, 	//算法标示符 
    privateKey	PrivateKey,  //私钥
    attributes		[0]  IMPLICIT Attributes OPTIONAL 
    } 
    复制代码

    转载于:https://juejin.im/post/5b135ac36fb9a01e2d702eaf

    展开全文
  • 网络安全之常用加密算法是什么

    千次阅读 2018-10-15 13:40:46
    文章目录加密分类对称加密非对称加密总结 加密分类 对称加密 非对称加密 对称加密   对称加密最快速、最简单一种加密方式,加密(encryption)与解密(decryption)用的是同样密钥(secret key)。   ...



    加密分类

    • 对称加密
    • 非对称加密


    对称加密

      对称加密是最快速、最简单的一种加密方式,加密(encryption)与解密(decryption)用的是同样的密钥(secret key)。
      对称加密有很多种算法,由于它效率很高,所以被广泛使用在很多加密协议的核心当中。对称加密通常使用的是相对较小的密钥,一般小于256 bit。因为密钥越大,加密越强,但加密与解密的过程越慢。
      对称加密的一大缺点是密钥的管理与分配,换句话说,如何把密钥发送到需要解密你的消息的人的手里是一个问题。在发送密钥的过程中,密钥有很大的风险会被黑客们拦截。


    非对称加密

    非对称加密允许在不安全的媒体上的通讯双方交换信息。
      它使用了一对密钥,公钥(public key)和私钥(private key)。私钥只能由一方安全保管,不能外泄,而公钥则可以发给任何请求它的人。非对称加密使用这对密钥中的一个进行加密,而解密则需要另一个密钥。
      比如,你向银行请求公钥,银行将公钥发给你,你使用公钥对消息加密,那么只有私钥的持有人–银行才能对你的消息解密。与对称加密不同的是,银行不需要将私钥通过网络发送出去,因此安全性大大提高。


    总结

    1. 对称加密加密与解密使用的是同样的密钥,所以速度快,但由于需要将密钥在网络传输,所以安全性不高。
    2. 非对称加密使用了一对密钥,公钥与私钥,所以安全性高,但加密与解密速度慢。
    3. 解决的办法是将对称加密的密钥使用非对称加密的公钥进行加密,然后发送出去,接收方使用私钥进行解密得到对称加密的密钥,然后双方可以使用对称加密来进行沟通。

    展开全文
  • 工作中时不时接触到一些加密算法,有md5、des、aes、对称加密、非对称加密、可逆算法、不可逆算法,那么这些算法这些概念都有什么区别呢,今天闲来无事打算梳理一下。 一、什么是加密解密,加密目的是什么? ...

    工作中经常会接触到一些加密算法,比如说base64、MD5、DES、AES等等,那么这些算法到底有什么区别以及具体的应用场景是什么呢,下面就做个简要的梳理。

    一、什么是加/解密,目的是什么?

    所谓加密,就是对原来为明文的文件或数据按某种算法进行处理,使其成为不可读的一段代码,通常称为 “密文”。目的就是保护数据不被非法窃取、阅读。
    所谓解密,也就是加密的逆过程,即将该密文信息转化为其原来数据的过程。
    举个例子:小王想给他的妻子写一封信,如果在邮寄的过程中,被他人截获那么就显而易见的将信息泄露掉。相反如果小王根据一个密码本将信的内容加密,比如每一个汉字对应一个编码,那么即使被别人截获,因为没有密码本那么信息也不会泄露,小王的妻子拿到加密后的信件后,用密码本再一一翻译成可读的文本,这个过程就是解密。

    二、什么是加/解密算法

    加密/解密过程中,使用到的算法就是加密/解密算法。

    三、加/解密算法的分类

    根据加/解密过程是否可逆,算法可以分为可逆加密算法和不可逆加密算法
    可逆算法包括:DES、3DES、AES、RSA、DSA
    不可逆加密算法包括:SHA-1、MD5
    对于可逆加密,如果没有秘钥,任何人拿到了密文后通过对应的可逆算法都可以解密,这是不安全的。所以引入了秘钥,加密的时候加入了秘钥,接收方解密时需提供秘钥,这样不知道秘钥就无法解密。
    根据加解密使用的秘钥是否相同,算法可以分为对称加密算法和非对称加密算法
    对称加解密使用的秘钥是一致的,非对称加解密使用的秘钥是不一致的。

    四、不可逆算法

    4.1 MD5加密算法

    MD5 用的是哈希函数。严格来说,MD5不是一种加密算法而是摘要算法。无论是多长的输入,MD5 都会输出长度为 128bits 的一个串 (通常用 16 进制 表示为 32 个字符)。完整的md5一般是32位,国内常见的一种是动网的16位(也就是只取32位md5的中间16位),另外有一种是变化过的md5,特征是全是数字,长度可能是20位或者19。

    它的典型应用是对一段信息产生信息摘要,以 防止被篡改。
    防止被篡改的意思是,发送方用此算法对一段信息产生一个摘要串,接收方也用此算法产生一个摘要串,然后比较这两个摘要串的内容是否一致,如果不一致我们就认为此信息在传输的过程中可能发生了篡改。
    那么有没有可能我修改了信息内容,修改后的内容产生的md5与修改之前是一致的呢?md5防止篡改的关键在于,它的碰撞算法以前一直没有找到,所谓碰撞算法,就是修改原来的文件,同时保持修改后的文件和原文件md5一致。
    不过后来,我国山东大学的杨教授搞定了碰撞算法。所以md5作为防篡改,已经不可靠了。类似的,sha1的碰撞算法,最近也被攻克。

     public static String getMd5(String source) throws NoSuchAlgorithmException {
            //1.获取MessageDigest对象
            MessageDigest digest = MessageDigest.getInstance("md5");
    
            //2.执行加密操作
            byte[] bytes = source.getBytes();
    
            //在MD5算法这,得到的目标字节数组的特点:长度固定为16
            byte[] targetBytes = digest.digest(bytes);
    
            //3.声明字符数组
            char [] characters = new char[]{'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
    
            //4.遍历targetBytes
            StringBuilder builder = new StringBuilder();
            for (byte b : targetBytes) {
                //5.取出b的高四位的值
                //先把高四位通过右移操作拽到低四位
                int high = (b >> 4) & 15;
    
                //6.取出b的低四位的值
                int low = b & 15;
    
                //7.以high为下标从characters中取出对应的十六进制字符
                char highChar = characters[high];
    
                //8.以low为下标从characters中取出对应的十六进制字符
                char lowChar = characters[low];
    
                builder.append(highChar).append(lowChar);
            }
            
            return builder.toString();
        }
    

    4.2 SHA-1加密算法

    SHA1 是和 MD5 一样流行的 消息摘要算法,然而 SHA1 比 MD5 的 安全性更强。对于长度小于 2 ^ 64 位的消息,SHA1 会产生一个 160 位(40个字符)的 消息摘要。基于 MD5、SHA1 的信息摘要特性以及 不可逆 (一般而言),可以被应用在检查 文件完整性 以及 数字签名 等场景。

    public static String shaEncode(String inStr) throws Exception {
            MessageDigest sha = null;
            try {
                sha = MessageDigest.getInstance("SHA");
            } catch (Exception e) {
                System.out.println(e.toString());
                e.printStackTrace();
                return "";
            }
     
            byte[] byteArray = inStr.getBytes("UTF-8");
            byte[] md5Bytes = sha.digest(byteArray);
            StringBuffer hexValue = new StringBuffer();
            for (int i = 0; i < md5Bytes.length; i++) {
                int val = ((int) md5Bytes[i]) & 0xff;
                if (val < 16) {
                    hexValue.append("0");
                }
                hexValue.append(Integer.toHexString(val));
            }
            return hexValue.toString();
        }
    
    

    五、对称加密算法

    5.1 DES算法

    DES(Data Encryption Standard)是一种分组密码算法,明文按 64 位进行分组,密钥长 64 位,密钥事实上是 56 位参与 DES 运算(第8、16、24、32、40、48、56、64 位是校验位)分组后的明文组和 56 位的密钥按位替代或交换的方法形成密文组,之后按照顺序将密文组连在一起,各段数据之间互不影响。标准的DES密钥长度为64bit,即8个字符,超过8个字符则舍弃后面。比如:用abcdefgh与abcdefghi加密是一样的结果。又因为有校验位的存在,所以用12345678与13345678进行加密是一样的。
    如果密钥长度不足,会以指定的填充方式( 比如PKCS7Padding )方式补足位
    关于数据补位参考:https://www.cnblogs.com/Lawson/archive/2012/05/20/2510781.html
    因此,破译 DES 加密算法实际上就是 搜索密钥的编码。对于56 位长度的密钥 来说,如果用穷举法来进行搜索的话,其运算次数为 2 ^ 56 次=非常大的一个数。
    des原理描述
    https://blog.csdn.net/qq_32445015/article/details/80184954

    package com.inspur.incloudmanager.controller.util;
    
    import javax.crypto.Cipher;
    import javax.crypto.CipherInputStream;
    import javax.crypto.SecretKeyFactory;
    import javax.crypto.spec.DESKeySpec;
    import javax.crypto.spec.IvParameterSpec;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.security.Key;
    import java.util.Base64;
    
    
    public class DESUtil {
    
        /**
         * 偏移变量,固定占8位字节
         */
        private final static String IV_PARAMETER = "12345678";
        /**
         * 密钥算法
         */
        private static final String ALGORITHM = "DES";
        /**
         * 加密/解密算法-工作模式-填充模式
         */
    //    private static final String CIPHER_ALGORITHM = "DES/CBC/PKCS5Padding";
    
        private static final String CIPHER_ALGORITHM = "DES/ECB/PKCS5Padding";
        /**
         * 默认编码
         */
        private static final String CHARSET = "utf-8";
    
        /**
         * 生成key
         *
         * @param password
         * @return
         * @throws Exception
         */
        private static Key generateKey(String password) throws Exception {
            DESKeySpec dks = new DESKeySpec(password.getBytes(CHARSET));
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
            return keyFactory.generateSecret(dks);
        }
    
    
        /**
         * DES加密字符串
         *
         * @param password 加密密码,长度不能够小于8位
         * @param data 待加密字符串
         * @return 加密后内容
         */
        public static String encrypt(String password, String data) {
            if (password== null || password.length() < 8) {
                throw new RuntimeException("加密失败,key不能小于8位");
            }
            if (data == null)
                return null;
            try {
                Key secretKey = generateKey(password);
                Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
                IvParameterSpec iv = new IvParameterSpec(IV_PARAMETER.getBytes(CHARSET));
                //非ECB模式使用下面的偏移量
    //            cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
                //ECB模式
                cipher.init(Cipher.ENCRYPT_MODE, secretKey);
                byte[] bytes = cipher.doFinal(data.getBytes(CHARSET));
    
                //JDK1.8及以上可直接使用Base64,JDK1.7及以下可以使用BASE64Encoder
                //Android平台可以使用android.util.Base64
                return new String(Base64.getEncoder().encode(bytes));
    
            } catch (Exception e) {
                e.printStackTrace();
                return data;
            }
        }
    
        /**
         * DES解密字符串
         *
         * @param password 解密密码,长度不能够小于8位
         * @param data 待解密字符串
         * @return 解密后内容
         */
        public static String decrypt(String password, String data) {
            if (password== null || password.length() < 8) {
                throw new RuntimeException("加密失败,key不能小于8位");
            }
            if (data == null)
                return null;
            try {
                Key secretKey = generateKey(password);
                Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
                IvParameterSpec iv = new IvParameterSpec(IV_PARAMETER.getBytes(CHARSET));
                //非ECB模式使用下面的偏移量
    //            cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
                cipher.init(Cipher.DECRYPT_MODE, secretKey);
                return new String(cipher.doFinal(Base64.getDecoder().decode(data.getBytes(CHARSET))), CHARSET);
            } catch (Exception e) {
                e.printStackTrace();
                return data;
            }
        }
    }
    

    5.2 3DES算法

    3DES(又叫Triple DES)是三重数据加密算法(TDEA,Triple Data Encryption Algorithm)块密码的通称。它相当于是对每个数据块应用三次DES加密算法。密钥长度是128位,192位(bit),如果密码位数少于等于64位,加密结果与DES相同。原版DES容易被破解,新的3DES出现,增加了加密安全性,避免被暴力破解。它同样是对称性加密,同样涉及到加密编码方式,及填充方式。包括3DES-ECB,3DES-CBC,3DES-CTR,3DES-OFB,3DES-CFB

    public static String threedesencrypt(String key,String text) {
            try {
                byte[] src = text.getBytes();
                DESedeKeySpec spec = new DESedeKeySpec(convert(key.getBytes()));
                SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede");
                SecretKey secretKey = factory.generateSecret(spec);
                Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
                cipher.init(Cipher.ENCRYPT_MODE, secretKey);
                byte[] res = cipher.doFinal(src);
                //encodeBase64会对字符串3位一组自动补全,因而最后可能会出现 == 或者 =
                return new String(Base64.getEncoder().encode(res), "utf-8");
    
            } catch (Exception e) {
                System.out.println("error");
            }
            return null;
        }
    
        /**
         * 不足24位进行补位
         * @param sources
         * @return
         */
        private static byte[] convert(byte[] sources){
            byte[] ret = new byte[24];
            if(sources.length < 24){
                for(int i = 0; i < 24;i++){
                    if(i < sources.length){
                        ret[i] = sources[i];
                    }else{
                        ret[i] = 0;
                    }
                }
            }else{
                ret = sources;
            }
            return ret;
        }
    

    5.3 AES算法

    高级加密标准(英语:Advanced Encryption Standard,缩写:AES),是一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。
    那么为什么原来的DES会被取代呢,原因就在于其使用56位密钥,比较容易被破解。而AES可以使用128、192、和256位密钥,并且用128位分组加密和解密数据,相对来说安全很多。完善的加密算法在理论上是无法破解的,除非使用穷尽法。使用穷尽法破解密钥长度在128位以上的加密数据是不现实的,仅存在理论上的可能性。统计显示,即使使用目前世界上运算速度最快的计算机,穷尽128位密钥也要花上几十亿年的时间,更不用说去破解采用256位密钥长度的AES算法了。

    package com.inspur.incloudmanager.controller.util;
    
    import org.springframework.util.Base64Utils;
    
    import javax.crypto.Cipher;
    import javax.crypto.KeyGenerator;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
    import java.security.NoSuchAlgorithmException;
    import java.security.SecureRandom;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    
    
    
    public class AESUtil{
    
        private static final String KEY_ALGORITHM = "AES";
        private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";//默认的加密算法
    
        /**
         * AES 加密操作
         *
         * @param content 待加密内容
         * @param key 加密密钥
         * @return 返回Base64转码后的加密数据
         */
        public static String encrypt(String content, String key) {
            try {
                Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);// 创建密码器
    
                byte[] byteContent = content.getBytes("utf-8");
    
                cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(key));// 初始化为加密模式的密码器
    
                byte[] result = cipher.doFinal(byteContent);// 加密
    
                return Base64Utils.encodeToString(result);//通过Base64转码返回
    
            } catch (Exception ex) {
                Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);
            }
    
            return null;
        }
    
        /**
         * AES 解密操作
         *
         * @param content
         * @param key
         * @return
         */
        public static String decrypt(String content, String key) {
    
            try {
                //实例化
                Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
    
                //使用密钥初始化,设置为解密模式
                cipher.init(Cipher.DECRYPT_MODE, getSecretKey(key));
    
                //执行操作
                byte[] result = cipher.doFinal(Base64Utils.decodeFromString(content));
    
    
                return new String(result, "utf-8");
            } catch (Exception ex) {
                Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);
            }
    
            return null;
        }
    
        /**
         * 生成加密秘钥
         *
         * @return
         */
        private static SecretKeySpec getSecretKey(final String key) {
            //返回生成指定算法密钥生成器的 KeyGenerator 对象
            KeyGenerator kg = null;
    
            try {
                kg = KeyGenerator.getInstance(KEY_ALGORITHM);
    
                //AES 要求密钥长度为 128
                kg.init(128, new SecureRandom(key.getBytes()));
    
                //生成一个密钥
                SecretKey secretKey = kg.generateKey();
    
                return new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);// 转换为AES专用密钥
            } catch (NoSuchAlgorithmException ex) {
                Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);
            }
    
            return null;
        }
    
        public static void main(String[] args) {
            String content = "Inspur1!";
            String key = "wang";
            System.out.println("content:" + content);
            String s1 = AESUtil.encrypt(content, key);
            System.out.println("s1:" + s1);
            System.out.println("s2:"+AESUtil.decrypt(s1, key));
    
        }
    
    }
    
    

    指定秘钥

    public class AESUtil{
    
        private static final String KEY_ALGORITHM = "AES";
        private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";//默认的加密算法
    
        /**
         * AES 加密操作
         *
         * @param content 待加密内容
         * @param key 加密密钥
         * @return 返回Base64转码后的加密数据
         */
        public static String encrypt(String content, String key) {
            try {
                Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);// 创建密码器
    
                byte[] byteContent = content.getBytes("utf-8");
    
                SecretKeySpec aeskey = new SecretKeySpec(convert(key.getBytes("utf-8")), "AES");
    
                cipher.init(Cipher.ENCRYPT_MODE, aeskey);// 初始化为加密模式的密码器
    
                byte[] result = cipher.doFinal(byteContent);// 加密
    
                return Base64Utils.encodeToString(result);//通过Base64转码返回
    
            } catch (Exception ex) {
                Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);
            }
    
            return null;
        }
    
        /**
         * AES 解密操作
         *
         * @param content
         * @param key
         * @return
         */
        public static String decrypt(String content, String key) {
    
            try {
                //实例化
                Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
    
                SecretKeySpec aeskey = new SecretKeySpec(convert(key.getBytes("UTF-8")), "AES");
    
                //使用密钥初始化,设置为解密模式
                cipher.init(Cipher.DECRYPT_MODE, aeskey);
    
                //执行操作
                byte[] result = cipher.doFinal(Base64Utils.decodeFromString(content));
    
    
                return new String(result, "utf-8");
            } catch (Exception ex) {
                Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);
            }
    
            return null;
        }
    
        /**
         * 截取算法,超过128位(32字节),手动截取掉
         * @param sources
         * @return
         */
        private static byte[] convert(byte[] sources){
            byte[] ret = new byte[32];
            if(sources.length > 32){
                for(int i = 0; i < 32;i++){
                        ret[i] = sources[i];
                }
            }else{
                ret = sources;
            }
            return ret;
        }
    
        public static void main(String[] args) {
            String content = "Inspur1!";
            String key = "inclouqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq";
            System.out.println("content:" + content);
            String s1 = AESUtil.encrypt(content, key);
            System.out.println("s1:" + s1);
            System.out.println("s2:"+AESUtil.decrypt(s1, key));
    
        }
    }
    

    六、非对称加密算法

    6.1 RSA算法

    import javax.crypto.Cipher;
    import java.security.*;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    import java.util.Base64;
     
     
    /**
     * RSA非对称加密算法工具类
     *
     * @author lixk
     */
     
    public class RSA {
        //非对称密钥算法
        private static final String KEY_ALGORITHM = "RSA";
        //密钥长度,在512到65536位之间,建议不要太长,否则速度很慢,生成的加密数据很长
        private static final int KEY_SIZE = 512;
        //字符编码
        private static final String CHARSET = "UTF-8";
     
        /**
         * 生成密钥对
         *
         * @return KeyPair 密钥对
         */
        public static KeyPair getKeyPair() throws Exception {
            return getKeyPair(null);
        }
     
        /**
         * 生成密钥对
         * @param password 生成密钥对的密码
         * @return
         * @throws Exception
         */
        public static KeyPair getKeyPair(String password) throws Exception {
            //实例化密钥生成器
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
            //初始化密钥生成器
            if(password == null){
                keyPairGenerator.initialize(KEY_SIZE);
            }else {
                SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
                secureRandom.setSeed(password.getBytes(CHARSET));
                keyPairGenerator.initialize(KEY_SIZE, secureRandom);
            }
            //生成密钥对
            return keyPairGenerator.generateKeyPair();
        }
     
        /**
         * 取得私钥
         *
         * @param keyPair 密钥对
         * @return byte[] 私钥
         */
        public static byte[] getPrivateKeyBytes(KeyPair keyPair) {
            return keyPair.getPrivate().getEncoded();
        }
     
        /**
         * 取得Base64编码的私钥
         *
         * @param keyPair 密钥对
         * @return String Base64编码的私钥
         */
        public static String getPrivateKey(KeyPair keyPair) {
            return Base64.getEncoder().encodeToString(getPrivateKeyBytes(keyPair));
        }
     
        /**
         * 取得公钥
         *
         * @param keyPair 密钥对
         * @return byte[] 公钥
         */
        public static byte[] getPublicKeyBytes(KeyPair keyPair) {
            return keyPair.getPublic().getEncoded();
        }
     
        /**
         * 取得Base64编码的公钥
         *
         * @param keyPair 密钥对
         * @return String Base64编码的公钥
         */
        public static String getPublicKey(KeyPair keyPair) {
            return Base64.getEncoder().encodeToString(getPublicKeyBytes(keyPair));
        }
     
        /**
         * 私钥加密
         *
         * @param data       待加密数据
         * @param privateKey 私钥字节数组
         * @return byte[] 加密数据
         */
        public static byte[] encryptByPrivateKey(byte[] data, byte[] privateKey) throws Exception {
            //实例化密钥工厂
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            //生成私钥
            PrivateKey key = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKey));
            //数据加密
            Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, key);
            return cipher.doFinal(data);
        }
     
        /**
         * 私钥加密
         *
         * @param data       待加密数据
         * @param privateKey Base64编码的私钥
         * @return String Base64编码的加密数据
         */
        public static String encryptByPrivateKey(String data, String privateKey) throws Exception {
            byte[] key = Base64.getDecoder().decode(privateKey);
            return Base64.getEncoder().encodeToString(encryptByPrivateKey(data.getBytes(CHARSET), key));
        }
     
        /**
         * 公钥加密
         *
         * @param data      待加密数据
         * @param publicKey 公钥字节数组
         * @return byte[] 加密数据
         */
        public static byte[] encryptByPublicKey(byte[] data, byte[] publicKey) throws Exception {
            //实例化密钥工厂
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            //生成公钥
            PublicKey key = keyFactory.generatePublic(new X509EncodedKeySpec(publicKey));
            //数据加密
            Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, key);
            return cipher.doFinal(data);
        }
     
        /**
         * 公钥加密
         *
         * @param data      待加密数据
         * @param publicKey Base64编码的公钥
         * @return String Base64编码的加密数据
         */
        public static String encryptByPublicKey(String data, String publicKey) throws Exception {
            byte[] key = Base64.getDecoder().decode(publicKey);
            return Base64.getEncoder().encodeToString(encryptByPublicKey(data.getBytes(CHARSET), key));
        }
     
        /**
         * 私钥解密
         *
         * @param data       待解密数据
         * @param privateKey 私钥字节数组
         * @return byte[] 解密数据
         */
        public static byte[] decryptByPrivateKey(byte[] data, byte[] privateKey) throws Exception {
            //实例化密钥工厂
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            //生成私钥
            PrivateKey key = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKey));
            //数据解密
            Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, key);
            return cipher.doFinal(data);
        }
     
        /**
         * 私钥解密
         *
         * @param data       Base64编码的待解密数据
         * @param privateKey Base64编码的私钥
         * @return String 解密数据
         */
        public static String decryptByPrivateKey(String data, String privateKey) throws Exception {
            byte[] key = Base64.getDecoder().decode(privateKey);
            return new String(decryptByPrivateKey(Base64.getDecoder().decode(data), key), CHARSET);
        }
     
        /**
         * 公钥解密
         *
         * @param data      待解密数据
         * @param publicKey 公钥字节数组
         * @return byte[] 解密数据
         */
        public static byte[] decryptByPublicKey(byte[] data, byte[] publicKey) throws Exception {
            //实例化密钥工厂
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            //产生公钥
            PublicKey key = keyFactory.generatePublic(new X509EncodedKeySpec(publicKey));
            //数据解密
            Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, key);
            return cipher.doFinal(data);
        }
     
        /**
         * 公钥解密
         *
         * @param data      Base64编码的待解密数据
         * @param publicKey Base64编码的公钥
         * @return String 解密数据
         */
        public static String decryptByPublicKey(String data, String publicKey) throws Exception {
            byte[] key = Base64.getDecoder().decode(publicKey);
            return new String(decryptByPublicKey(Base64.getDecoder().decode(data), key), CHARSET);
        }
     
        /**
         * 测试加解密方法
         *
         * @param args
         * @throws Exception
         */
        public static void main(String[] args) throws Exception {
            //生成密钥对,一般生成之后可以放到配置文件中
            KeyPair keyPair = RSA.getKeyPair();
            //公钥
            String publicKey = RSA.getPublicKey(keyPair);
            //私钥
            String privateKey = RSA.getPrivateKey(keyPair);
     
            System.out.println("公钥:\n" + publicKey);
            System.out.println("私钥:\n" + privateKey);
     
            String data = "RSA 加解密测试!";
            {
                System.out.println("\n===========私钥加密,公钥解密==============");
                String s1 = RSA.encryptByPrivateKey(data, privateKey);
                System.out.println("加密后的数据:" + s1);
                String s2 = RSA.decryptByPublicKey(s1, publicKey);
                System.out.println("解密后的数据:" + s2 + "\n\n");
            }
     
            {
                System.out.println("\n===========公钥加密,私钥解密==============");
                String s1 = RSA.encryptByPublicKey(data, publicKey);
                System.out.println("加密后的数据:" + s1);
                String s2 = RSA.decryptByPrivateKey(s1, privateKey);
                System.out.println("解密后的数据:" + s2 + "\n\n");
            }
     
        }
    }
    

    声明:本文章主要将几种常用的加密算法及其java实现统一整理,便于以后查看。大多数是转载参考网上的内容。如有侵权请告知。
    参考文章列表如下:

    https://blog.csdn.net/u013314786/article/details/80324461

    展开全文
  • 什么是加密算法

    2018-09-29 19:19:18
    转载自 什么是加密算法 Java的加密知识也Java常见的领域之一,加密技术的底层确实很复杂,运用了...常用的加密算法有对称加密算法,非对称加密算法,哈希算法,数字签名等几类。  对称加密顾名思义就是加密和...
  • 3,非对称加密算法,RSA加密算法 4,CCM算法 5,HMAC算法 文章目录学习目标:前言一、AES是什么?1.1 常用的AES加密方式:二、SHA256 是什么三、RSA是什么四、CCM是什么五、HMAC是什么总结 前言 比如发送端如何传输...
  • 在这个过程中难免会被别有用心的人监听(现在常用的网络数据监听软件就有charles,具体可以查看相关使用教程,通过这个软件可以监听到某个页面用到了哪些接口,发送以及返回的参数分别是什么)。所以在传输敏感数据...
  • RSA(非对称加密)加密/量子计算机解密 ... 对称加密与非对称加密什么是对称加密? 采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密...常用的单向加密算法: DES(Data Encryp...
  • 第一想到的就是对数据做加密处理, 常用的加密方式有对称加密 非对称加密。 所谓的对称加密进行数据传输的两端只有一把秘钥,提供加密解密。如果每个客户端都有这样一把秘钥, 那对数据加密没有什么意识的。传统的...
  • 由于常用的加密算法公开的,所以,对原文的加密的关键,就是密钥了。对于这种加解密都使用同样的密钥的算法,我们称之为对称加密对称加密的代表算法就是DES家族了。那么这种对称加密什么缺陷呢?由于加...
  • 由于常用的加密算法公开的,所以,对原文的加密的关键,就是密钥了。对于这种加解密都使用同样的密钥的算法,我们称之为对称加密对称加密的代表算法就是DES家族了。那么这种对称加密什么缺陷呢?由于加解密...
  • 网络通信常用加密算法研究

    千次阅读 2015-12-24 10:46:10
    什么是对称加密和非对称加密 什么是对称加密: 对称加密采用了对称密码编码技术,它特点文件加密和解密使用相同密钥,即加密密钥也可以用作解密密钥,这种方法在密码学中叫做对称加密算法对称加密算法使用...
  • RSA加密算法

    千次阅读 2018-07-21 11:34:48
    一、对称加密算法 在RSA算法出现之前,人们一直用的是对称加密算法,什么是对称加密算法: ...二、非对称加密算法 针对对称算法不足,后来有三位大牛想出了一套非对称算法,也就是现在我们常说R...
  • 由于常用的加密算法公开的,所以,对原文的加密的关键,就是密钥了。对于这种加解密都使用同样的密钥的算法,我们称之为对称加密对称加密的代表算法就是DES家族了。那么这种对称加密什么缺陷呢?由于加解密...
  • java中的加密算法

    2019-05-02 16:09:04
    一,java中的加密算法 ...非对称加密 接下来按照分类依次总结 1.可逆加密 什么是可逆加密? 可逆加密就是能将需要明文进行加密,也能对原来加密后密文进行解密,其中最经典也比较常用...
  • Java科普之加密算法

    千次阅读 2016-06-16 16:19:14
    ...   加密比较复杂,但今天公司有需求,就稍微再研究一下,方式...非对称加密指加密后不可解密,有什么用途呢?登录密码使用非对称加密,拿到加密后数据跟数据库存数据对比,相同则让登录成功(也就说数据库...
  • Java面试之加密算法

    千次阅读 2019-01-29 16:38:31
    1、Java中常用的加密算法 散列算法 MD5 SHA 对称加密 DES 3DES AES 非对称加密 RSA ECC 2、什么是base64 Base64网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来...
  • 最近开始做金融项目,接触了加密算法,在这里做个总结,加深认识。 目前比较常用的加密算法总结起来...而双向加密算法,与单向加密正好相反,就是可以把密文逆推还原成明文,双向加密又分为对称加密和非对称加密...
  • Go密码学之对称加密

    2019-06-07 23:29:56
    非对称加密 单向散列函数 哈希函数 消息认证码 数字签名 证书 ssl/tls - https 为什么要加密, 以及解决方案 保证数据安全 加密三要素 明文/密文 秘钥 定长字符串 需要根据加密算法确定其长度 算法 ...
  • 【面试总结】MD5及加密算法优劣

    千次阅读 2018-08-14 16:06:24
    最近在面试中问到项目为什么要使用MD5加密,对其他加密... 双向加密:又分为对称性加密算法非对称加密算法。对称性加密算法,发送和接收端双方都知道秘钥和加密算法且秘钥都相同,之后便对数据加密和...
  • 目录 概述 加密算法的分类 对称算法分类 各分类区别 对称加密之间区别 非对称加密之间区别 散列算法之间区别 对称与非对称比较 RSA RSA是什么 作用场...
  • 加密对称(一)

    2020-11-06 15:52:15
    非对称加密 单向散列函数 哈希函数 消息认证码 数字签名 证书 ssl/tls - https 为什么要加密, 以及解决方案 保证数据安全 加密三要素 明文/密文 秘钥 定长字符串 需要根据加密算法确定其长度 算法 ...

空空如也

空空如也

1 2 3 4 5 6
收藏数 104
精华内容 41
关键字:

常用的非对称加密算法是什么