加密技術皮毛概念

上次寫網誌已經7月的事情了,這篇阿猩思考了很久,標題要怎麼下才好。密碼學跟程式息息相關,但已經跳脫出程式語言框架的領域,因此阿猩決定用「皮毛」形容此篇內容的等級,但阿猩想更進一步了解密碼學,故整理了一些學習的過程中,覺得對於工作上有幫助的內容,如有不對的想法,歡迎各位提出。

 

資料儲存單位


在查加密相關文章的過程中,會看像SHA128SHA256等加密演算法。SHA128、SHA512等演算法,除了背後的加密的演算法不同之外,其中一個重要的概念就是,依不同Size分解內文,例如SHA256會以512 bit,作為分解內文的單位。

下列為常見的資料儲存單位。
Bit 位元
電腦中最基本的儲存單位,可儲存0與1

Byte 位元組
記憶體的容量單位,1 byte = 8 bit
可用來表達英文字母、數字、特殊符號等。
例如內容=”abc”,換成ASCII為97,98,99,原始的二進制內容為011000001、01100010、01100011。

字元或字串
可以使用Notepad++,隨意輸入一些內容,例如內容共3個string,分別為「1、x、阿猩」(圖1)。
共包含4個char,「1」、「x」、「阿」、「猩」,

1 char = 1 byte,UTF-8中,中文字占用的儲存空間為3 byte
文件長度為所有內容的char,
「1」 = 1 byte
「x」 = 1 byte
「阿」= 3 byte
「猩」= 3 byte

內容為3行,故有2個隱藏的換行符號「\n」,
8 +  2*2 = 12,故文件長度為12 byte。

 

圖1

加密的類型


針對敏感資料處理時,常常會使用「加密」來描述,但加密只是密碼學中的一種處理方式。

下列為常見的機密性資料的處理方式。
Base64
是一種將字元轉為二進位資料方法(參考),再以6個bit為單位,透過Base64索引表作轉換(圖2)。
例如「abc」=> 「01100001 01100010、01100011」 => 「YWJj」
因為可逆,故通常不放敏感資料。常用於如JWT Token、傳送MP3、Image、PDF等。

圖2 Base64索引表

 

 

加密
加密演算法又可分為對稱式加密、及非對稱式加密。常見的對稱式加密類型可閱讀(參考   3.2.1章節),非對稱式加密類型可參考(參考 3.3.1章節)。

  1. 對稱式加密
    使用情境為,Client端及Server端,使用同1把Key進行加解密。所以Key須以物理方式、或其他的加密法將Key加密後做傳送。NIST文件中有提到DES,而AES可替代DES。由上述版本的文件描述,看起來目前至少到AES256是相對安全的,AES皆使用128 bit為單位對資料做分割,而AES-X則代表Key的Size。在FIPS文件中似乎也有演算法的規範,例如寫程式時會用到的設定,如ECB ModeCBC Mode等(Mode參考)
     
  2. 非對稱式加密
    常見演算法如RSA,使用情境為,每個Client端及Server端,都有一對Key,分別為Public key及Private key。例如Client要傳送資料給Server端,以Server的Public key加密,Server端收到資料後,再以Server的Private key進行解密。
     
  3. 數位簽章
    假設駭客無某一端的Private key的情況下,非對稱加密只能確保資料被攔截後,無法取得解密後的內容。若要判斷資料來源,是否真的為正確對象所送出,例如Server端,使用Client端的Public key加密之外,還要用Server端的Private key進行Hash簽名,Clinet端收到資料後,除了使用Client端的Private Key解開內容之外,也要使用Server端Public key進行簽章驗證。

 

雜湊
常見雜湊演算法如MD5SHA256SHA-512等。雜湊是根據Hash Table 轉換成對應的雜湊值,如果使用同樣的資料,以使用同樣的雜湊演算法,可得到同樣的結果。由於電腦的計算能力越來越強大,可能會遇到暴力破解,或是遇到較舊的雜湊演算法被發現碰撞的可能,故資安的要求會越來越高,如SHA-0、SHA-1已被發現可能有碰撞,SHA256屬於SHA-2,由NIST的文件看來目前尚屬安全。

 

 

程式設定注意事項


確認Key的長度
上章節提到AES-X,代表Key的長度,若使用AES-128,代表AES Key需要128 bit,換算為128bit = 16 byte,故key長度為16。阿猩看了好幾篇文章及程式範例,在.NET中無論是自寫或使用套件,幾乎都是用byte來進行設定,故會常看到程式中,會出現Encoding.UTF8.GetBytes(param),例如下列檢驗key及iv長度的程式


/// <summary>
/// 驗證key和iv的長度(AES只有三種長度適用)
/// </summary>
/// <param name="key"></param>
/// <param name="iv"></param>
private static void Validate_KeyIV_Length(string key,string iv)
{
    //驗證key和iv都必須為128bits或192bits或256bits
    List<int> LegalSizes = new List<int>() { 128, 192, 256 };
    int keyBitSize = Encoding.UTF8.GetBytes(key).Length * 8;
    int ivBitSize = Encoding.UTF8.GetBytes(iv).Length * 8;
    if (!LegalSizes.Contains(keyBitSize) || !LegalSizes.Contains(ivBitSize))
    {
        throw new Exception($@"key或iv的長度不在128bits、192bits、256bits其中一個,輸入的key bits:{keyBitSize},iv bits:{ivBitSize}");
    }
}

 

CipherMode
原ECB Mode中,加密內容與金鑰相同時,得到的密文也是相同的。故在CBC Mode中,引入了 IV(Initialiaztion Vector)的概念,在第一組明文加密前,先使用IV進行處理,後續明文分組,則根據前一組密文進行處理。

 

PaddingMode
因明文轉成byte後,並不一定會剛好符合演算的block大小,若不足則會進行補值,PaddingMode就是用來設定補值的方法,如PKCS5、PKCS7(參考1參考2)

程式碼中應該可以找到類似下列的設定    

Aes aes = Aes.Create();
aes.Mode = CipherMode.CBC; 
aes.Padding = PaddingMode.PKCS7;

 

SHA 演算法
其實程式使用邏輯與上述AES大同小異,就是指定演算法後,將明文資料轉byte後,塞進SHA函數內,即可得到SHA值。.
net 中可使用System.Security.Cryptography;