Linux Kernel(Android) 加密算法總結(一)(cipher、compress、digest)

1. Linux內核支持哪些加密算法 ?php

    內核支持的加密算法很是多,包含:html

    對稱加密算法。如AES,3DES。linux

    對稱password體制的發展趨勢將以分組password爲重點。算法

分組password算法一般由密鑰擴展算法和加密(解密)算法兩部分組成。密鑰擴展算法將b字節用戶主密鑰擴展成r個子密鑰。安全

加密算法由一個password學上的弱函數f與r個子密鑰迭代r次組成。混亂和密鑰擴散是分組password算法設計的基本原則。網絡

抵禦已知明文的差分和線性攻擊,可變長密鑰和分組是該體制的設計要點。  AES是美國國家標準技術研究所NIST旨在代替DES的21世紀的加密標準。框架

  AES的基本要求是。採用對稱分組password體制,密鑰長度的最少支持爲12八、19二、256,分組長度128位。算法應易於各類硬件和軟件實現。1998年NIST開始AES第一輪分析、測試和徵集,共產生了15個候選算法。函數

1999年3月完畢了第二輪AES2的分析、測試。2000年10月2日美國政府正式宣佈選中比利時password學家Joan Daemen 和 Vincent Rijmen 提出的一種password算法RIJNDAEL 做爲 AES.   在應用方面,雖然DES在安全上是脆弱的,但由於高速DES芯片的大量生產,使得DES仍能臨時繼續使用。爲提升安全強度,一般使用獨立密鑰的三級DES。但是DES早晚要被AES取代。流password體制較之分組password在理論上成熟且安全,但未被列入下一代加密標準。 工具


    摘要算法,如sha1,md5。oop

    數據摘要算法是password學算法中很重要的一個分支,它經過對所有數據提取指紋信息以實現數據簽名、數據完整性校驗等功能,由於其不可逆性。有時候會被用作敏感信息的加密。

數據摘要算法也被稱爲哈希(Hash)算法或散列算法。

     SHA(Secure Hash Algorithm)是由美國專門制定password算法的標準機構—— 美國國家標準技術研究院(NIST)制定的。SHA系列算法的摘要長度分別爲:SHA爲20字節(160位)、SHA256爲32字節(256位)、 SHA384爲48字節(384位)、SHA512爲64字節(512位)。由於它產生的數據摘要的長度更長。所以更難以發生碰撞,所以也更爲安全,它是將來數據摘要算法的發展方向。由於SHA系列算法的數據摘要長度較長,所以其運算速度與MD5相比。也相對較慢。

眼下SHA1的應用較爲普遍,主要應用於CA和數字證書中,另外在眼下互聯網中流行的BT軟件中,也是使用SHA1來進行文件校驗的。

MD5(Message-Digest Algorithm 5,消息摘要算法版本號5)。它由MD二、MD三、MD4發展而來,由Ron Rivest(RSA公司)在1992年提出,眼下被普遍應用於數據完整性校驗、數據(消息)摘要、數據加密等。

MD二、MD四、MD5 都產生16字節(128位)的校驗值,通常用32位十六進制數表示。MD2的算法較慢但相對安全。MD4速度很是快,但安全性降低,MD5比MD4更安全、速度更快。

眼下在互聯網上進行大文件傳輸時。都要得用MD5算法產生一個與文件匹配的、存儲MD5值的文本文件(後綴名爲 .md5或.md5sum),這樣接收者在接收到文件後,就可以利用與 SFV 相似的方法來檢查文件完整性。眼下絕大多數大型軟件公司或開源組織都是以這樣的方式來校驗數據完整性,而且部分操做系統也使用此算法來對用戶password進行加密,另外,它也是眼下計算機犯罪中數據取證的最常用算法。


     壓縮算法。如deflate。

 

     DEFLATE是同一時候使用了LZ77算法與哈夫曼編碼(Huffman Coding)的一個無損數據壓縮算法。它最初是由Phil Katz爲他的PKZIP歸檔工具第二版所定義的。後來定義在RFC 1951規範中。

        人們廣泛以爲DEFLATE不受不論什麼專利所制約,並且在LZWGIF文件格式使用)相關的專利失效以前,這樣的格式除了在ZIP文件格式中獲得應用以外也在gzip壓縮文件以及PNG圖像文件裏獲得了應用。

        DEFLATE壓縮與解壓的源碼可以在自由、通用的壓縮庫zlib上找到。


    只是內核好像不支持非對稱加密算法。


