常見的加密算法
基本的單向加密算法:
BASE64嚴格地說,屬於編碼格式,而非加密算法
MD5(MessageDigestalgorithm5,信息摘要算法)
SHA(SecureHashAlgorithm,安全散列算法)
HMAC(HashMessageAuthenticationCode,散列消息鑑別碼)
複雜的對稱加密(DES、PBE)、非對稱加密算法:
DES(DataEncryptionStandard,數據加密算法)
PBE(Password-basedencryption,基於密碼驗證)
RSA(算法的名字以發明者的名字命名:RonRivest,AdiShamir和LeonardAdleman)
DH(Diffie-Hellman算法,密鑰一致協議)
DSA(DigitalSignatureAlgorithm,數字簽名)
ECC(EllipticCurvesCryptography,橢圓曲線密碼編碼學)
數字簽名
算法簡述
數字簽名算法可以看做是一種帶有密鑰的消息摘要算法,並且這種密鑰包含了公鑰和私鑰。也就是說,數字簽名算法是非對稱加密算法和消息摘要算法的結合體。
特點
數字簽名算法要求能夠驗證數據完整性、認證數據來源,並起到抗否認的作用。
原理
數字簽名算法包含簽名和驗證兩項操作,遵循私鑰簽名,公鑰驗證的方式。
簽名時要使用私鑰和待簽名數據,驗證時則需要公鑰、簽名值和待簽名數據,其核心算法主要是消息摘要算法。
1. 消息摘要
String beforeDegist = "asdf"; System.out.println("摘要前:"+beforeDegist); //初始信息要轉換成字節流的形式byte[] plainText = beforeDegist.getBytes("UTF8"); //使用getInstance("算法")來獲得消息摘要,這裡使用SHA-1的160位算法或者MD5算法geDigest messageDigest = MessageDigest.getInstance("SHA-1"); MessageDigest messageDigest = MessageDigest.getInstance("MD5"); System.out.println("/n" + messageDigest.getProvider().getInfo()); //開始使用算法messageDigest.update(plainText); //輸出算法運算結果String afterDegist = new String(messageDigest.digest(),"UTF8"); System.out.println("摘要後:"+afterDegist);2. 私鑰加密
/** * 此例子是對一個字符串信息,用一個私鑰(key)加密,然後在用該私鑰解密,驗證是否一致* 私鑰加密,是對稱加密* 使用對稱算法。比如:A用一個密鑰對一個文件加密,而B讀取這個文件的話,則需要和A一樣的密鑰,雙方共享一* 個私鑰(而在web環境下,私鑰在傳遞時容易被偵聽) * * 附:主要對稱算法有:DES(實際密鑰只用到56 位) * AES(支持三種密鑰長度:128、192、256位),通常首先128位,其他的還有DESede等*/ <span style="white-space: pre; "> </span>String before = "asdf"; byte[] plainText = before.getBytes("UTF8"); // STEP 1. System.out.println("Start generate AES key.");//得到一個使用AES算法的KeyGenerator的實例KeyGenerator keyGen = KeyGenerator.getInstance("AES");//定義密鑰長度128位keyGen.init(128);//通過KeyGenerator產生一個key(密鑰算法剛才已定義,為AES) Key key = keyGen.generateKey();System.out.println("Finish generating AES key="+key);//STEP 2.
//獲得一個私鑰加密類Cipher,定義Cipher的基本信息:ECB是加密方式,PKCS5Padding是填充方法Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); //System.out.println("/n" + cipher.getProvider().getInfo());//STEP 3.
// 使用私鑰加密System.out.println("/n用私鑰加密...");// 把剛才生成的key當作參數,初始化使用剛才獲得的私鑰加密類,Cipher.ENCRYPT_MODE意思是加密cipher.init(Cipher.ENCRYPT_MODE, key);//私鑰加密類Cipher進行加密,加密後返回一個字節流byte[] byte[] cipherText = cipher.doFinal(plainText);//以UTF8格式把字節流轉化為String String after1 = new String(cipherText, "UTF8");System.out.println("用私鑰加密完成:"+after1);// STEP 4.
[java] view plain copy//使用私鑰對剛才加密的信息進行解密,看看是否一致,Cipher.DECRYPT_MODE意思是解密鑰System.out.println("/n用私鑰解密...");cipher.init(Cipher.DECRYPT_MODE, key);//對剛才私鑰加密的字節流進行解密,解密後返回一個字節流byte[] byte[] newPlainText = cipher.doFinal(cipherText);String after2 = new String(newPlainText, "UTF8");System.out.println("用私鑰解密完成:"+after2);3. 公鑰加密
String before = "asdf";byte[] plainText = before.getBytes("UTF8");//產生一個RSA密鑰生成器KeyPairGenerator(顧名思義:一對鑰匙生成器) KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");//定義密鑰長度1024位keyGen.initialize(1024);//通過KeyPairGenerator產生密鑰,注意:這裡的key是一對鑰匙! ! KeyPair key = keyGen.generateKeyPair();//獲得一個RSA的Cipher類,使用公鑰加密Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");//System.out.println("/n" + cipher.getProvider().getInfo()); System.out.println("/n用公鑰加密...");//Cipher.ENCRYPT_MODE意思是加密,從一對鑰匙中得到公鑰key.getPublic() cipher.init(Cipher.ENCRYPT_MODE, key.getPublic());//用公鑰進行加密,返回一個字節流byte[] cipherText = cipher.doFinal(plainText);//以UTF8格式把字節流轉化為String String after1 = new String(cipherText, "UTF8");System.out.println("用公鑰加密完成:"+after1);//使用私鑰解密System.out.println("/n用私鑰解密...");//Cipher.DECRYPT_MODE意思是解密模式,從一對鑰匙中得到私鑰key.getPrivate() cipher.init(Cipher.DECRYPT_MODE, key.getPrivate());//用私鑰進行解密,返回一個字節流byte[] newPlainText = cipher.doFinal(cipherText);String after2 = new String(newPlainText, "UTF8");System.out.println("用私鑰解密完成:"+after2);4. 數字簽名
/** * 此例子是數字簽名的例子,使用RSA私鑰對消息摘要(這裡指的是原始數據)進行簽名,然後使用公鑰驗證簽名* * A通過使用B的公鑰加密數據後發給B,B利用B的私鑰解密就得到了需要的數據(進過B公鑰加密的數據只有B的私鑰能夠* 解開,C沒有B的私鑰,所以C解不開,但C可以使用B的公鑰加密一份數據發給B,這樣一來,問題來了,B收到的數據到* 底是A發過來的還是C發過來的呢) * 由於私鑰是唯一的,那麼A就可以利用A自己的私鑰進行加密,然後B再利用A的公鑰來解密,就可以確定:一定是A的消* 息,數字簽名的原理就基於此* * 總結:A想將目標數據傳給B,此時A需要準備1和2兩部分* 1:A使用B的公鑰將原始信息加密,以起到保密作用(只有B的私鑰能解開,其他人使用其他鑰匙都解不開,當然就保密咯) * 2:A使用A的私鑰將原始信息的摘要進行簽名,以起到接收方B確定是A發過來的作用(A用A的私鑰對目標數據的摘要進行簽* 名,然後傳給B,同時,C用C的私鑰對任意信息進行簽名也傳給B,B想接受的是A的數據(比如說一個轉帳請求),於是B * 就通過A的公鑰對接受到的兩個信息進行解密,解開的就是A(A的公鑰能且只能解開A的私鑰加密的數據)) */String before = "asdf";byte[] plainText = before.getBytes("UTF8");//形成RSA公鑰對KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");keyGen.initialize(1024);KeyPair key = keyGen.generateKeyPair();//使用私鑰簽名********************************************************** Signature sig = Signature.getInstance("SHA1WithRSA");sig.initSign(key.getPrivate());//sig對象得到私鑰//簽名對象得到原始數據sig.update(plainText);//sig對象得到原始數據(現實中用的是原始數據的摘要,摘要的是單向的,即摘要算法後無法解密) byte[] signature = sig.sign();//sig對像用私鑰對原始數據進行簽名,簽名後得到簽名signature em.out.println(sig.getProvider().getInfo());String after1 = new String(signature, "UTF8");System.out.println("/n用私鑰簽名後:"+after1);//使用公鑰驗證sig.initVerify(key.getPublic());//sig對象得到公鑰//簽名對象得到原始信息sig.update(plainText);//sig對象得到原始數據(現實中是摘要) try {if (sig.verify(signature)) {//sig對像用公鑰解密簽名signature得到原始數據(即摘要),一致則true System.out.println("簽名驗證正確!!"+new String(plainText, "UTF8"));} else {System.out.println("簽名驗證失敗!!");}}catch (SignatureException e) {System.out.println("簽名驗證失敗!!");}5. 數字證書
/** * 此例是對“數字證書”文件的操作* java平台(在機器上安裝jdk)為你提供了密鑰庫(證書庫),cmd下提供了keytool命令就可以創建證書庫* * 在運行此例前: * 在c盤目錄下創建一個證書,指定證書庫為BocsoftKeyLib,創建別名為TestCertification的一條證書,它指定用* RSA 算法生成,且指定密鑰長度為1024,證書有效期為1年* 導出證書文件為TC.cer已存於本地磁盤C:/ * 密碼是qazzaq */try {//前提:將證書庫中的一條證書導出到證書文件(我寫的例子裡證書文件叫TC.cer) //從證書文件TC.cer裡讀取證書信息CertificateFactory cf = CertificateFactory.getInstance("X.509");FileInputStream in = new FileInputStream("C:/TC.cer");//將文件以文件流的形式讀入證書類Certificate中Certificate c = cf.generateCertificate(in);System.err.println("轉換成String後的證書信息:"+c.toString());*/ //或者不用上面代碼的方法,直接從證書庫中讀取證書信息,和上面的結果一摸一樣String pass="qazzaq";FileInputStream in2=new FileInputStream("C:/BocsoftKeyLib");KeyStore ks=KeyStore.getInstance("JKS");ks.load(in2,pass.toCharArray());String alias = "TestCertification";//alias為條目的別名Certificate c=ks.getCertificate(alias);System.err.println("轉換成String後的證書信息:"+c.toString());//獲取獲取X509Certificate類型的對象,這是證書類獲取Certificate的子類,實現了更多方法X509Certificate t=(X509Certificate)c;//從信息中提取需要信息System.out.println("版本號:"+t.getVersion());System.out.println("序列號:"+t.getSerialNumber().toString(16));System.out.println("主體名:"+t.getSubjectDN());System.out.println("簽發者:"+t.getIssuerDN());System.out.println("有效期:"+t.getNotBefore());System.out.println("簽名算法:"+t.getSigAlgName());byte [] sig=t.getSignature();//簽名值PublicKey pk = t.getPublicKey();byte [] pkenc=pk.getEncoded();System.out.println("公鑰:");for (int i=0;i<pkenc.length;i++){System.out.print(pkenc[i]+",");}System.err.println();//證書的日期有效性檢查,頒發的證書都有一個有效性的日期區間Date TimeNow=new Date();t.checkValidity(TimeNow);System.out.println("證書的日期有效性檢查:有效的證書日期!");//驗證證書籤名的有效性,通過數字證書認證中心(CA)機構頒布給客戶的CA證書,比如:caroot.crt文件//我手裡沒有CA頒給我的證書,所以下面代碼執行不了/*FileInputStream in3=new FileInputStream("caroot.crt"); //獲取CA證書Certificate cac = cf.generateCertificate(in3); //獲取CA的公鑰PublicKey pbk=cac.getPublicKey(); //c為本地證書,也就是待檢驗的證書,用CA的公鑰校驗數字證書c的有效性c.verify(pbk); } catch(CertificateExpiredException e){//證書的日期有效性檢查:過期System.out.println("證書的日期有效性檢查:過期"); } catch(CertificateNotYetValidException e){ //證書的日期有效性檢查:尚未生效System.out.println("證書的日期有效性檢查:尚未生效"); } catch (CertificateException ce) { ce.printStackTrace(); } catch (FileNotFoundException fe) { fe.printStackTrace(); } /*catch (IOException ioe){ } catch (KeyStoreException kse){ }*/catch (Exception e){e.printStackTrace();}}總結
以上就是本文關於Java加密解密和數字簽名完整代碼示例的全部內容,希望對大家有所幫助。感興趣的朋友可以繼續參閱本站其他相關專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!