• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • 用CryptoAPI進行數據加密

    發表于:2007-07-14來源:作者:點擊數: 標簽:
    南京理工大學計算機系 胡靜 李蔚清 ---- 因為過于復雜的加密算法實現起來非常困難,所以在過去,許多應用程序只能使用非常簡單的加密技術,這樣做的結果就是加密的數據很容易就可以被人破譯。而使用Microsoft提供的加密應用程序接口(即Cryptography API),
    南京理工大學計算機系 胡靜 李蔚清  

    ---- 因為過于復雜的加密算法實現起來非常困難,所以在過去,許多應用程序只能使用非常簡單的加密技術,這樣做的結果就是加密的數據很容易就可以被人破譯。而使用Microsoft提供的加密應用程序接口(即Cryptography API),或稱CryptoAPI,就可以方便地在應用程序中加入強大的加密功能,而不必考慮基本的算法。本文將對CryptoAPI及其使用的數據加密原理作一簡單的介紹,然后給出了用CryptoAPI編寫加密程序的大致步驟,最后以一個文件的加密、解密程序為例演示了CryptoAPI的部分功能。

    ---- 1. CryptoAPI簡介

    ---- CryptoAPI是一組函數,為了完成數學計算,必須具有密碼服務提供者模塊(CSP)。Microsoft通過捆綁RSA Base Provider在操作系統級提供一個CSP,使用RSA公司的公鑰加密算法,更多的CSP可以根據需要增加到應用中。事實上,CSP有可能與特殊硬件設備(如智能卡)一起來進行數據加密。CryptoAPI接口允許簡單的函數調用來加密數據,交換公鑰,散列一個消息來建立摘要以及生成數字簽名。它還提供高級的管理操作,如從一組可能的CSP中使用一個CSP。此外,CryptoAPI還為許多高級安全性服務提供了基礎,包括用于電子商務的SET,用于加密客戶機/服務器消息的PCT,用于在各個平臺之間來回傳遞機密數據和密鑰的PFX,代碼簽名等等。

    ---- 目前支持CryptoAPI的Windows系統有:Windows 95 OSR2、Windows NT SP3及后續版本、Windows 98、Windows 2000等。CryptoAPI的配置信息存儲在注冊表中,包括如下密鑰:

    HKEY_LOCAL_MACHINE\SOFTWARE\
    Microsoft \ Cryptography \Defaults
    HKEY_CURRENT_USER\ Software \ Microsoft
    \ Cryptography \Providers

    ---- 2.數據加密原理

    ---- CryptoAPI使用兩種密鑰:會話密鑰與公共/私人密鑰對。會話密鑰使用相同的加密和解密密鑰,這種算法較快,但必須保證密鑰的安全傳遞。公共/私人密鑰對使用一個公共密鑰和一個私人密鑰,私人密鑰只有專人才能使用,公共密鑰可以廣泛傳播。如果密鑰對中的一個用于加密,另一個一定用于解密。公共/私人密鑰對算法很慢,一般只用于加密小批數據,例如用于加密會話密鑰。

    ---- CryptoAPI支持兩種基本的編碼方法:流式編碼和塊編碼。流式編碼在明碼文本的每一位上創建編碼位,速度較快,但安全性較低。塊編碼在一個完整的塊上(一般為64位)上工作,需要使用填充的方法對要編碼的數據進行舍入,以組成多個完整的塊。這種算法速度較慢,但更安全。

    ---- 3.應用舉例

    ---- 下面以兩個文件加密與解密的C程序片斷為例,演示一下CryptoAPI的強大功能。這兩個程序均為Win32控制臺應用,程序省略了出錯處理,實際運行時請加入。

    ---- ①文件加密

    #include < windows.h >
    #include < stdio.h >
    #include < stdlib.h >
    #include < wincrypt.h >

    //確定使用RC2塊編碼或是RC4流式編碼
    #ifdef USE_BLOCK_CIPHER
    #define ENCRYPT_ALGORITHMCALG_RC2
    #define ENCRYPT_BLOCK_SIZE8
    #else
       #define ENCRYPT_ALGORITHMCALG_RC4
       #define ENCRYPT_BLOCK_SIZE1
    #endif

    void CAPIDecryptFile(PCHAR szSource,
    PCHAR szDestination, PCHAR szPassword);

    void _cdecl main(int argc, char *argv[])
    {
    PCHAR szSource= NULL;
    PCHAR szDestination = NULL;
    PCHAR szPassword= NULL;

    // 驗證參數個數
    if(argc != 3 && argc != 4) {
    printf("USAGE: decrypt < source file >
    < dest file > [ < password > ]\n");
    exit(1);
    }

    //讀取參數.
    szSource   = argv[1];
    szDestination  = argv[2];
    if(argc == 4) {
    szPassword = argv[3];
    }
    CAPIDecryptFile(szSource, szDestination, szPassword);
    }

    /*szSource為要加密的文件名稱,szDestination
    為加密過的文件名稱,szPassword為加密口令*/
    void CAPIEncryptFile(PCHAR szSource, PCHAR
    szDestination, PCHAR szPassword)
    {
    FILE *hSource  = NULL;
    FILE *hDestination = NULL;
    INT eof = 0;
    HCRYPTPROV hProv   = 0;
    HCRYPTKEY hKey = 0;
    HCRYPTKEY hXchgKey = 0;
    HCRYPTHASH hHash   = 0;
    PBYTE pbKeyBlob = NULL;
    DWORD dwKeyBlobLen;
    PBYTE pbBuffer = NULL;
    DWORD dwBlockLen;
    DWORD dwBufferLen;
    DWORD dwCount;

    hSource = fopen(szSource,"rb"));// 打開源文件.
    hDestination = fopen(szDestination,"wb") ;
    //.打開目標文件
       // 連接缺省的CSP
    CryptAcquireContext(&hProv, NULL, NULL,
    PROV_RSA_FULL, 0));
    if(szPassword == NULL) {
    //口令為空,使用隨機產生的會話密鑰加密
    // 產生隨機會話密鑰.
    CryptGenKey(hProv, ENCRYPT_ALGORITHM,
    CRYPT_EXPORTABLE, &hKey)
    // 取得密鑰交換對的公共密鑰
    CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hXchgKey);
    // 計算隱碼長度并分配緩沖區
    CryptExportKey(hKey, hXchgKey, SIMPLEBLOB, 0,
    NULL, &dwKeyBlobLen);
    pbKeyBlob = malloc(dwKeyBlobLen)) == NULL) ;
    // 將會話密鑰輸出至隱碼
    CryptExportKey(hKey, hXchgKey, SIMPLEBLOB,
    0, pbKeyBlob, &dwKeyBlobLen));
    // 釋放密鑰交換對的句柄
    CryptDestroyKey(hXchgKey);
    hXchgKey = 0;
    // 將隱碼長度寫入目標文件
    fwrite(&dwKeyBlobLen, sizeof(DWORD), 1, hDestination);
    //將隱碼長度寫入目標文件
    fwrite(pbKeyBlob, 1, dwKeyBlobLen, hDestination);
    } else {
    //口令不為空, 使用從口令派生出的密鑰加密文件
    CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
    // 建立散列表
    CryptHashData(hHash, szPassword, strlen(szPassword), 0);
    //散列口令
    // 從散列表中派生密鑰
    CryptDeriveKey(hProv, ENCRYPT_ALGORITHM, hHash, 0, &hKey);
    // 刪除散列表
    CryptDestroyHash(hHash);
    hHash = 0;
    }

    //計算一次加密的數據字節數,必須為ENCRYPT_BLOCK_SIZE的整數倍
    dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;
    //如果使用塊編碼,則需要額外空間
    if(ENCRYPT_BLOCK_SIZE  > 1) {
    dwBufferLen = dwBlockLen + ENCRYPT_BLOCK_SIZE;
    } else {
    dwBufferLen = dwBlockLen;
    }
    //分配緩沖區
    pbBuffer = malloc(dwBufferLen);
    //加密源文件并寫入目標文件
    do {
    // 從源文件中讀出dwBlockLen個字節
    dwCount = fread(pbBuffer, 1, dwBlockLen, hSource);
    eof = feof(hSource);
    //加密數據
    CryptEncrypt(hKey, 0, eof, 0, pbBuffer,
    &dwCount, dwBufferLen);
    // 將加密過的數據寫入目標文件
    fwrite(pbBuffer, 1, dwCount, hDestination);
    } while(!feof(hSource));
    printf("OK\n");
    ……//關閉文件、釋放內存
       }

    ②文件解密

    void CAPIDecryptFile(PCHAR szSource, PCHAR
    szDestination, PCHAR szPassword)
    {
    ……//變量聲明、文件操作同文件加密程序

    CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0);
      if(szPassword == NULL) {
    // 口令為空,使用存儲在加密文件中的會話密鑰解密
    // 讀隱碼的長度并分配內存
    fread(&dwKeyBlobLen, sizeof(DWORD), 1, hSource);
    pbKeyBlob = malloc(dwKeyBlobLen)) == NULL);
    // 從源文件中讀隱碼.
    fread(pbKeyBlob, 1, dwKeyBlobLen, hSource);
    // 將隱碼輸入CSP
    CryptImportKey(hProv, pbKeyBlob,
    dwKeyBlobLen, 0, 0, &hKey);
    } else {
    // 口令不為空, 使用從口令派生出的密鑰解密文件
    CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
    CryptHashData(hHash, szPassword, strlen(szPassword), 0);
    CryptDeriveKey(hProv, ENCRYPT_ALGORITHM,
    hHash, 0, &hKey);
    CryptDestroyHash(hHash);
    hHash = 0;
    }

    dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;
    if(ENCRYPT_BLOCK_SIZE  > 1) {
    dwBufferLen = dwBlockLen + ENCRYPT_BLOCK_SIZE;
    } else {
    dwBufferLen = dwBlockLen;
    }
    pbBuffer = malloc(dwBufferLen);

    //解密源文件并寫入目標文件
    do {
    dwCount = fread(pbBuffer, 1, dwBlockLen, hSource);
    eof = feof(hSource);
    // 解密數據
    CryptDecrypt(hKey, 0, eof, 0, pbBuffer, &dwCount);
    // 將解密過的數據寫入目標文件
    fwrite(pbBuffer, 1, dwCount, hDestination);
    } while(!feof(hSource));
    printf("OK\n");
    ……//關閉文件、釋放內存
    }

    ---- 以上代碼在Windows NT4.0、Visual C++6.0環境中編譯通過。
    ---- 除直接用于加密數據外,CryptoAPI還廣泛用于產生并確認數字簽名,這里就不一一舉例說明了,有興趣的讀者可以參考MSDN文檔。

    原文轉自:http://www.kjueaiud.com

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>