当前位置: 首页 > 后端技术 > Java

快速了解常用的非对称加密算法,再也不用担心面试官的盘问

时间:2023-04-01 15:49:14 Java

面试官:说说你常用的加密算法有哪些?加密算法一般分为两种:对称加密算法和非对称加密算法。其中,对称加密算法使用相同的密钥进行加密和解密;非对称加密算法使用不同的密钥进行加密和解密,分为公钥和私钥。此外,还有一类叫做消息摘要算法,是一种不可逆的数据汇总算法。这次我们来看非对称加密算法。非对称加密算法非对称加密算法在加密和解密时使用两种不同的密钥,其中一个可以公开的称为公钥,另一个完全保密的密钥称为私钥。只有相同的公钥和私钥对才能正常加解密。对于相同的公钥和私钥对,如果使用公钥加密数据,则只能使用对应的私钥进行解密;如果用私钥加密数据,只有对应的公钥才能解密。常见的非对称加密算法有:RSA算法、DSA。RSA算法RSA算法是目前影响最大的公钥加密算法。它是由RonRivest、AdiShamir和LeonardAdleman于1977年在麻省理工学院工作时提出的。RSA是他们三个名字的开头。字母放在一起。此外,1973年,英国政府通信总部的数学家CliffordCocks在一份内部文件中提出了一个等价的算法,但该算法被保密,直到1997年才公开。RSA算法利用了两个数论性质:p1和p2是两个素数,n=p1*p2。知道p1和p2来找到n很容易,但是知道n来找到p1和p2很难。(m^e)modn=c,知道m,e,n求c容易,知道e,n,c求m难。公钥私钥生成过程:随机选取两个质数p1,p2,n=p1*p2,然后随机选取一个与φ(n)互质且小于φ(n)的整数e,然后计算e对于φ(n的模元d),最终得到n和e作为公钥,n和d作为私钥。加密过程:(m^e)modn=c,其中m为明文,c为密文,n、e为公钥。解密过程:(c^d)modn=m,其中m为明文,c为密文,n、d为私钥。我们用Java写一个例子:importjavax.crypto.Cipher;importjava.nio.charset.Charset;importjava.nio.charset.StandardCharsets;importjava.security.GeneralSecurityException;importjava.security.KeyFactory;importjava.security.KeyPair;导入java.security.KeyPairGenerator;导入java.security.PrivateKey;导入java.security.PublicKey;导入java.security.spec.PKCS8EncodedKeySpec;导入java.security.spec.X509EncodedKeySpec;导入java.util.Base64;公共classRsaUtil{privatestaticfinalStringRSA="RSA";私人静态最终字符集CHARSET=StandardCharsets.UTF_8;/***加密**@paraminput明文*@parampublicKey公钥*@return密文*@throwsGeneralSecurityException*/publicstaticStringencrypt(Stringinput,StringpublicKey)throwsGeneralSecurityException{Ciphercipher=Cipher.getInstance(RSA);PublicKeypubKey=KeyFactory.getInstance(RSA).generatePublic(newX509EncodedKeySpec(Base64.getDecoder().decode(publicKey)));cipher.init(Cipher.ENCRYPT_MODE,pubKey);byte[]data=cipher.doFinal(input.getBytes(CHARSET));返回Base64.getEncoder().encodeToString(数据);}/***解密**@paraminput密文*@paramprivateKey私钥*@return明文*@throwsGeneralSecurityException*/publicstaticStringdecrypt(Stringinput,StringprivateKey)throwsGeneralSecurityException{Ciphercipher=Cipher.getInstance(RSA);PrivateKeypriKey=KeyFactory.getInstance("RSA").generatePrivate(newPKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));cipher.init(Cipher.DECRYPT_MODE,priKey);byte[]data=cipher.doFinal(Base64.getDecoder().decode(input));返回新字符串(数据,字符集);}publicstaticvoidmain(String[]args)throwsGeneralSecurityException{//生成公钥/私钥对:KeyPairGeneratorkpGen=KeyPairGenerator.getInstance(RSA);kpGen.initialize(1024);KeyPairkeyPair=kpGen.generateKeyPair();StringpublicKey=Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());StringprivateKey=Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());System.out.println("公钥:"+publicKey);System.out.println("私钥:"+privateKey);Stringmsg="我喜欢你,可以做我女朋友吗?";System.out.println("加密前:"+msg);Stringpwd=RsaUtil.encrypt(msg,publicKey);System.out.println("加密后:"+pwd);System.out.println("解密后:"+RsaUtil.decrypt(pwd,privateKey));}}运行结果如下:公钥:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDd4brSm8gdJqFi04m3aW8kjVYbd/T4ymyc7l3c2WmwOhVPlZO1eaZJpTvas61rW0HPf267CRIhc52Zp2+e1hoknApvT0gKeRkfSwC5aws/yoT2vZ9J627QbCFkFc8mmfP8LJ5V/rCpmUE12dIW4xVlEYtWPzmNK2iTMzuR99Jq9wIDAQAB私钥:MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAN3hutKbyB0moWLTibdpbySNVht39PjKbJzuXdzZabA6FU+Vk7V5pkmlO9qzrWtbQc9/brsJEiFznZmnb57WGiScCm9PSAp5GR9LALlrCz/KhPa9n0nrbtBsIWQVzyaZ8/wsnlX+sKmZQTXZ0hbjFWURi1Y/OY0raJMzO5H30mr3AgMBAAECgYEAuxPtKlAwzOtaXXIQhrV+AWqttGFTCkXaiAKu31vssap3d2+daACWxTdtHPwr9v2tol9GpKqEP/I0am5zPZA13x+tv068x2TxGf8ZEbp579CKE3NrzTrnhtJN31TT82HIJoJ0TsNUhHbwZPWVAsq98afSCP1rn5RY/kwJ6bzsjhECQQD8Ev044KaUdWd0WZoomMP+5tATUL0HTMmUiBEvrXjOWG2mjuD4M5n/9C11FZWFg+o75riAUiNYE5dfGyK1uDP5AkEA4VZdUOTPt0DclMESX3lOddS3o+TL/OkowErP0mAl3NzbJ1PnDUifQ0q1IZUoCi1nG9eVZScS8xZ7oa7ICgdybwJBAIY/OrsK8cyJBlLx0WcjjOZ5WIGg8zsrCwRevwBsW7VRZPxahbfKC49EJN2BZENaMOo8AzDcDdS/glN1aTPsaUkCQAVLhj3UYp0nxQcp0ki0DQfvy7DqO3Dh+bcrCt8iq0EZX3z5F8DUKAnow4DahGpYzsd0tWn/FQ7pRFZ0SPcTXbkCQQCp7ay9nEo2hEH08E5LekFsuipDjCEpeCgKojZUmFCh7BdawG6XzCLzNMMIIIjqRHlrJaxS41WhedPZR4nTNxGF加密前:我喜欢你,可以做mygirlfriend?Afterencryption:tRt5hdF0XB8V2wk6BWC2i8UWVQj/jOCRZn3wIfGYqVaYJ9OjC/+VRUI3c5WgpZlKCZd5zrHo3g1LuQ02G934Gcb51cKH4uhWxRY8oxugs/fibkvc9+w1X7FQarFwAGCs5SddHIL/vYUxHIvQslelyP9l9/EFpgSs0WWSfOfKcUc=解密后:我喜欢你,你可以做我女朋友吗?RSA算法解决了对称算法的安全依赖于同一个密钥的缺点。但是RSA算法计算比较复杂,性能也不好,远不如对称加密算法。因此,在一般实际情况下,往往会通过非对称加密算法随机生成临时对称密钥,然后通过对称加密传输大量主体数据。DSADSA(数字签名算法)是Schnorr和ElGamal签名算法的变体,基于模运算和离散对数的复杂性。美国国家标准技术研究院(NIST)于1991年提出将DSA用于其DSS(DigitalSignatureStandard),并于1994年采纳为FIPS186。不同于RSA算法,它使用公钥加密和解密私钥,DSA使用私钥加密数据生成数字签名,然后使用公钥将解密后的数据与原始数据进行比对,验证数字签名。数字签名提供信息认证(接收方可以验证消息的来源)、完整性(接收方可以验证消息在签名后没有被修改)和不可否认性(发送方不能谎称他们没有签署消息)。我们用Java写一个例子:importjava.nio.charset.Charset;importjava.nio.charset.StandardCharsets;importjava.security.GeneralSecurityException;importjava.security.KeyFactory;importjava.security.KeyPair;importjava.security.KeyPairGenerator;导入java.security.PrivateKey;导入java.security.PublicKey;导入java.security.Signature;导入java.security.spec.PKCS8EncodedKeySpec;导入java.security.spec.X509EncodedKeySpec;导入java.util.Base64;公共classDsaUtil{privatestaticfinalStringDSA="DSA";privatestaticfinalStringSHA1withDSA="SHA1withDSA";私人静态最终字符集CHARSET=StandardCharsets.UTF_8;/***签名**@paramdata数据*@paramprivateKey私钥*@return签名*@throwsGeneralSecurityException*/publicstaticStringsign(Stringdata,StringprivateKey)throwsGeneralSecurityException{PrivateKeypriKey=KeyFactory.getInstance(DSA).generatePrivate(新PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));签名signature=Signature.getInstance(SHA1withDSA);signature.initSign(priKey);signature.update(data.getBytes(CHARSET));返回Base64.getEncoder().encodeToString(signature.sign());}/***验证**@paramdata数据*@parampublicKey公钥*@paramsign签名*@return是否验证通过*/publicstaticbooleanverify(Stringdata,StringpublicKey,Stringsign)throwsGeneralSecurityException{try{PublicKeypubKey=KeyFactory.getInstance(DSA).generatePublic(newX509EncodedKeySpec(Base64.getDecoder().decode(publicKey)));签名signature=Signature.getInstance(SHA1withDSA);signature.initVerify(pubKey);signature.update(data.getBytes(CHARSET));返回signature.verify(Base64.getDecoder().decode(sign));}赶上(例如概念e){抛出新的RuntimeException(e);}}publicstaticvoidmain(String[]args)throwsGeneralSecurityException{//生成公钥/私钥对:KeyPairGeneratorkpGen=KeyPairGenerator.getInstance(DSA);kpGen.initialize(1024);KeyPairkeyPair=kpGen.generateKeyPair();StringpublicKey=Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());StringprivateKey=Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());System.out.println("公钥:"+publicKey);System.out.println("私钥:"+privateKey);Stringmsg="我喜欢你,可以做我女朋友吗?";System.out.println("数据:"+msg);Stringsign=DsaUtil.sign(msg,privateKey);System.out.println("签名:"+sign);System.out.println("验证是否通过:"+DsaUtil.verify(msg,publicKey,sign));}}结果如下:公钥:MIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQAAoGABDM1s78NZ4C0Bh9V86Z1lylEyCjCg2oAj6Kxd3/2IXhSlplnSpJPLlomet9yWJpagLQieIWHAIyq6JLmdcVxOxUvnLIsrvWKIPr4lz7pIqO1xi4AYunP48gPECHlMgOKPyik3ZkQQ3iHl9MiaWOaeisqsw/gzTUtE1xi8CVscks=私钥:MIIBSwIBADCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoEFgIUA1HUKjMiSvazMzpKczR6w6DDbeM=Data:我喜欢你,你可以做我女朋友吗?Signature:MCwCFHhnd/3yRCIygyD1GPa1K9ZVQ+4rAhR8zAtlrBim9KKEkv+Fxz47opvSuA==Verificationpassed:true从Java例子可以看出,数据不会直接用私钥加密,而是先通过信息摘要算法对数据进行消化,以及那么摘要信息加密与私钥摘要非对称加密算法使用两种不同的密钥进行加密和解密,分别称为公钥和私钥。只有相同的公钥和私钥对才能进行正常的加密和解密。常见的非对称加密算法有:RSA算法、DSA。RSA算法主要是用公钥对数据进行加密,DSA算法主要是对数据进行签名校验。这点我早就看出来了,你我一定是有缘,留下你的喜欢和关注,你日后必成大器。