2. 加密算法源文件位置

     這些算法做爲加密函數框架的最底層。提供加密和解密的實際操做。這些函數可以在內核crypto目錄下,對應的文件裏找到。


3.  配置編譯選項將加密算法做爲模塊編入內核

   

Cryptographic options
加密選項

Cryptographic API
    提供核心的加密API支持.這裏的加密算法被普遍的應用於驅動程序通訊協議等機制中.子選項可以全不選,內核中如有其它部分依賴它,會本身主動選上

    Cryptographic algorithm manager
        建立加密模版實例,必須要選

    HMAC support
        爲IPSec所必須,可爲PPPoE提供壓縮支持
    Null algorithms
        NULL加密算法(什麼也不作),用於IPsec協議的封裝安全載荷模塊(ESP)
    MD4 digest algorithm
        老舊的摘要算法,已通過時
    MD5 digest algorithm
        主流摘要算法,128位(已被中國山東大學王小云攻破,可以高速找到碰撞)
    SHA1 digest algorithm
        主流摘要算法,160位(已被中國山東大學王小云攻破,可以高速找到碰撞),速度與MD5至關
    SHA256 digest algorithm
        更好的摘要算法,256位,速度較SHA1稍慢

    SHA384 and SHA512 digest algorithms
        更好的摘要算法,384/512位,速度大約僅僅有SHA1的40-50%
    Whirlpool digest algorithms
        最安全的摘要算法,512位,已被列入ISO標準,眼下最新版本號爲3.0(2003年公佈)
    Tiger digest algorithms
        號稱最快的摘要算法,192位,專門爲64位CPU進行了優化
    ECB support
        電子password本,最簡單的加密方法
    CBC support
        password塊鏈,IPSec需要使用它
    DES and Triple DES EDE cipher algorithms
        老邁的(DES)和尚佳的(Triple DES)對稱加密算法
    Blowfish cipher algorithm
        又老又慢的對稱加密算法
    Twofish cipher algorithm
        很是強的對稱加密算法,使用較廣
    Twofish cipher algorithms (i586)
        很是強的對稱加密算法,使用較廣(針對i586的版本號)
    Serpent cipher algorithm
        很是強的對稱加密算法
    AES cipher algorithms
        最佳的對稱加密算法(Rijndael),128/192/256位,強度最高,高速且節省內存

    AES cipher algorithms (i586)
        最佳的對稱加密算法(Rijndael),128/192/256位,強度最高,高速且節省內存(針對i586的版本號)
    CAST5 (CAST-128) cipher algorithm
        對稱加密算法
    CAST6 (CAST-256) cipher algorithm
        對稱加密算法
    TEA, XTEA and XETA cipher algorithms
        較弱的對稱加密算法
    ARC4 cipher algorithm
        脆弱的流對稱加密算法
    Khazad cipher algorithm
        對稱加密算法
    Anubis cipher algorithm
        對稱加密算法
    Deflate compression algorithm
        壓縮算法,當在IPSec中使用IPCOMP協議時才需要

    Michael MIC keyed digest algorithm
        摘要算法,只用於校驗iSCSI設備傳輸的數據,因爲算法自己比較脆弱
    CRC32c CRC algorithm
        摘要算法,可用於校驗iSCSI設備傳輸的數據
    Testing module
        高速且醜陋的測試模塊
    Hardware crypto devices
        僅有VIA C7系列處理器支持硬件加密(VIA PadLock高級加密引擎)


