經典混合加密系統(java實現)
阿新 • • 發佈:2019-01-04
此理論知識摘自《電子商務安全導論》一書
由於網路協議的開放行,資料在網路傳輸的過程中,難以避免的會出現安全性問題.
實際上,在一次資訊傳送過程中,可以綜合利用訊息加密、數字信封、雜湊函式和數字簽名實現安全性、完整性、可鑑別性和不可否認.具體過程如下:
(1)傳送方A
①求明文訊息的訊息雜湊值:hA=H'(M);
②傳送方用自己的私鑰KSA對雜湊值進行數字簽名:h'=EKSA (hA);
③將明文M和數字簽名h'合併為M',M'=【M h'】;
④隨機產生—個DES金鑰KDES;
⑤用DES金鑰KDES加密M',C1=EKDES( M');
⑥用接受方B的公鑰加密DES金鑰,C2=EKPB(KDES)。
A將C1和C2傳送給接受方B。
(2)接受方B
接受方B收到訊息後:
①B用其私鑰開啟數字信封,得到傳送方的DES金鑰,KDES=DKSB( C2);
②再用此金鑰去解密訊息C1,M'=DKDES( C1);
③從M’中分離出M和h’;
④求明文訊息的訊息雜湊值,hB=H(M);
⑤對A的數字簽名h’進行身份驗證,hA=DKPA (h’);
⑥比較hA和hB,如hA=hB,則說明M確是A傳送的訊息,如hA≠hB,則收到的M是不可信的。這就是資料完整性檢驗。
鑑於以上的原理設計一套java程式碼,下載地址
核心程式碼如下:
package com.rzl.gateway.commons.mixencrypt; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; /** * 混合加密工具類 * * @author gui * @create 2018-12-07 9:30 **/ public class MixEncryptUtils { private static final String splitFlag = "#@#"; /** * 混合加密方法-訊息傳送者 * @param plaintext 加密明文 * @param privateKeyA 傳送者A私鑰 * @param publicKeyB 接受者B公鑰 * @return * @throws Exception */ public static String encrypt(String plaintext,String privateKeyA,String publicKeyB) throws Exception{ //求明文訊息的訊息雜湊值:hA=H'(M) String hA = EncryptMd5Util.MD5Encode(plaintext,"UTF-8"); //傳送方用自己的私鑰KSA對雜湊值進行數字簽名:h'=EKSA (hA) RSAPrivateKey rsaPrivateKey = RSAUtils.getPrivateKey(privateKeyA); String hASign = RSAUtils.privateEncrypt(hA,rsaPrivateKey); //將明文M和數字簽名h'合併為M',M'=【M h'】 StringBuilder mixPlaintext = new StringBuilder(plaintext); mixPlaintext.append(splitFlag + hASign); //隨機產牛—個DES金鑰KDES String DESKey = EncryptMd5Util.getUUID(); //用DES金鑰KDES加密M',C1=EKDES( M') String c1 = DESUtils.encrypt(mixPlaintext.toString(),DESKey); //用接受方B的公鑰加密DES金鑰,C2=EKPB(KDES) String c2 = RSAUtils.publicEncrypt(DESKey,RSAUtils.getPublicKey(publicKeyB));// DESUtils.encrypt(DESKey,publicKeyB); StringBuilder message = new StringBuilder(c1); message.append(splitFlag + c2); return message.toString(); } public static String decrypt(String ciphertext,String privateKeyB,String publicKeyA) throws Exception{ String[] c1c2 = ciphertext.split(splitFlag); String c1= c1c2[0]; String c2=c1c2[1]; //B用其私鑰開啟數字信封,得到傳送方的DES金鑰,KDES=DKSB( C2) RSAPrivateKey rsaPrivateKeyB = RSAUtils.getPrivateKey(privateKeyB); String desKey = RSAUtils.privateDecrypt(c2,rsaPrivateKeyB); //再用此金鑰去解密訊息C1,M'=DKDES( C1) String c1Message = DESUtils.decrypt(c1,desKey); //從M’中分離出M和h’ String[] Mh = c1Message.split(splitFlag); String M = Mh[0]; //明文 String h = Mh[1]; //求明文訊息的訊息雜湊值,hB=H(M) String hB = EncryptMd5Util.MD5Encode(M,"UTF-8"); //對A的數字簽名h’進行身份驗證,hA=DKPA (h’) RSAPublicKey hAPublicKey = RSAUtils.getPublicKey(publicKeyA); String hA = RSAUtils.publicDecrypt(h,hAPublicKey); if (!hA.equals(hB)){ throw new MixEncrypteException("數字簽名不一致,資料被篡改!"); } return M; } }