关于设计中常用的加密方式整理


关于设计中常用的加密方式整理

关于设计中常用的加密方式整理


我们在日常软件设计的时候,加密问题是经常遇到的。比如,我们的用户信息的密码应该如何安全的保存;前端敏感信息如何加密后向后端传输等等。

摘要算法

消息摘要算法的主要特征是加密过程不需要密钥,并且经过加密的数据无法被解密,目前可以被解密逆向的只有CRC32算法,只有输入相同的明文数据经过相同的消息摘要算法才能得到相同的密文。

摘要算法通常被用来做数字签名、数据指纹等场景,因为摘要算法最大的特点任意长度的字符通过加密后得到相同长度的结果,而且都比较短,验证的效率比较高。

扩展–摘要算法在数字签名中的应用

传统的数字签名方案中,是利用公钥密码的方式,即可信数据源利用私钥对信息体加密,形成签体;通过用公钥解密的方式进行验证,如果解密后的信息与原来的信息一致,则验证通过(此方式与公钥用于消息保密正好想法)。

此种方式利用的就是只有可信数据源有私钥,因此只有它能加密,因此既保证信息提供者确实提供了该信息,同时也保证了信息的不可变性。

但是这种方式有几个问题:

  • 信息体本身是不保密的
  • 由于要对信息体加密,所以效率很低

因此这种方式不可取。

推荐使用的方式是,信息体首先用摘要算法生成摘要信息,然后再通过私钥加密;接收方的操作也一样,先摘要,再公钥解密,然后再比较是否一致。

MD5

MD5信息摘要算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。MD5由美国密码学家罗纳德·李维斯特(Ronald Linn Rivest)设计,于1992年公开,用以取代MD4算法。这套算法的程序在 RFC 1321 标准中被加以规范。1996年后该算法被证实存在弱点,可以被加以破解,对于需要高度安全性的数据,专家一般建议改用其他算法,如SHA-2。2004年,证实MD5算法无法防止碰撞(collision),因此不适用于安全性认证,如SSL公开密钥认证或是数字签名等用途。

划重点

1996年后该算法被证实存在弱点,可以被加以破解,2004年,证实MD5算法无法防止碰撞(collision),因此不适用于安全性认证,如SSL公开密钥认证或是数字签名等用途

demo

为方便,我们直接使用牛X的工具来测试。

引入hutool工具包

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.9</version>
        </dependency>
public class EncrypTest {
    public static void main(String[] args) {
        String word= "hello world";
        //MD5
        System.out.println(SecureUtil.md5(word));
    }
}

总结

不安全,对于安全性要求比较高的数据,不建议使用。

SHA

安全散列算法(英语:Secure Hash Algorithm,缩写为SHA)是一个密码散列函数家族,是FIPS所认证的安全散列算法。能计算出一个数字消息所对应到的,长度固定的字符串(又称消息摘要)的算法。且若输入的消息不同,它们对应到不同字符串的机率很高。

刚才md5的介绍中,专家建议改为SHA-2

NIST发布了三个额外的SHA变体,这三个函数都将讯息对应到更长的讯息摘要。以它们的摘要长度(以位元计算)加在原名后面来命名:SHA-256,SHA-384和SHA-512。它们发布于2001年的FIPS PUB 180-2草稿中,随即通过审查和评论。包含SHA-1的FIPS PUB 180-2,于2002年以官方标准发布。2004年2月,发布了一次FIPS PUB 180-2的变更通知,加入了一个额外的变种SHA-224″,这是为了符合双金钥3DES所需的金钥长度而定义。

SHA-256和SHA-512是很新的杂凑函数,前者以定义一个word为32位元,后者则定义一个word为64位元。它们分别使用了不同的偏移量,或用不同的常数,然而,实际上二者结构是相同的,只在循环执行的次数上有所差异。SHA-224以及SHA-384则是前述二种杂凑函数的截短版,利用不同的初始值做计算。

这些新的杂凑函数并没有接受像SHA-1一样的公众密码社群做详细的检验,所以它们的密码安全性还不被大家广泛的信任。Gilbert和Handschuh在2003年曾对这些新变种作过一些研究,声称他们没有找到弱点。

划重点

sha-2系列的算法是推荐使用的。

demo

public class EncrypTest {
    public static void main(String[] args) {
        String word= "hello world";
        //sha256
        String sha256Hex = DigestUtil.sha256Hex(word);
        System.out.println(sha256Hex);
    }
}

国密–SM3

SM3是中华人民共和国政府采用的一种密码散列函数标准,由国家密码管理局于2010年12月17日发布。相关标准为“GM/T 0004-2012 《SM3密码杂凑算法》”。

在商用密码体系中,SM3主要用于数字签名及验证、消息认证码生成及验证、随机数生成等,其算法公开。据国家密码管理局表示,其安全性及效率与SHA-256相当。