參考:

    CryptoAPI support


     提供核心的加密API支持.這裏的加密算法被普遍的應用於驅動程序通訊協議等機制上,子選項可以全不選,內核中如有其它部分依賴它。會本身主動選

      (M)Cipher Algorithms

    建立加密模版實例。必須要選

     -- 128 bit blocksize

         (M) AES (aka Rijndael) cipher

         (M) Identity Function cipher

         (M) Crypto Devices

          (M) Loop Crypto support

4.  加密API 的調用方法:

    只是內核模塊不能直接調用這些函數。因爲它們並無export。內核提供一個統一的框架,來管理這些算法。

      加密算法經過crypto_register_alg()和crypto_unregister_alg()註冊。

      內核將加密算法分爲三類,1)cipher,2)compress,3)digest。

        加密函數框架中有對應的API封裝,提供給模塊調用。

對於使用這些加密函數,首先經過crypto_alloc_tfm()來分配一個加密函數對象的實例。初始化這些實例,而後就可以經過框架提供的API對數據進行加密和解密。

完畢之後。必須經過crypto_free_tfm()撤銷實例。



5.  代碼演示樣例:


1)digest算法(sha1)
#include<linux/kernel.h>
#include <linux/module.h>
#include <linux/crypto.h>
#include <linux/scatterlist.h>
#include <linux/gfp.h>
#include <linux/err.h>
#include <linux/syscalls.h>
#include <linux/slab.h>

struct crypto_tfm *tfm;
struct scatterlist sg[1];
char * code1="234123132513451345";
char * code2="234123132513451345";

char *do_digest(char* code){
    char *result;
    int code_len =strlen(code);
   
        tfm = crypto_alloc_tfm("sha1",0);
        if(IS_ERR(tfm))
                return 0;
        sg_init_one(sg,code,code_len);

        crypto_digest_init(tfm);
        crypto_digest_update(tfm,sg,1);
    result = (char*)kmalloc(sizeof(char)*50,GFP_KERNEL);

    if(result == NULL) {
        crypto_free_tfm(tfm);
        return 0;
    }
    memset(result,0,sizeof(char)*50);
    crypto_digest_final(tfm,result);
        crypto_free_tfm(tfm);
    return result;
}

static int __init test_init(void)
{
    char *result1,*result2;
    result1 = do_digest(code1);
    if(!result1)
        goto failed2;
    result2 = do_digest(code2);
    if(!result2)
        goto failed1;
   
    if(memcmp(result1,result2,50)!= 0)
        printk("<1>code1 != code2\n");
    else
        printk("<1>code1 == code2\n");
    kfree(result2);

failed1:
    kfree(result1);
failed2:
    return 0;
}

static void __exit test_exit(void)
{

}

module_init(test_init);
module_exit(test_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("robert@cm");


2)compress算法(deflate)
#include<linux/module.h>
#include <linux/kernel.h>
#include <linux/crypto.h>
#include <linux/scatterlist.h>
#include <linux/gfp.h>
#include <linux/err.h>
#include <linux/syscalls.h>
#include <linux/slab.h>

struct crypto_tfm *tfm;
char * code="Hello everyone, I'm robert from cm !";


static inline  void hexdump(unsignedchar*buf,unsignedint len){
    while(len--)
        printk("0x%02x,",*buf++);
    printk("\n");
}

