当前位置: 首页 > 科技观察

面试官:说说你常用的加密算法

时间:2023-03-20 12:15:31 科技观察

加密算法分为:可逆加密和不可逆加密,可逆加密又可以分为:对称加密和非对称加密。1、不可逆加密常见的不可逆加密算法有MD5、HMAC、SHA1、SHA-224、SHA-256、SHA-384、SHA-512,其中SHA-224、SHA-256、SHA-384、SHA-512我们可以统称为SHA2加密算法。SHA加密算法的安全性高于MD5,SHA2加密算法高于SHA1。SHA后面的数字表示加密字符串的长度,SHA1默认会生成一个160位的消息摘要。不可逆加密算法最大的特点就是密钥,但是HMAC需要密钥【手动狗头】。由于这些加密是不可逆的,所以更常见的场景是用户密码加密。验证过程是通过比较两个加密字符串是否相同来确认身份。网上也有很多网站号称可以破解MD5密码。原理都是一样的,就是有一个庞大的资源库,里面存放着很多字符串和对应的MD5加密字符串,通过你输入的MD5加密字符串进行比对,如果你的密码复杂度比较低,通过验证的概率还是很高的。1.1MD5MD5Message-DigestAlgorithm(英文:MD5Message-DigestAlgorithm),一种应用广泛的密码哈希函数,可以生成一个128位(16-byte)的哈希值(hashvalue),用于保证信息的传输是完整和一致。MD5算法具有以下特点:1、可压缩性:不管数据的长度是多少,计算出的MD5值的长度都是一样的。2、计算方便:很容易从原始数据中计算出MD5值。3、抗修改:即使修改了一个字节,计算出的MD5值也会有很大的差异。4、抗碰撞性:知道数据和MD5值,有很小的概率找到MD5值相同的原始数据。publicstaticStringmd5(Stringtext){MessageDigestmessageDigest=null;try{messageDigest=MessageDigest.getInstance("MD5");}catch(NoSuchAlgorithmExceptione){e.printStackTrace();}byte[]bytes=messageDigest.digest(text.getBytes());returnHex.encodeHexString(bytes);}1.2SHA系列安全哈希算法(英文:SecureHashAlgorithm,简称SHA)是密码哈希函数族,是通过FIPS认证的安全哈希算法。一种算法,可以计算出数字消息对应的固定长度字符串(也称为消息摘要)。而如果输入的消息不同,很大概率对应的是不同的字符串。2005年8月17日CRYPTO会议结束时,王晓云、姚期智、姚初峰再次发表了一种更高效的SHA-1攻击方法,可以在2的63次方计算复杂度内找到碰撞。也就是说,SHA-1加密算法是有碰撞的可能性的,虽然碰撞的可能性很小。publicstaticStringsha256(Stringtext){MessageDigestmessageDigest=null;try{messageDigest=MessageDigest.getInstance("SHA-256");}catch(NoSuchAlgorithmExceptione){e.printStackTrace();}byte[]bytes=messageDigest.digest(text.getBytes());returnHex.encodeHexString(bytes);}1.3HMAC系列HMAC是key-relatedhashoperationmessageauthenticationcode(Hash-basedMessageAuthenticationCode)的缩写,由H.Krawezyk,M.Bellare,R.CanettiA开发基于哈希函数和密钥的消息认证方法于1996年提出,1997年作为RFC2104发布,广泛应用于IPSec等网络协议(如SSL),现已成为事实上的互联网安全标准。它可以与任何迭代哈希函数捆绑在一起。HMAC算法更像是一种加密算法。它引入了一个密钥,其安全性并不完全依赖于使用的哈希算法();}try{mac.init(sk);}catch(InvalidKeyExceptione){e.printStackTrace();}byte[]rawHmac=mac.doFinal(text.getBytes());returnnewString(Base64.encodeBase64(rawHmac));如果要使用不可逆加密,建议使用SHA256、SHA384、SHA512和HMAC-SHA256、HMAC-SHA384、HMAC-SHA512这几个算法。2.对称加密算法对称加密算法是较早的算法,数据加密和解密使用同一个密钥,造成密钥管理困难。常见的对称加密算法有DES、3DES、AES128、AES192、AES256(默认安装的JDK不支持AES256,需要安装相应的jce补丁升级jce1.7、jce1.8)。AES后面的数字代表密钥长度。对称加密算法的安全性比较低,比较适用的场景是在内网环境下的加解密。2.1DESDES是对称加密算法领域的典型算法,其默认密钥长度为56位。/encryptpublicstaticStringencrypt(byte[]dataSource,Stringpassword){try{SecureRandomrandom=newSecureRandom();DESKeySpecdesKeySpec=newDESKeySpec(password.getBytes());//创建一个密钥工厂,然后用它把DESKeySpec转换成SecretKeyFactorysecretKeyFactory=SecretKeyFactory。getInstance("DES");SecretKeysecretKey=secretKeyFactory.generateSecret(desKeySpec);//Cipher对象真正完成加密操作Ciphercipher=Cipher.getInstance("DES");//用密钥初始化Cipher对象cipher.init(Cipher.ENCRYPT_MODE,secretKey,random);//正式执行加密操作returnBase64.encodeBase64String(cipher.doFinal(dataSource));}catch(Throwablee){e.printStackTrace();}returnnull;}//解密publicstaticStringdecrypt(Stringsrc,Stringpassword)throwsException{//DES算法需要一个可信的随机数源SecureRandomrandom=newSecureRandom();//创建一个DESKeySpec对象DESKeySpecdesKeySpec=newDESKeySpec(password.getBytes());//创建一个密钥工厂SecretKeyFactoryke??yFactory=SecretKeyFactory.getInstance("DES");//将DESKeySpec对象转换为SecretKey对象SecretKeysecretKey=keyFactory.generateSecret(desKeySpec);//Cipher对象才真正完成解密操作cipher.doFinal(Base64.decodeBase64(src)));}2.23DES3DES(TripleDES)是一种从DES过渡到AES的加密算法。它使用三个56位密钥对数据进行三次加密,是DES的一种更安全的变体。它以DES为基本模块,通过组合分块的方法设计了分块加密算法。3DES比原来的DES更安全。密钥长度默认为168位,也可以选择128位。publicstaticStringencryptThreeDESECB(Stringsrc,Stringkey){try{DESedeKeySpecdks=newDESedeKeySpec(key.getBytes("UTF-8"));SecretKeyFactoryke??yFactory=SecretKeyFactory.getInstance("DESede");SecretKeysecurekey=keyFactory.generateSecret(dks);Ciphercipher=Cipher.getInstance("DESede/ECB/PKCS5Padding");cipher.init(Cipher.ENCRYPT_MODE,securekey);byte[]b=cipher.doFinal(src.getBytes("UTF-8"));Stringss=newString(Base64.encodeBase64(b));ss=ss.replaceAll("\\+","-");ss=ss.replaceAll("/","_");returnss;}catch(Exceptionex){ex.printStackTrace();returnsrc;}}publicstaticStringdecryptThreeDESECB(Stringsrc,Stringkey){try{src=src.replaceAll("-","+");src=src.replaceAll("_","/");byte[]bytesrc=Base64。decodeBase64(src.getBytes("UTF-8"));//--解密的keyDESedeKeySpecdks=newDESedeKeySpec(key.getBytes("UTF-8"));SecretKeyFactoryke??yFactory=SecretKeyFactory.getInstance("DESede");SecretKeysecurekey=keyFactory.generateSecret(dks);//--Chipher对象解密Ciphercipher=Cipher.getInstance("DESede/ECB/PKCS5Padding");cipher.init(Cipher.DECRYPT_MODE,securekey);byte[]retByte=cipher.doFinal(bytesrc);returnnewString(retByte,"UTF-8");}catch(Exceptionex){ex.printStackTrace();returnsrc;}}2.3AESAES高级数据加密标准,可有效抵御对于所有已知的针对DES算法的攻击,默认的密钥长度是128位,192位和256位是可选的。对了,这个bit指的是bit。privatestaticfinalStringdefaultCharset="UTF-8";privatestaticfinalStringKEY_AES="AES";privatestaticfinalStringKEY_MD5="MD5";privatestaticMessageDigestmd5Digest;static{try{md5Digest=MessageDigest.getInstance(KEY_MD5);}catch(NoSuchAlgorithmExceptione){}}/***加密*/publicstaticStringencrypt(Stringdata,Stringkey){returndoAES(data,key,Cipher.ENCRYPT_MODE);}/***解密*/publicstaticStringdecrypt(Stringdata,Stringkey){returndoAES(data,key,Cipher.DECRYPT_MODE);}/***加解密*/privatestaticStringdoAES(Stringdata,Stringkey,intmode){try{booleanencrypt=mode==Cipher.ENCRYPT_MODE;byte[]content;if(encrypt){content=data.getBytes(defaultCharset);}else{content=Base64.decodeBase64(data.getBytes());}SecretKeySpeckeySpec=newSecretKeySpec(md5Digest.digest(key.getBytes(defaultCharset)),KEY_AES);Ciphercipher=Cipher.getInstance(KEY_AES);//创建密码器cipher.init(mode,keySpec);//初始化byte[]result=cipher.doFinal(content);if(encrypt){returnnewString(Base64.encodeBase64(result));}else{returnnewString(result,defaultCharset);}}catch(Exceptione){}returnnull;}推荐的对称加密算法有:AES128,AES192,AES2563.非对称加密算法非对称加密算法是两个key完全不同但完全匹配。只有使用一对匹配的公钥和私钥才能完成对明文的加密和解密。常见的非对称加密有RSA、SM2等。3.1RSARSA密钥长度必须至少为500位,一般推荐1024位。//非对称密钥算法publicstaticfinalStringKEY_ALGORITHM="RSA";/***密钥长度,DH算法默认密钥长度为1024*密钥长度必须是64的倍数,介于512和65536位之间*/privatestaticfinalintKEY_SIZE=1024;//公钥privatestaticfinalStringPUBLIC_KEY="RSAPublicKey";//私钥privatestaticfinalStringPRIVATE_KEY="RSAPrivateKey";/***初始化密钥对**@returnMap甲方密钥Map*/publicstaticMapinitKey()throwsException{//实例化密钥生成器KeyPairGeneratorkeyPairGenerator=KeyPairGenerator.getInstance(KEY_ALGORITHM);//初始化密钥生成器keyPairGenerator.initialize(KEY_SIZE);//生成密钥对KeyPairkeyPair=keyPairGenerator.generateKeyPair();//甲方公钥RSAPublicKeypublicKey=(RSAPublicKey)keyPair.getPublic();//甲方私钥RSAPrivateKeyprivateKey=(RSAPrivateKey)keyPair.getPrivate();//将key存入mapMapkeyMap=newHashMap();keyMap.put(PUBLIC_KEY,publicKey);keyMap.put(PRIVATE_KEY,privateKey);returnkeyMap;}/***私钥加密**@paramdata待加密数据*@paramkeykey*@returnbyte[]加密数据*/publicstaticbyte[]encryptByPrivateKey(byte[]data,byte[]key)throwsException{//获取私钥PKCS8EncodedKeySpecpkcs8KeySpec=newPKCS8EncodedKeySpec(key);KeyFactoryke??yFactory=KeyFactory.getInstance(KEY_ALGORITHM);//生成私钥PrivateKeyprivateKey=keyFactory.generatePrivate(pkcs8KeySpecphercipher);//数据加密CiphercigetInstance(keyFactory.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE,privateKey);returncipher.doFinal(data);}/***公钥加密**@paramdata待加密数据*@paramkeykey*@returnbyte[]加密数据*/publicstaticbyte[]encryptByPublicKey(byte[]data,byte[]key)throwsException{//实例化密钥工厂KeyFactoryke??yFactory=KeyFactory.getInstance(KEY_ALGORITHM);//初始化公钥//密钥材料转换X509EncodedKeySpecx509KeySpec=newX509EncodedKeySpec(key);//生成公钥PublicKeypubKey=keyFactory.generatePublic(x509KeySpec);//数据加密Ciphercipher=Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE,pubncKey);re.doFinal(data);}/***私钥解密ion**@paramdata待解密数据*@paramkeykey*@returnbyte[]解密数据*/publicstaticbyte[]decryptByPrivateKey(byte[]data,byte[]key)throwsException{//获取私钥PKCS8EncodedKeySpecpkcs8KeySpec=newPKCS8EncodedKeySpec(key);KeyFactoryke??yFactory=KeyFactory.getInstance(KEY_ALGORITHM);//生成私钥PrivateKeyprivateKey=keyFactory.generatePrivate(pkcs8KeySpec);//数据解密Ciphercipher=Cipher.getInstance(keyFactory.cipher.getAlg)(Cipher.DECRYPT_MODE,privateKey);returncipher.doFinal(data);}/***公钥解密**@paramdata待解密数据*@paramkeykey*@returnbyte[]解密数据*/publicstaticbyte[]decryptByPublicKey(byte[]data,byte[]key)throwsException{//实例化密钥工厂KeyFactoryke??yFactory=KeyFactory.getInstance(KEY_ALGORITHM);//初始化公钥//密钥材料转换X509EncodedKeySpecx509KeySpec=newX509EncodedKeySpec(key);//生成公钥PublicKeypubKey=keyFactory.generatePublic(x509KeySpec);//数据解密Ciphercipher=Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.DECRYPT_MODE,pubKey);returncipher.doFinal(data);}/***获取私钥**@paramkeyMapkeymap*@returnbyte[]私钥*/publicstaticbyte[]getPrivateKey(MapkeyMap){Keykey=(Key)keyMap.get(PRIVATE_KEY);returnkey.getEncoded();}/***获取公钥**@paramkeyMapkeymap*@returnbyte[]publickey*/publicstaticbyte[]getPublicKey(MapkeyMap)throwsException{Keykey=(Key)keyMap.get(PUBLIC_KEY);returnkey.getEncoded();}4.加密盐加密盐也是一个经常听到的概念。salt是一个随机字符串,用来和我们的加密字符串进行拼接,然后加密加盐,主要是为了提供加密字符串的安全性。如果有加盐后的加密字符串,黑客通过一定的手段利用加密后的字符串,得到的明文不是我们加密前的字符串,而是加密前的字符串加盐后的字符串。据说增加了字符串的安全性。本文部分算法来源于网络,可直接复制使用。推荐的几种加密算法有:不可逆加密:SHA256、SHA384、SHA512和HMAC-SHA256、HMAC-SHA384、HMAC-SHA512对称加密算法:AES、3DES非对称加密算法:RSA本文转载自微信公众号》JavaJourney》,可通过以下二维码关注。转载本文,请联系JavaJourney公众号。