demo

hutool工具包使用国密时,需要引入的jar包

        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15to18</artifactId>
            <version>1.68</version>
        </dependency>
public class EncrypTest {
    public static void main(String[] args) {
        String word= "hello world";
        //SM3
        String digestHex = SmUtil.sm3(word);
        System.out.println(digestHex);
    }
}

对称加密

采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密。

常用的单向加密算法:

  • DES(Data Encryption Standard):数据加密标准,速度较快,适用于加密大量数据的场合;
  • 3DES(Triple DES):是基于DES,对一块数据用三个不同的密钥进行三次加密,强度更高;
  • AES(Advanced Encryption Standard):高级加密标准,是下一代的加密算法标准,速度快,安全级别高,支持128、192、256、512位密钥的加密
  • Blowfish

优缺点

对称加密算法的优点是算法公开、计算量小、加密速度快、加密效率高。

对称加密算法的缺点是在数据传送前,发送方和接收方必须商定好秘钥,然后使双方都能保存好秘钥。其次如果一方的秘钥被泄露,那么加密信息也就不安全了。另外,每对用户每次使用对称加密算法时,都需要使用其他人不知道的独一秘钥,这会使得收、发双方所拥有的钥匙数量巨大,密钥管理成为双方的负担。

AES

密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。

这个标准用来替代原先的DES(Data Encryption Standard),已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院 (NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准。2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一。

demo

public class EncrypTest {
    public static void main(String[] args) {
        //AES
        //随机生成密钥
        byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.AES.getValue()).getEncoded();
        System.out.println("随机生成密钥******t"+key);
        //构建
        SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, key);
        //加密
        byte[] encrypt = aes.encrypt(word);
        System.out.println("加密后********t"+encrypt);
        //解密
        byte[] decrypt = aes.decrypt(encrypt);
        System.out.println("解密后********t"+decrypt);
        //加密为16进制表示
        String encryptHex = aes.encryptHex(word);
        System.out.println("加密为16进制表示********t"+encryptHex);
        //解密为字符串
        String decryptStr = aes.decryptStr(encryptHex, CharsetUtil.CHARSET_UTF_8);
        System.out.println("解密16进制********t"+decryptStr)
    }
}

国密–SM4

SM4.0(原名SMS4.0)是中华人民共和国政府采用的一种分组密码标准,由国家密码管理局于2012年3月21日发布。相关标准为“GM/T 0002-2012《SM4分组密码算法》(原SMS4分组密码算法)”。

在商用密码体系中,SM4主要用于数据加密,其算法公开,分组长度与密钥长度均为128bit,加密算法与密钥扩展算法都采用32轮非线性迭代结构,S盒为固定的8比特输入8比特输出。

demo

public class EncrypTest {
    public static void main(String[] args) {
        String word= "hello world";
        //SM4
        SymmetricCrypto sm4 = SmUtil.sm4();

        String s = sm4.encryptHex(word);
        System.out.println("SM4加密后*******t"+s);
        String dS = sm4.decryptStr(s, CharsetUtil.CHARSET_UTF_8);
        System.out.println("SM4解密后*******t"+dS);

    }
}

Blowfish

Blowfish是布鲁斯·施奈尔于1993年开发的区块加密算法,对称加密的一种。

Blowfish是一个对称加密块算法,由Bruce Schneider于1993年设计,现已应用在多种加密产品。Blowfish能保证很好的加密速度,并且目前为止没有发现有效地破解方法。目前为止AES比Blowfish有更广的知名度。

Schneider 设计的Blowfish算法用途广泛,意在摒弃DES的老化以及其他算法的强制捆绑。Blowfish刚刚研发出的时候,大部分其他加密算法是专利所有的或属于商业(政府)机密,所以发展起来非常受限制。Schneider 则声明 Blowfish 的使用没有任何限制,任何国家任何人任何时候都可以随意使用 Blowfish算法。

可能大家对Blowfish不是很熟悉,但是一个基于它的加密工具大家一定听说或使用过,那就是Bcrypt。很多人接触到Bcrypt是因为SpringSecurity中使用其作为用户密码加密的工具。

Bcrypt生成的密文是60位的,而且使用BCrypt 主要是能实现每次加密的值都是不一样的,它也可以有效抵御彩虹表。

demo