static int __init test_init(void){
    int ret,result_len,temp_len;
    char result[512];
    char temp[512];

    printk("<1>%s\n",code);   
   
    /* Allocate transform for deflate */
            
    tfm = crypto_alloc_tfm("deflate",0);
        if(IS_ERR(tfm)){
        printk("<1>failed to load transform for deflate !\n");
                return 0;
    }

    memset(result,0,sizeof(result));

    temp_len = 512;
    ret = crypto_comp_compress(tfm,code,strlen(code),temp,&temp_len);
    if(ret){
        printk("<1>failed to compress !\n");
        return 0;
    }
      
    hexdump(temp,strlen(temp));
   
    memset(result,0,sizeof(result));

    result_len = 512;
    ret = crypto_comp_decompress(tfm,temp,strlen(temp),result,&result_len);
    if(ret){
                printk("<1>failed to decompress !\n");
                return 0;
        }

    printk("<1>%s\n",result);

    if(memcmp(code,result,strlen(code))!= 0)
        printk("<1>decompressed was not successful\n");
    else
        printk("<1>decompressed was successful\n");

           crypto_free_tfm(tfm);
    return 0;
}

static void __exit test_exit(void)
{

}

module_init(test_init);
module_exit(test_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("robert@cm");


3)cipher算法(aes)
#include<linux/module.h>
#include <linux/kernel.h>
#include <linux/crypto.h>
#include <linux/scatterlist.h>
#include <linux/gfp.h>
#include <linux/err.h>
#include <linux/syscalls.h>
#include <linux/slab.h>
#include <linux/highmem.h>

struct crypto_tfm *tfm;
#if 1
char *code = "Hello everyone,I'm robert"
        "Hello everyone,I'm robert"
            "Hello everyone,I'm robert";

char *key = "00112233445566778899aabbccddeeff";
#endif

#if 0
char code[]={0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,
        0xbb,0xcc,0xdd,0xee,0xff};
char key[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,
        0x0b,0x0c,0x0d,0x0e,0x0f};
#endif

static inline  void hexdump(unsignedchar*buf,unsignedint len){
    while(len--)
        printk("%02x",*buf++);
    printk("\n");
}

static int __init test_init(void){
    int ret,templen,keylen,codelen;
    struct scatterlist sg[1];
    char *result;
    char *temp;

    keylen = 16;
    codelen = strlen(code)/2;
#if 0
    printk("<1>%s, codelen=%d\n",code,strlen(code));
    printk("<1>%s, keylen=%d\n",key,strlen(key));   
#endif   
    /* Allocate transform for AES ECB mode */
            
    tfm = crypto_alloc_tfm("aes",CRYPTO_TFM_MODE_ECB);
        if(IS_ERR(tfm)){
        printk("<1>failed to load transform for aes ECB mode !\n");
                return 0;
    }

    ret = crypto_cipher_setkey(tfm,key,keylen);
    if(ret){
        printk("<1>failed to setkey \n");
        goto failed1;
    }
   
    sg_init_one(sg,code,codelen);
        
    /* start encrypt */
   
    ret = crypto_cipher_encrypt(tfm,sg,sg,codelen);
    if(ret){
        printk("<1>encrypt failed \n");
        goto failed1;
    }
   
    temp = kmap(sg[0].page)+ sg[0].offset;

    hexdump(temp,sg[0].length);
   
          /* start dencrypt */
    templen = strlen(temp)/2;
    sg_init_one(sg,temp,templen);
    ret = crypto_cipher_decrypt(tfm,sg,sg,templen);
        if(ret){
                printk("<1>dencrypt failed \n");
                goto failed1;
        }

        result = kmap(sg[0].page)+ sg[0].offset;
    printk("<1>%s\n",result);
//        hexdump(result,sg[0].length);


#if 0
    if(memcmp(code,result,strlen(code))!= 0)
        printk("<1>dencrpt was not successful\n");
    else
        printk("<1>dencrypt was successful\n");
#endif
failed1:
           crypto_free_tfm(tfm);
    return 0;
}

static void __exit test_exit(void)
{

}

module_init(test_init);
module_exit(test_exit);

MODULE_LICENSE("GPL");

MODULE_AUTHOR("robert@cm");  

部分採用網絡代碼。

相關文章
相關標籤/搜索