1. 程式人生 > 其它 >安全架構-加密演算法-對稱加密

安全架構-加密演算法-對稱加密

技術標籤:安全架構安全架構師對稱加密DES3Des

安全架構-加密演算法-對稱加密

本系列安全架構文章中,之前談到了api介面簽名防止資料篡改,但是關鍵資料在通訊過程中是不能明文傳遞的,這就涉及到另外的安全問題,資料加密傳輸。


加密演算法根據加密祕鑰的不同分為對稱加密和非對稱加密。加密和解密使用同一個祕鑰時,稱之為 對稱加密。加密和解密使用不同的祕鑰時,稱之為非對稱加密,如使用金鑰對裡的公鑰加密,私鑰解密。本文介紹對稱加密演算法,後續文章再來介紹非對稱加密。

文章目錄


前言

對稱加密演算法是應用較早的加密演算法,技術成熟。在對稱加密演算法中,資料發信方將明文(原始資料)和加密金鑰(mi yao)一起經過特殊加密演算法處理後,使其變成複雜的加密密文傳送出去。收信方收到密文後,若想解讀原文,則需要使用加密用過的金鑰及相同演算法的逆演算法對密文進行解密,才能使其恢復成可讀明文。在對稱加密演算法中,使用的金鑰只有一個,發收信雙方都使用這個金鑰對資料進行加密和解密,這就要求解密方事先必須知道加密金鑰。


一、簡介

指加密和解密使用相同金鑰的加密演算法。對稱加密演算法的優點在於加解密的高速度和使用長金鑰時的難破解性。

二、特點

對稱加密演算法的特點是演算法公開、計算量小、加密速度快、加密效率高。

假設兩個使用者需要使用對稱加密方法加密然後交換資料,則使用者最少需要2個金鑰並交換使用,如果企業內使用者有n個,則整個企業共需要n×(n-1) 個金鑰,金鑰的生成和分發將成為企業資訊部門的惡夢。

對稱加密演算法的安全性取決於加密金鑰的儲存情況,但要求企業中每一個持有金鑰的人都保守祕密是不可能的,他們通常會有意無意的把金鑰洩漏出去——如果一個使用者使用的金鑰被入侵者所獲得,入侵者便可以讀取該使用者金鑰加密的所有文件,如果整個企業共用一個加密金鑰,那整個企業文件的保密性便無從談起。

三、常見演算法

常見的對稱加密演算法:DES、3DES、DESX、Blowfish、IDEA、RC4、RC5、RC6和AES;

3DES其實是做三次DES。

最常用的:

DES(Data Encryption Standard):資料加密標準,速度較快,適用於加密大量資料的場合;

3DES(Triple DES):是基於DES,對一塊資料用三個不同的金鑰進行三次加密,強度更高;

AES(Advanced Encryption Standard):高階加密標準,是下一代的加密演算法標準,速度快,安全級別高。

四、加密填充模式

加密模式(英文名稱及簡寫) 中文名稱
Electronic Code Book(ECB) 電子密碼本模式
Cipher Block Chaining(CBC) 密碼分組連結模式
Cipher Feedback Mode(CFB) 加密反饋模式
Output Feedback Mode(OFB) 輸出反饋模式

ECB:最基本的加密模式,也就是通常理解的加密,相同的明文將永遠加密成相同的密文,無初始向量,容易受到密碼本重放攻擊,一般情況下很少用。

CBC:明文被加密前要與前面的密文進行異或運算後再加密,因此只要選擇不同的初始向量,相同的密文加密後會形成不同的密文,這是目前應用最廣泛的模式。CBC加密後的密文是上下文相關的,但明文的錯誤不會傳遞到後續分組,但如果一個分組丟失,後面的分組將全部作廢(同步錯誤)。

CFB:類似於自同步序列密碼,分組加密後,按8位分組將密文和明文進行移位異或後得到輸出同時反饋回移位暫存器,優點最小可以按位元組進行加解密,也可以是n位的,CFB也是上下文相關的,CFB模式下,明文的一個錯誤會影響後面的密文(錯誤擴散)。

OFB:將分組密碼作為同步序列密碼執行,和CFB相似,不過OFB用的是前一個n位密文輸出分組反饋回移位暫存器,OFB沒有錯誤擴散問題。

五、加密演算法的選擇

由於非對稱加密演算法的執行速度比對稱加密演算法的速度慢很多,當我們需要加密大量的資料時,建議採用對稱加密演算法,提高加解密速度。

對稱加密演算法不能實現簽名,因此簽名只能非對稱演算法。

