1. 程式人生 > >經典混合加密系統(java實現)

經典混合加密系統(java實現)

此理論知識摘自《電子商務安全導論》一書

由於網路協議的開放行,資料在網路傳輸的過程中,難以避免的會出現安全性問題.

實際上,在一次資訊傳送過程中,可以綜合利用訊息加密、數字信封、雜湊函式和數字簽名實現安全性、完整性、可鑑別性和不可否認.具體過程如下:

(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;
    }
}