public class EncrypTest {
    public static void main(String[] args) {
        String word= "hello world";
        //BCrypt
        String pw_hash = BCrypt.hashpw(word, BCrypt.gensalt());
        System.out.println("pw_hash********t"+pw_hash);
        //加密后的其中一次密文
        String encodedPassword = "$2a$10$y6jqMbgAOyspX/N6YCIJOOUyBwAar6GwMF8QODHmcuAQbAOJ/TUkC";
        //验证是否一致
        System.out.println(BCrypt.checkpw(word, pw_hash));
        System.out.println(BCrypt.checkpw(word, encodedPassword));
        //gensalt方法提供了可选参数 (log_rounds) 来定义加盐多少,也决定了加密的复杂度:默认是10,复杂度越高越安全,但是效率越低
        String strong_salt = BCrypt.gensalt(10);
        String stronger_salt = BCrypt.gensalt(12);
        String strong_hash = BCrypt.hashpw(word, strong_salt);
        String stronger_hash = BCrypt.hashpw(word, stronger_salt);
        //$2a$10$wE368HEs30T6NocLz.QIT.7vDA2kYK/jY10GvWb2wJb4yYr/l4N4W
        System.out.println("默认10复杂度的加密***********t"+strong_hash);
        //$2a$12$81A8jaJA/dQNaXCLAXyh5uFsiym2TSeRFrHAlWdYEqgv.qTuSP12m
        System.out.println("自定义12复杂度的加密***********t hhh"+stronger_hash);
    }
}

详见:https://apidoc.Gitee.com/loolly/hutool/cn/hutool/crypto/digest/BCrypt.html

非对称加密

对称加密算法在加密和解密时使用的是同一个秘钥;而非对称加密算法需要两个密钥来进行加密和解密,这两个密钥是公开密钥(public key,简称公钥)和私有密钥(private key,简称私钥)。

与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。

优缺点

公钥密码体制采用的加密密钥(公开钥)和解密密钥(秘密钥)是不同的。由于加密密钥是公开的,密钥的分配和管理就很简单,而且能够很容易地实现数字签名,因此最适合于电子商务应用的需要。其主要的优点是:

  • 密钥分配简单。
  • 密钥的保存量少。
  • 可以满足互不相识的人之间进行私人谈话时的保密性要求。
  • 可以完成数字签名和数字鉴别。

但在实际应用中,公钥密码体制并没有完全取代私钥密码体制,这是因为公钥密码体制在应用中存在以下几个缺点:

  • 公钥密码是对大数进行操作,计算量特别浩大,速度远比不上私钥密码体制。
  • 公钥密码中要将相当一部分密码信息予以公布,势必对系统产生影响。
  • 在公钥密码中,若公钥文件被更改,则公钥被攻破。

RSA

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

demo

public class EncrypTest {
    public static void main(String[] args) {
        String word= "hello world";

        //RSA
        RSA rsa = new RSA();

        //获得私钥
        System.out.println("获得私钥******t"+rsa.getPrivateKey());
        System.out.println("获得私钥64******t"+rsa.getPrivateKeyBase64());
        //获得公钥
        System.out.println("获得公钥******t"+rsa.getPublicKey());
        System.out.println("获得公钥64******t"+rsa.getPublicKeyBase64());

        //公钥加密,私钥解密
        byte[] encryptRSA = rsa.encrypt(StrUtil.bytes(word, CharsetUtil.CHARSET_UTF_8), KeyType.PublicKey);
        System.out.println("公钥加密******t"+encryptRSA);
        byte[] decryptRSA = rsa.decrypt(encryptRSA, KeyType.PrivateKey);
        System.out.println("私钥解密******t"+decryptRSA);
        System.out.println("私钥解密明文******t"+StrUtil.str(decryptRSA,CharsetUtil.CHARSET_UTF_8));

        //Junit单元测试
//        Assert.assertEquals("我是一段测试aaaa", StrUtil.str(decrypt, CharsetUtil.CHARSET_UTF_8));

        //私钥加密,公钥解密
        byte[] encryptRSA2 = rsa.encrypt(StrUtil.bytes(word, CharsetUtil.CHARSET_UTF_8), KeyType.PrivateKey);
        System.out.println("私钥加密******t"+encryptRSA2);
        byte[] decryptRSA2 = rsa.decrypt(encryptRSA2, KeyType.PublicKey);
        System.out.println("公钥解密******t"+decryptRSA2);


        //Junit单元测试
        //Assert.assertEquals("我是一段测试aaaa", StrUtil.str(decrypt2, CharsetUtil.CHARSET_UTF_8));
    }
}

总结

这次主要是把常见、常用的一些加密方式进行了整理,各类算法的用途和场景也有介绍,至于用户密码加密的推荐方式为BCrypt,当然很多实际的场景要考虑整合使用,比如可能在信息传输时采用对称加密或非对称加密,保证在传输过程中的信息安全,然后在存储时采用BCrypt。

欢迎大家分享自己的加密场景,让大家一起变的更完善。


原文始发于微信公众号(云户):关于设计中常用的加密方式整理

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/35325.html

(0)

相关推荐

发表回复

登录后才能评论
半码博客——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!