由於對稱加密演算法的金鑰管理是一個複雜的過程,金鑰的管理直接決定著他的安全性,因此當資料量很小時,我們可以考慮採用非對稱加密演算法。

在實際的操作過程中,我們通常採用的方式是:採用非對稱加密演算法管理對稱演算法的金鑰,然後用對稱加密演算法加密資料,這樣我們就集成了兩類加密演算法的優點,既實現了加密速度快的優點,又實現了安全方便管理金鑰的優點。

那採用多少位的金鑰呢? RSA建議採用1024位的數字,ECC建議採用160位,AES採用128為即可。

六、加密演算法的實現

各技術棧都有相對應演算法的完善的類庫

.NET

 /// <summary>
        /// DES加密
        /// </summary>
        /// <param name="source">要加密的源字串</param>
        /// <param name="key">公鑰</param>
        /// <returns></returns>
        public static string Encrypt(string source, string key)
        {
            DESCryptoServiceProvider provider = new DESCryptoServiceProvider();
            provider.Key = Encoding.ASCII.GetBytes(key);
            provider.IV = Encoding.ASCII.GetBytes(key);
            byte[] bytes = Encoding.GetEncoding("GB2312").GetBytes(source);
            MemoryStream stream = new MemoryStream();
            CryptoStream stream2 = new CryptoStream(stream, provider.CreateEncryptor(), CryptoStreamMode.Write);
            stream2.Write(bytes, 0, bytes.Length); stream2.FlushFinalBlock();
            StringBuilder builder = new StringBuilder(); foreach (byte num in stream.ToArray())
            {
                builder.AppendFormat("{0:X2}", num);
            }
            stream.Close();
            return builder.ToString().ToByteArray().ToHexString();
        }

DESCryptoServiceProvider provider = new DESCryptoServiceProvider();
可指定對應的padding和mode.

      provider.Padding = PaddingMode.None;
      provider.Mode = CipherMode.CBC;

JAVA實現

/**
     * 偏移變數,固定佔8位位元組
     */
    private final static String IV_PARAMETER = "12345678";
    /**
     * 金鑰演算法
     */
    private static final String ALGORITHM = "DES";
    /**
     * 加密/解密演算法-工作模式-填充模式
     */
    private static final String CIPHER_ALGORITHM = "DES/CBC/PKCS5Padding";
    /**
     * 預設編碼
     */
    private static final String CHARSET = "utf-8";
 
    /**
     * 生成key
     *
     * @param password
     * @return
     * @throws Exception
     */
    private static Key generateKey(String password) throws Exception {
        DESKeySpec dks = new DESKeySpec(password.getBytes(CHARSET));
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
        return keyFactory.generateSecret(dks);
    }
 
 
    /**
     * DES加密字串
     *
     * @param password 加密密碼,長度不能夠小於8位
     * @param data 待加密字串
     * @return 加密後內容
     */
    public static String encrypt(String password, String data) {
        if (password== null || password.length() < 8) {
            throw new RuntimeException("加密失敗,key不能小於8位");
        }
        if (data == null)
            return null;
        try {
            Key secretKey = generateKey(password);
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            IvParameterSpec iv = new IvParameterSpec(IV_PARAMETER.getBytes(CHARSET));
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
            byte[] bytes = cipher.doFinal(data.getBytes(CHARSET));
 
            //JDK1.8及以上可直接使用Base64,JDK1.7及以下可以使用BASE64Encoder
            //Android平臺可以使用android.util.Base64
            return new String(Base64.getEncoder().encode(bytes));
 
        } catch (Exception e) {
            e.printStackTrace();
            return data;
        }
    }
 
    /**
     * DES解密字串
     *
     * @param password 解密密碼,長度不能夠小於8位
     * @param data 待解密字串
     * @return 解密後內容
     */
    public static String decrypt(String password, String data) {
        if (password== null || password.length() < 8) {
            throw new RuntimeException("加密失敗,key不能小於8位");
        }
        if (data == null)
            return null;
        try {
            Key secretKey = generateKey(password);
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            IvParameterSpec iv = new IvParameterSpec(IV_PARAMETER.getBytes(CHARSET));
            cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
            return new String(cipher.doFinal(Base64.getDecoder().decode(data.getBytes(CHARSET))), CHARSET);
        } catch (Exception e) {
            e.printStackTrace();
            return data;
        }
    }
 

總結

本篇簡要介紹加密演算法中的對稱加密,對稱加密中的DES,3DES,AES用的比較廣泛,可以在後續文章中深度解讀。

參考資料:
https://my.oschina.net/u/4277503/blog/4647838