課程總結(jié)-密碼學(xué)總結(jié)-簽名加密算法及實(shí)現(xiàn)_第1頁(yè)
課程總結(jié)-密碼學(xué)總結(jié)-簽名加密算法及實(shí)現(xiàn)_第2頁(yè)
課程總結(jié)-密碼學(xué)總結(jié)-簽名加密算法及實(shí)現(xiàn)_第3頁(yè)
課程總結(jié)-密碼學(xué)總結(jié)-簽名加密算法及實(shí)現(xiàn)_第4頁(yè)
課程總結(jié)-密碼學(xué)總結(jié)-簽名加密算法及實(shí)現(xiàn)_第5頁(yè)
已閱讀5頁(yè),還剩23頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

總結(jié)—簽名加密算法及實(shí)現(xiàn)前言數(shù)字簽名、信息加密是前后端開(kāi)發(fā)都經(jīng)常需要使用到的技術(shù),應(yīng)用場(chǎng)景包括了用戶登入、交易、信息通訊、oauth等等,不同的應(yīng)用場(chǎng)景也會(huì)需要使用到不同的簽名加密算法,或者需要搭配不一樣的簽名加密算法來(lái)達(dá)到業(yè)務(wù)目標(biāo)。本文介紹了數(shù)字簽名,加密和解密,對(duì)稱加密和非對(duì)稱加密,然后詳細(xì)說(shuō)明

MD5,SHA-1,HMAC,DES/AES,RSA和ECC這幾種加密算法和代碼示例。正文1.數(shù)字簽名數(shù)字簽名,簡(jiǎn)單來(lái)說(shuō)就是通過(guò)提供可鑒別的數(shù)字信息驗(yàn)證自身身份的一種方式。一套數(shù)字簽名通常定義兩種互補(bǔ)的運(yùn)算,一個(gè)用于簽名,另一個(gè)用于驗(yàn)證。分別由發(fā)送者持有能夠代表自己身份的私鑰(私鑰不可泄露),由接受者持有與私鑰對(duì)應(yīng)的公鑰,能夠在接受到來(lái)自發(fā)送者信息時(shí)用于驗(yàn)證其身份。2.加密和解密2.1.加密數(shù)據(jù)加密的基本過(guò)程,就是對(duì)原來(lái)為明文的文件或數(shù)據(jù)按某種算法進(jìn)行處理,使其成為不可讀的一段代碼,通常稱為“密文”。通過(guò)這樣的途徑,來(lái)達(dá)到保護(hù)數(shù)據(jù)不被非法人竊取、閱讀的目的。2.2.解密加密的逆過(guò)程為解密,即將該編碼信息轉(zhuǎn)化為其原來(lái)數(shù)據(jù)的過(guò)程。3.對(duì)稱加密和非對(duì)稱加密加密算法分對(duì)稱加密和非對(duì)稱加密,其中對(duì)稱加密算法的加密與解密密鑰相同,非對(duì)稱加密算法的加密密鑰與解密密鑰不同,此外,還有一類不需要密鑰的散列算法。常見(jiàn)的對(duì)稱加密算法主要有:DES、3DES、AES等,常見(jiàn)的非對(duì)稱算法主要有:RSA、DSA等,散列算法主要有SHA-1、MD5等。3.1.對(duì)稱加密對(duì)稱加密算法是應(yīng)用較早的加密算法,又稱為共享密鑰加密算法。在對(duì)稱加密算法中,使用的密鑰只有一個(gè),發(fā)送和接收雙方都使用這個(gè)密鑰對(duì)數(shù)據(jù)進(jìn)行加密和解密。這就要求加密和解密方事先都必須知道加密的密鑰。數(shù)據(jù)加密過(guò)程:在對(duì)稱加密算法中,數(shù)據(jù)發(fā)送方將明文(原始數(shù)據(jù))和加密密鑰一起經(jīng)過(guò)特殊加密處理,生成復(fù)雜的加密密文進(jìn)行發(fā)送。數(shù)據(jù)解密過(guò)程:數(shù)據(jù)接收方收到密文后,若想讀取原數(shù)據(jù),則需要使用加密使用的密鑰及相同算法的逆算法對(duì)加密的密文進(jìn)行解密,才能使其恢復(fù)成可讀明文。3.2.非對(duì)稱加密非對(duì)稱加密算法,又稱為公開(kāi)密鑰加密算法。它需要兩個(gè)密鑰,一個(gè)稱為公開(kāi)密鑰(publickey),即公鑰,另一個(gè)稱為私有密鑰(privatekey),即私鑰。因?yàn)榧用芎徒饷苁褂玫氖莾蓚€(gè)不同的密鑰,所以這種算法稱為非對(duì)稱加密算法。如果使用公鑰對(duì)數(shù)據(jù)進(jìn)行加密,只有用對(duì)應(yīng)的私鑰才能進(jìn)行解密。如果使用私鑰對(duì)數(shù)據(jù)進(jìn)行加密,只有用對(duì)應(yīng)的公鑰才能進(jìn)行解密。例子:甲方生成一對(duì)密鑰并將其中的一把作為公鑰向其它人公開(kāi),得到該公鑰的乙方使用該密鑰對(duì)機(jī)密信息進(jìn)行加密后再發(fā)送給甲方,甲方再使用自己保存的另一把專用密鑰(私鑰),對(duì)加密后的信息進(jìn)行解密。4.常見(jiàn)的簽名加密算法4.1.MD5算法MD5用的是哈希函數(shù),它的典型應(yīng)用是對(duì)一段信息產(chǎn)生信息摘要,以防止被篡改。嚴(yán)格來(lái)說(shuō),MD5不是一種加密算法而是摘要算法。無(wú)論是多長(zhǎng)的輸入,MD5都會(huì)輸出長(zhǎng)度為128bits的一個(gè)串(通常用16進(jìn)制表示為32個(gè)字符)。Java代碼如下:publicstaticfinalbyte[]computeMD5(byte[]content){try{MessageDigestmd5=MessageDigest.getInstance("MD5");returnmd5.digest(content);}catch(NoSuchAlgorithmExceptione){thrownewRuntimeException(e);}}4.2.SHA1算法SHA1是和MD5一樣流行的消息摘要算法,然而SHA1比MD5的安全性更強(qiáng)。對(duì)于長(zhǎng)度小于2^64位的消息,SHA1會(huì)產(chǎn)生一個(gè)160位的消息摘要。基于MD5、SHA1的信息摘要特性以及不可逆(一般而言),可以被應(yīng)用在檢查文件完整性以及數(shù)字簽名等場(chǎng)景。Java代碼如下:publicstaticbyte[]computeSHA1(byte[]content){try{MessageDigestsha1=MessageDigest.getInstance("SHA1");returnsha1.digest(content);}catch(NoSuchAlgorithmExceptione){thrownewRuntimeException(e);}}4.3.HMAC算法HMAC是密鑰相關(guān)的哈希運(yùn)算消息認(rèn)證碼(Hash-basedMessageAuthenticationCode),HMAC運(yùn)算利用哈希算法(MD5、SHA1等),以一個(gè)密鑰和一個(gè)消息為輸入,生成一個(gè)消息摘要作為輸出。HMAC發(fā)送方和接收方都有的key進(jìn)行計(jì)算,而沒(méi)有這把key的第三方,則是無(wú)法計(jì)算出正確的散列值的,這樣就可以防止數(shù)據(jù)被篡改。java代碼如下:packagenet.pocrd.util;importnet.pocrd.annotation.NotThreadSafe;importnet.pocrd.define.ConstField;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importjavax.crypto.Mac;importjavax.crypto.SecretKey;importjavax.crypto.spec.SecretKeySpec;importjava.util.Arrays;@NotThreadSafepublicclassHMacHelper{privatestaticfinalLoggerlogger=LoggerFactory.getLogger(HMacHelper.class);privateMacmac;/***MAC算法可選以下多種算法*HmacMD5/HmacSHA1/HmacSHA256/HmacSHA384/HmacSHA512*/privatestaticfinalStringKEY_MAC="HmacMD5";publicHMacHelper(Stringkey){try{SecretKeysecretKey=newSecretKeySpec(key.getBytes(ConstField.UTF8),KEY_MAC);mac=Mac.getInstance(secretKey.getAlgorithm());mac.init(secretKey);}catch(Exceptione){logger.error("createhmachelperfailed.",e);}}publicbyte[]sign(byte[]content){returnmac.doFinal(content);}publicbooleanverify(byte[]signature,byte[]content){try{byte[]result=mac.doFinal(content);returnArrays.equals(signature,result);}catch(Exceptione){logger.error("verifysigfailed.",e);}returnfalse;}}測(cè)試結(jié)論:HMAC算法實(shí)例在多線程環(huán)境下是不安全的。但是需要在多線程訪問(wèn)時(shí),進(jìn)行同步的輔助類,使用ThreadLocal為每個(gè)線程緩存一個(gè)實(shí)例可以避免進(jìn)行鎖操作。4.4.AES/DES/3DES算法AES、DES、3DES都是對(duì)稱的塊加密算法,加解密的過(guò)程是可逆的。常用的有AES128、AES192、AES256(默認(rèn)安裝的JDK尚不支持AES256,需要安裝對(duì)應(yīng)的jce補(bǔ)丁進(jìn)行升級(jí)jce1.7,jce1.8)。4.4.1.DES算法DES加密算法是一種分組密碼,以64位為分組對(duì)數(shù)據(jù)加密,它的密鑰長(zhǎng)度是56位,加密解密用同一算法。DES加密算法是對(duì)密鑰進(jìn)行保密,而公開(kāi)算法,包括加密和解密算法。這樣,只有掌握了和發(fā)送方相同密鑰的人才能解讀由DES加密算法加密的密文數(shù)據(jù)。因此,破譯DES加密算法實(shí)際上就是搜索密鑰的編碼。對(duì)于56位長(zhǎng)度的密鑰來(lái)說(shuō),如果用窮舉法來(lái)進(jìn)行搜索的話,其運(yùn)算次數(shù)為2^56次。4.4.2.3DES算法是基于DES的對(duì)稱算法,對(duì)一塊數(shù)據(jù)用三個(gè)不同的密鑰進(jìn)行三次加密,強(qiáng)度更高。4.4.3.AES算法AES加密算法是密碼學(xué)中的高級(jí)加密標(biāo)準(zhǔn),該加密算法采用對(duì)稱分組密碼體制,密鑰長(zhǎng)度的最少支持為128位、192位、256位,分組長(zhǎng)度128位,算法應(yīng)易于各種硬件和軟件實(shí)現(xiàn)。這種加密算法是美國(guó)聯(lián)邦政府采用的區(qū)塊加密標(biāo)準(zhǔn)。AES本身就是為了取代DES的,AES具有更好的安全性、效率和靈活性。Java代碼如下:importnet.pocrd.annotation.NotThreadSafe;importjavax.crypto.Cipher;importjavax.crypto.KeyGenerator;importjavax.crypto.spec.IvParameterSpec;importjavax.crypto.spec.SecretKeySpec;importjava.security.SecureRandom;@NotThreadSafepublicclassAesHelper{privateSecretKeySpeckeySpec;privateIvParameterSpeciv;publicAesHelper(byte[]aesKey,byte[]iv){if(aesKey==null||aesKey.length<16||(iv!=null&&iv.length<16)){thrownewRuntimeException("錯(cuò)誤的初始密鑰");}if(iv==null){iv=Md5Upute(aesKey);}keySpec=newSecretKeySpec(aesKey,"AES");this.iv=newIvParameterSpec(iv);}publicAesHelper(byte[]aesKey){if(aesKey==null||aesKey.length<16){thrownewRuntimeException("錯(cuò)誤的初始密鑰");}keySpec=newSecretKeySpec(aesKey,"AES");this.iv=newIvParameterSpec(Md5Upute(aesKey));}publicbyte[]encrypt(byte[]data){byte[]result=null;Ciphercipher=null;try{cipher=Cipher.getInstance("AES/CFB/NoPadding");cipher.init(Cipher.ENCRYPT_MODE,keySpec,iv);result=cipher.doFinal(data);}catch(Exceptione){thrownewRuntimeException(e);}returnresult;}publicbyte[]decrypt(byte[]secret){byte[]result=null;Ciphercipher=null;try{cipher=Cipher.getInstance("AES/CFB/NoPadding");cipher.init(Cipher.DECRYPT_MODE,keySpec,iv);result=cipher.doFinal(secret);}catch(Exceptione){thrownewRuntimeException(e);}returnresult;}publicstaticbyte[]randomKey(intsize){byte[]result=null;try{KeyGeneratorgen=KeyGenerator.getInstance("AES");gen.init(size,newSecureRandom());result=gen.generateKey().getEncoded();}catch(Exceptione){thrownewRuntimeException(e);}returnresult;}}4.5.RSA算法RSA加密算法是目前最有影響力的公鑰加密算法,并且被普遍認(rèn)為是目前最優(yōu)秀的公鑰方案之一。RSA是第一個(gè)能同時(shí)用于加密和數(shù)字簽名的算法,它能夠抵抗到目前為止已知的所有密碼攻擊,已被ISO推薦為公鑰數(shù)據(jù)加密標(biāo)準(zhǔn)。RSA加密算法基于一個(gè)十分簡(jiǎn)單的數(shù)論事實(shí):將兩個(gè)大素?cái)?shù)相乘十分容易,但想要對(duì)其乘積進(jìn)行因式分解卻極其困難,因此可以將乘積公開(kāi)作為加密密鑰。Java代碼如下:importnet.pocrd.annotation.NotThreadSafe;importvider.BouncyCastleProvider;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importjavax.crypto.Cipher;importjava.io.ByteArrayOutputStream;importjava.security.KeyFactory;importjava.security.Security;importjava.security.Signature;importerfaces.RSAPrivateCrtKey;importerfaces.RSAPublicKey;importjava.security.spec.PKCS8EncodedKeySpec;importjava.security.spec.X509EncodedKeySpec;@NotThreadSafepublicclassRsaHelper{privatestaticfinalLoggerlogger=LoggerFactory.getLogger(RsaHelper.class);privateRSAPublicKeypublicKey;privateRSAPrivateCrtKeyprivateKey;static{Security.addProvider(newBouncyCastleProvider());//使用bouncycastle作為加密算法實(shí)現(xiàn)}publicRsaHelper(StringpublicKey,StringprivateKey){this(Base64Util.decode(publicKey),Base64Util.decode(privateKey));}publicRsaHelper(byte[]publicKey,byte[]privateKey){try{KeyFactorykeyFactory=KeyFactory.getInstance("RSA");if(publicKey!=null&&publicKey.length>0){this.publicKey=(RSAPublicKey)keyFactory.generatePublic(newX509EncodedKeySpec(publicKey));}if(privateKey!=null&&privateKey.length>0){this.privateKey=(RSAPrivateCrtKey)keyFactory.generatePrivate(newPKCS8EncodedKeySpec(privateKey));}}catch(Exceptione){thrownewRuntimeException(e);}}publicRsaHelper(StringpublicKey){this(Base64Util.decode(publicKey));}publicRsaHelper(byte[]publicKey){try{KeyFactorykeyFactory=KeyFactory.getInstance("RSA");if(publicKey!=null&&publicKey.length>0){this.publicKey=(RSAPublicKey)keyFactory.generatePublic(newX509EncodedKeySpec(publicKey));}}catch(Exceptione){thrownewRuntimeException(e);}}publicbyte[]encrypt(byte[]content){if(publicKey==null){thrownewRuntimeException("publickeyisnull.");}if(content==null){returnnull;}try{Ciphercipher=Cipher.getInstance("RSA/ECB/PKCS1Padding");cipher.init(Cipher.ENCRYPT_MODE,publicKey);intsize=publicKey.getModulus().bitLength()/8-11;ByteArrayOutputStreambaos=newByteArrayOutputStream((content.length+size-1)/size*(size+11));intleft=0;for(inti=0;i<content.length;){left=content.length-i;if(left>size){cipher.update(content,i,size);i+=size;}else{cipher.update(content,i,left);i+=left;}baos.write(cipher.doFinal());}returnbaos.toByteArray();}catch(Exceptione){thrownewRuntimeException(e);}}publicbyte[]decrypt(byte[]secret){if(privateKey==null){thrownewRuntimeException("privatekeyisnull.");}if(secret==null){returnnull;}try{Ciphercipher=Cipher.getInstance("RSA/ECB/PKCS1Padding");cipher.init(Cipher.DECRYPT_MODE,privateKey);intsize=privateKey.getModulus().bitLength()/8;ByteArrayOutputStreambaos=newByteArrayOutputStream((secret.length+size-12)/(size-11)*size);intleft=0;for(inti=0;i<secret.length;){left=secret.length-i;if(left>size){cipher.update(secret,i,size);i+=size;}else{cipher.update(secret,i,left);i+=left;}baos.write(cipher.doFinal());}returnbaos.toByteArray();}catch(Exceptione){logger.error("rsadecryptfailed.",e);}returnnull;}publicbyte[]sign(byte[]content){if(privateKey==null){thrownewRuntimeException("privatekeyisnull.");}if(content==null){returnnull;}try{Signaturesignature=Signature.getInstance("SHA1WithRSA");signature.initSign(privateKey);signature.update(content);returnsignature.sign();}catch(Exceptione){thrownewRuntimeException(e);}}publicbooleanverify(byte[]sign,byte[]content){if(publicKey==null){thrownewRuntimeException("publickeyisnull.");}if(sign==null||content==null){returnfalse;}try{Signaturesignature=Signature.getInstance("SHA1WithRSA");signature.initVerify(publicKey);signature.update(content);returnsignature.verify(sign);}catch(Exceptione){logger.error("rsaverifyfailed.",e);}returnfalse;}}4.6.ECC算法ECC也是一種非對(duì)稱加密算法,主要優(yōu)勢(shì)是在某些情況下,它比其他的方法使用更小的密鑰,比如RSA加密算法,提供相當(dāng)?shù)幕蚋叩燃?jí)的安全級(jí)別。不過(guò)一個(gè)缺點(diǎn)是加密和解密操作的實(shí)現(xiàn)比其他機(jī)制時(shí)間長(zhǎng)(相比RSA算法,該算法對(duì)CPU消耗嚴(yán)重)。Java代碼如下:importnet.pocrd.annotation.NotThreadSafe;importvider.asymmetric.ec.BCECPrivateKey;importvider.asymmetric.ec.BCECPublicKey;importvider.BouncyCastleProvider;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importjavax.crypto.Cipher;importjava.io.ByteArrayOutputStream;importjava.security.KeyFactory;importjava.security.Security;importjava.security.Signature;importjava.security.spec.PKCS8EncodedKeySpec;importjava.security.spec.X509EncodedKeySpec;@NotThreadSafepublicclassEccHelper{privatestaticfinalLoggerlogger=LoggerFactory.getLogger(EccHelper.class);privatestaticfinalintSIZE=4096;privateBCECPublicKeypublicKey;privateBCECPrivateKeyprivateKey;static{Security.addProvider(newBouncyCastleProvider());}publicEccHelper(StringpublicKey,StringprivateKey){this(Base64Util.decode(publicKey),Base64Util.decode(privateKey));}publicEccHelper(byte[]publicKey,byte[]privateKey){try{KeyFactorykeyFactory=KeyFactory.getInstance("EC","BC");if(publicKey!=null&&publicKey.length>0){this.publicKey=(BCECPublicKey)keyFactory.generatePublic(newX509EncodedKeySpec(publicKey));}if(privateKey!=null&&privateKey.length>0){this.privateKey=(BCECPrivateKey)keyFactory.generatePrivate(newPKCS8EncodedKeySpec(privateKey));}}catch(ClassCastExceptione){thrownewRuntimeException("",e);}catch(Exceptione){thrownewRuntimeException(e);}}publicEccHelper(StringpublicKey){this(Base64Util.decode(publicKey));}publicEccHelper(byte[]publicKey){try{KeyFactorykeyFactory=KeyFactory.getInstance("EC","BC");if(publicKey!=null&&publicKey.length>0){this.publicKey=(BCECPublicKey)keyFactory.generatePublic(newX509EncodedKeySpec(publicKey));}}catch(Exceptione){thrownewRuntimeException(e);}}publicbyte[]encrypt(byte[]content){if(publicKey==null){thrownewRuntimeException("publickeyisnull.");}try{Ciphercipher=Cipher.getInstance("ECIES","BC");cipher.init(Cipher.ENCRYPT_MODE,publicKey);intsize=SIZE;ByteArrayOutputStreambaos=newByteArrayOutputStream((content.length+size-1)/size*(size+45));intleft=0;for(inti=0;i<content.length;){left=content.length-i;if(left>size){cipher.update(content,i,size);i+=size;}else{cipher.update(content,i,left);i+=left;}baos.write(cipher.doFinal());}returnbaos.toByteArray();}catch(Exceptione){thrownewRuntimeException(e);}}publicbyte[]decrypt(byte[]secret){if(privateKey==null){thrownewRuntimeException("privatekeyisnull.");}try{Ciphercipher=Cipher.getInstance("ECIES","BC");cipher.init(Cipher.DECRYPT_MODE,privateKey);intsize=SIZE+45;ByteArrayOutputStreambaos=newByteArrayOutputStream((secret.length+size+44)/(size+45)*size);intleft=0;for(inti=0;i<secret.length;){left=secret.length-i;if

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論