API就是好啊,利用API计算MD2 MD4 MD5 SHA1

笨狗先飞 2016-12-28 07:50:09

Public Const ALG_CLASS_HASH = 32768  
Public Const ALG_SID_MD2 = 1  
Public Const ALG_SID_MD4 = 2  
Public Const ALG_SID_MD5 = 3  
Public Const ALG_SID_SHA1 = 4  
Public Const ALG_TYPE_ANY = 0  
  
Public Const CRYPT_NEWKEYSET = 8  
  
Public Const HP_HASHVAL = 2  
Public Const HP_HASHSIZE = 4  
  
Public Const PROV_RSA_FULL = 1  
  
Public Declare Function CryptAcquireContext Lib "advapi32.dll" Alias "CryptAcquireContextA" (ByRef phProv As Long, ByVal pszContainer As String, ByVal pszProvider As String, ByVal dwProvType As Long, ByVal dwFlags As Long) As Long  
Public Declare Function CryptCreateHash Lib "advapi32.dll" (ByVal hProv As Long, ByVal Algid As Long, ByVal hKey As Long, ByVal dwFlags As Long, ByRef phHash As Long) As Long  
Public Declare Function CryptDestroyHash Lib "advapi32.dll" (ByVal hHash As Long) As Long  
Public Declare Function CryptGetHashParam Lib "advapi32.dll" (ByVal hHash As Long, ByVal dwParam As Long, pbData As Any, pdwDataLen As Long, ByVal dwFlags As Long) As Long  
Public Declare Function CryptHashData Lib "advapi32.dll" (ByVal hHash As Long, pbData As Any, ByVal dwDataLen As Long, ByVal dwFlags As Long) As Long  
Public Declare Function CryptReleaseContext Lib "advapi32.dll" (ByVal hProv As Long, ByVal dwFlags As Long) As Long  
  
Public Function CryptStr(ByVal Str As String, Optional ByVal CryptMode As String = "md5") As String  
    CryptStr = CryptByte(StrConv(Str, vbFromUnicode), CryptMode)  
End Function  
  
Public Function CryptByte(ByRef Buffer() As Byte, Optional ByVal CryptMode As String = "md5") As String  
    Dim Algorithm As Long, hCtx As Long, lRes As Long, hHash As Long, lLen As Long, abHash() As Byte  
    Select Case LCase(CryptMode)  
        Case "md2"  
            Algorithm = ALG_CLASS_HASH Or ALG_TYPE_ANY Or ALG_SID_MD2  
        Case "md4"  
            Algorithm = ALG_CLASS_HASH Or ALG_TYPE_ANY Or ALG_SID_MD4  
        Case "md5"  
            Algorithm = ALG_CLASS_HASH Or ALG_TYPE_ANY Or ALG_SID_MD5  
        Case "sha1"  
            Algorithm = ALG_CLASS_HASH Or ALG_TYPE_ANY Or ALG_SID_SHA1  
        Case Else  
            Exit Function  
    End Select  
    If CryptAcquireContext(hCtx, vbNullString, vbNullString, PROV_RSA_FULL, 0) = 0 Then  
        CryptAcquireContext hCtx, vbNullString, vbNullString, PROV_RSA_FULL, CRYPT_NEWKEYSET  
    End If  
    CryptCreateHash hCtx, Algorithm, 0, 0, hHash  
    If UBound(Buffer) >= 0 Then CryptHashData hHash, Buffer(0), UBound(Buffer) + 1, 0  
    CryptGetHashParam hHash, HP_HASHSIZE, lLen, 4, 0  
    ReDim abHash(lLen - 1)  
    CryptGetHashParam hHash, HP_HASHVAL, abHash(0), lLen, 0  
    CryptDestroyHash hHash  
    CryptReleaseContext hCtx, 0  
    For lRes = 0 To UBound(abHash)  
        CryptByte = CryptByte & Right("0" & Hex(abHash(lRes)), 2)  
    Next  
    Erase abHash  
End Function  
  
Public Function CryptFile(ByVal FileName As String, Optional ByVal CryptMode As String = "md5", Optional ByVal BlockSize As Long = 327680) As String  
    Dim Algorithm As Long, hCtx As Long, lRes As Long, hHash As Long, lLen As Long, abHash() As Byte, Data() As Byte, FN As Integer, FileSize As Long  
    Select Case LCase(CryptMode)  
        Case "md2"  
            Algorithm = ALG_CLASS_HASH Or ALG_TYPE_ANY Or ALG_SID_MD2  
        Case "md4"  
            Algorithm = ALG_CLASS_HASH Or ALG_TYPE_ANY Or ALG_SID_MD4  
        Case "md5"  
            Algorithm = ALG_CLASS_HASH Or ALG_TYPE_ANY Or ALG_SID_MD5  
        Case "sha1"  
            Algorithm = ALG_CLASS_HASH Or ALG_TYPE_ANY Or ALG_SID_SHA1  
        Case Else  
            Exit Function  
    End Select  
    If CryptAcquireContext(hCtx, vbNullString, vbNullString, PROV_RSA_FULL, 0) = 0 Then  
        CryptAcquireContext hCtx, vbNullString, vbNullString, PROV_RSA_FULL, CRYPT_NEWKEYSET  
    End If  
    CryptCreateHash hCtx, Algorithm, 0, 0, hHash  
    FN = FreeFile  
    ReDim Data(BlockSize - 1)  
    Open FileName For Binary As FN  
    FileSize = LOF(FN)  
    Do While FileSize > 0  
        Get FN, , Data  
        CryptHashData hHash, Data(0), IIf(FileSize > BlockSize, BlockSize, FileSize), 0  
        FileSize = FileSize - BlockSize  
    Loop  
    Erase Data  
    Close FN  
    CryptGetHashParam hHash, HP_HASHSIZE, lLen, 4, 0  
    ReDim abHash(lLen - 1)  
    CryptGetHashParam hHash, HP_HASHVAL, abHash(0), lLen, 0  
    CryptDestroyHash hHash  
    CryptReleaseContext hCtx, 0  
    For lRes = 0 To UBound(abHash)  
        CryptFile = CryptFile & Right("0" & Hex(abHash(lRes)), 2)  
    Next  
    Erase abHash  
End Function  
...全文
1065 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
一笑拔剑 2017-01-08
  • 打赏
  • 举报
回复
MD5说弃用也没这么夸张 毕竟不是每个人都是密码破解专家 很多地方加密要求不高的还是用MD5的 另外MD5再很多下载站是拿来校检文件的 这个对碰撞的要求不高 还是有很大的生存余地的
无·法 2017-01-04
  • 打赏
  • 举报
回复
引用 16 楼 Chen8013 的回复:
[quote=引用 15 楼 sysdzw 的回复:] ………… 受教了。听你这么一说立刻明白了。。。 你太适合当老师了
怎么取个这么怪的名字? 我看到“消息”提示时,还以为CSDN又抽风了呢……[/quote]这样好玩。。
舉杯邀明月 2016-12-31
  • 打赏
  • 举报
回复
引用 15 楼 sysdzw 的回复:
………… 受教了。听你这么一说立刻明白了。。。 你太适合当老师了
怎么取个这么怪的名字? 我看到“消息”提示时,还以为CSDN又抽风了呢……
舉杯邀明月 2016-12-30
  • 打赏
  • 举报
回复
引用 8 楼 sysdzw 的回复:
[quote=引用 5 楼 of123 的回复:] MD5 已经被弃用。它的“提前”下架与中国密码学家王晓云教授的工作有关,她找到了加速“破解”MD5 的算法。也就是可以用大大缩短的时间,伪造出一个与原有 MD5 相同(学科中称为“碰撞”)的消息。比如,在一份改过的合同文本加一些不可见数据使之与原文 MD5 相同。 美国推行的商用标准,Hash 算法用 Security SHA,也就是 SHA-1、SHA-256(SHA-224)、SHA-384 和 SHA-512。中国商密标准执行的是 SM3。
是不是说多对一? 也就是一个密码有多个原文可以对应着?[/quote] 难道在你的“意识”中,这些“摘要”算法的结果是“一对一”的啊………… 这些“Hash”结果都是有限的字节数,它的“结果组合数”最多就是对应的“2的n次方(n是对应的bit数)”,   比如MD5是128位,最多就有“2^128”种结果(比如全0、全1这些比较特殊的,应该是不会出现的),   即便是SHA-512,也是最多 2^512种结果,虽然算是“很巨大的数”,但毕竟还是有限的; 然而现实的“数据组合”,从1字节到数GB字节(你可以想象成“磁盘文件”的数据,每个字节有256种可能),  这些“组合总数”才是真正的“天文数字”,“天文数÷有限的巨大数”,其“商”也可以说是一个“天文数字”;  也就是说,任意一个“Hash码”都可能对应着“非常多种数据组合”。
笨狗先飞 2016-12-30
  • 打赏
  • 举报
回复
用有限的字符去表示无限的内容,脚趾头想想就知道有重复的了。
of123 2016-12-30
  • 打赏
  • 举报
回复
引用 8 楼 sysdzw 的回复:
[quote=引用 5 楼 of123 的回复:] MD5 已经被弃用。它的“提前”下架与中国密码学家王晓云教授的工作有关,她找到了加速“破解”MD5 的算法。也就是可以用大大缩短的时间,伪造出一个与原有 MD5 相同(学科中称为“碰撞”)的消息。比如,在一份改过的合同文本加一些不可见数据使之与原文 MD5 相同。 美国推行的商用标准,Hash 算法用 Security SHA,也就是 SHA-1、SHA-256(SHA-224)、SHA-384 和 SHA-512。中国商密标准执行的是 SM3。
是不是说多对一? 也就是一个密码有多个原文可以对应着?[/quote]是的。实际上,碰撞的可能天然存在。只是由于它的 Hash 值长度和算法设计使得碰撞概率非常低。你可以根据应用的安全需求,选择合适的算法。
of123 2016-12-30
  • 打赏
  • 举报
回复
引用 7 楼 Tiger_Zhao 的回复:
[Quote=引用 5 楼 of123 的回复:]MD5 已经被弃用。它的“提前”下架与中国密码学家王晓云教授的工作有关,她找到了加速“破解”MD5 的算法。也就是可以用大大缩短的时间,伪造出一个与原有 MD5 相同(学科中称为“碰撞”)的消息。比如,在一份改过的合同文本加一些不可见数据使之与原文 MD5 相同。[/Quote] 其实任何Hash算法都有类似的问题,SHA-1不也弃用了。 所以要追加其它验证来提高安全性:用长度进行验证;用其它Hash进行验证。
至少,SHA-1 还没有被发现类似 MD5 这样的漏洞。而且,在 TPM 可信平台等规范中,SHA-1 还是备选的算法。其他 SHA 算法目前还都没有被找到类似 MD5 的“问题”。注意,MD5 不是因为 Hash 结果长度被弃用的,是有安全漏洞。在王晓云方法攻击下,找到碰撞的概率远小于它的设计指标。 目前,金融界使用的数字签名,按照标准,应是 ECC-256 + SHA-256(国际)或 SM2 + SM3(中国,SM2 是 ECC 的一种,SM3 也是输出 256 比特的)。这与 ECC-256 的“包”是 256 比特有关,省去了填充(原来在 RSA 中有专门的填充规范)。
无·法 2016-12-30
  • 打赏
  • 举报
回复
引用 5 楼 of123 的回复:
MD5 已经被弃用。它的“提前”下架与中国密码学家王晓云教授的工作有关,她找到了加速“破解”MD5 的算法。也就是可以用大大缩短的时间,伪造出一个与原有 MD5 相同(学科中称为“碰撞”)的消息。比如,在一份改过的合同文本加一些不可见数据使之与原文 MD5 相同。 美国推行的商用标准,Hash 算法用 Security SHA,也就是 SHA-1、SHA-256(SHA-224)、SHA-384 和 SHA-512。中国商密标准执行的是 SM3。
是不是说多对一? 也就是一个密码有多个原文可以对应着?
Tiger_Zhao 2016-12-30
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 of123 的回复:]MD5 已经被弃用。它的“提前”下架与中国密码学家王晓云教授的工作有关,她找到了加速“破解”MD5 的算法。也就是可以用大大缩短的时间,伪造出一个与原有 MD5 相同(学科中称为“碰撞”)的消息。比如,在一份改过的合同文本加一些不可见数据使之与原文 MD5 相同。[/Quote]
其实任何Hash算法都有类似的问题,SHA-1不也弃用了。

所以要追加其它验证来提高安全性:用长度进行验证;用其它Hash进行验证。
笨狗先飞 2016-12-30
  • 打赏
  • 举报
回复
安不安全别人说了算,我们只也是对对接口的,我们只要求解决过程简单可靠。
of123 2016-12-30
  • 打赏
  • 举报
回复
MD5 已经被弃用。它的“提前”下架与中国密码学家王晓云教授的工作有关,她找到了加速“破解”MD5 的算法。也就是可以用大大缩短的时间,伪造出一个与原有 MD5 相同(学科中称为“碰撞”)的消息。比如,在一份改过的合同文本加一些不可见数据使之与原文 MD5 相同。 美国推行的商用标准,Hash 算法用 Security SHA,也就是 SHA-1、SHA-256(SHA-224)、SHA-384 和 SHA-512。中国商密标准执行的是 SM3。
无·法 2016-12-30
  • 打赏
  • 举报
回复
引用 12 楼 Chen8013 的回复:
[quote=引用 8 楼 sysdzw 的回复:] [quote=引用 5 楼 of123 的回复:] MD5 已经被弃用。它的“提前”下架与中国密码学家王晓云教授的工作有关,她找到了加速“破解”MD5 的算法。也就是可以用大大缩短的时间,伪造出一个与原有 MD5 相同(学科中称为“碰撞”)的消息。比如,在一份改过的合同文本加一些不可见数据使之与原文 MD5 相同。 美国推行的商用标准,Hash 算法用 Security SHA,也就是 SHA-1、SHA-256(SHA-224)、SHA-384 和 SHA-512。中国商密标准执行的是 SM3。
是不是说多对一? 也就是一个密码有多个原文可以对应着?[/quote] 难道在你的“意识”中,这些“摘要”算法的结果是“一对一”的啊………… 这些“Hash”结果都是有限的字节数,它的“结果组合数”最多就是对应的“2的n次方(n是对应的bit数)”,   比如MD5是128位,最多就有“2^128”种结果(比如全0、全1这些比较特殊的,应该是不会出现的),   即便是SHA-512,也是最多 2^512种结果,虽然算是“很巨大的数”,但毕竟还是有限的; 然而现实的“数据组合”,从1字节到数GB字节(你可以想象成“磁盘文件”的数据,每个字节有256种可能),  这些“组合总数”才是真正的“天文数字”,“天文数÷有限的巨大数”,其“商”也可以说是一个“天文数字”;  也就是说,任意一个“Hash码”都可能对应着“非常多种数据组合”。 [/quote]受教了。听你这么一说立刻明白了。。。 你太适合当老师了
笨狗先飞 2016-12-30
  • 打赏
  • 举报
回复
引用 13 楼 zhao4zhong1 的回复:
仅供参考:
#pragma comment(lib, "crypt32.lib")
#pragma comment(lib, "advapi32.lib")
#define _WIN32_WINNT 0x0400
#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>
#define KEYLENGTH  0x00800000
void HandleError(char *s);
//--------------------------------------------------------------------
//  These additional #define statements are required.
#define ENCRYPT_ALGORITHM CALG_RC4
#define ENCRYPT_BLOCK_SIZE 8
//   Declare the function EncryptFile. The function definition
//   follows main.
BOOL EncryptFile(
    PCHAR szSource,
    PCHAR szDestination,
    PCHAR szPassword);
//--------------------------------------------------------------------
//   Begin main.
void main(void) {
    CHAR szSource[100];
    CHAR szDestination[100];
    CHAR szPassword[100];
    printf("Encrypt a file. \n\n");
    printf("Enter the name of the file to be encrypted: ");
    scanf("%s",szSource);
    printf("Enter the name of the output file: ");
    scanf("%s",szDestination);
    printf("Enter the password:");
    scanf("%s",szPassword);
    //--------------------------------------------------------------------
    // Call EncryptFile to do the actual encryption.
    if(EncryptFile(szSource, szDestination, szPassword)) {
        printf("Encryption of the file %s was a success. \n", szSource);
        printf("The encrypted data is in file %s.\n",szDestination);
    } else {
        HandleError("Error encrypting file!");
    }
} // End of main
//--------------------------------------------------------------------
//   Code for the function EncryptFile called by main.
static BOOL EncryptFile(
    PCHAR szSource,
    PCHAR szDestination,
    PCHAR szPassword)
//--------------------------------------------------------------------
//   Parameters passed are:
//     szSource, the name of the input, a plaintext file.
//     szDestination, the name of the output, an encrypted file to be
//         created.
//     szPassword, the password.
{
    //--------------------------------------------------------------------
    //   Declare and initialize local variables.
    FILE *hSource;
    FILE *hDestination;
    HCRYPTPROV hCryptProv;
    HCRYPTKEY hKey;
    HCRYPTHASH hHash;
    PBYTE pbBuffer;
    DWORD dwBlockLen;
    DWORD dwBufferLen;
    DWORD dwCount;
    //--------------------------------------------------------------------
    // Open source file.
    if(hSource = fopen(szSource,"rb")) {
        printf("The source plaintext file, %s, is open. \n", szSource);
    } else {
        HandleError("Error opening source plaintext file!");
    }
    //--------------------------------------------------------------------
    // Open destination file.
    if(hDestination = fopen(szDestination,"wb")) {
        printf("Destination file %s is open. \n", szDestination);
    } else {
        HandleError("Error opening destination ciphertext file!");
    }
    //以下获得一个CSP句柄
    if(CryptAcquireContext(
                &hCryptProv,
                NULL,               //NULL表示使用默认密钥容器,默认密钥容器名
                //为用户登陆名
                NULL,
                PROV_RSA_FULL,
                0)) {
        printf("A cryptographic provider has been acquired. \n");
    } else {
        if(CryptAcquireContext(
                    &hCryptProv,
                    NULL,
                    NULL,
                    PROV_RSA_FULL,
                    CRYPT_NEWKEYSET))//创建密钥容器
        {
            //创建密钥容器成功,并得到CSP句柄
            printf("A new key container has been created.\n");
        } else {
            HandleError("Could not create a new key container.\n");
        }
    }
    //--------------------------------------------------------------------
    // 创建一个会话密钥(session key)
    // 会话密钥也叫对称密钥,用于对称加密算法。
    // (注: 一个Session是指从调用函数CryptAcquireContext到调用函数
    //   CryptReleaseContext 期间的阶段。会话密钥只能存在于一个会话过程)
    //--------------------------------------------------------------------
    // Create a hash object.
    if(CryptCreateHash(
                hCryptProv,
                CALG_MD5,
                0,
                0,
                &hHash)) {
        printf("A hash object has been created. \n");
    } else {
        HandleError("Error during CryptCreateHash!\n");
    }
    //--------------------------------------------------------------------
    // 用输入的密码产生一个散列
    if(CryptHashData(
                hHash,
                (BYTE *)szPassword,
                strlen(szPassword),
                0)) {
        printf("The password has been added to the hash. \n");
    } else {
        HandleError("Error during CryptHashData. \n");
    }
    //--------------------------------------------------------------------
    // 通过散列生成会话密钥
    if(CryptDeriveKey(
                hCryptProv,
                ENCRYPT_ALGORITHM,
                hHash,
                KEYLENGTH,
                &hKey)) {
        printf("An encryption key is derived from the password hash. \n");
    } else {
        HandleError("Error during CryptDeriveKey!\n");
    }
    //--------------------------------------------------------------------
    // Destroy the hash object.
    CryptDestroyHash(hHash);
    hHash = NULL;
    //--------------------------------------------------------------------
    //  The session key is now ready.
    //--------------------------------------------------------------------
    // 因为加密算法是按ENCRYPT_BLOCK_SIZE 大小的块加密的,所以被加密的
    // 数据长度必须是ENCRYPT_BLOCK_SIZE 的整数倍。下面计算一次加密的
    // 数据长度。
    dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;
    //--------------------------------------------------------------------
    // Determine the block size. If a block cipher is used,
    // it must have room for an extra block.
    if(ENCRYPT_BLOCK_SIZE > 1)
        dwBufferLen = dwBlockLen + ENCRYPT_BLOCK_SIZE;
    else
        dwBufferLen = dwBlockLen;
    //--------------------------------------------------------------------
    // Allocate memory.
    if(pbBuffer = (BYTE *)malloc(dwBufferLen)) {
        printf("Memory has been allocated for the buffer. \n");
    } else {
        HandleError("Out of memory. \n");
    }
    //--------------------------------------------------------------------
    // In a do loop, encrypt the source file and write to the destination file.
    do {
        //--------------------------------------------------------------------
        // Read up to dwBlockLen bytes from the source file.
        dwCount = fread(pbBuffer, 1, dwBlockLen, hSource);
        if(ferror(hSource)) {
            HandleError("Error reading plaintext!\n");
        }
        //--------------------------------------------------------------------
        // 加密数据
        if(!CryptEncrypt(
                    hKey,           //密钥
                    0,              //如果数据同时进行散列和加密,这里传入一个
                    //散列对象
                    feof(hSource),  //如果是最后一个被加密的块,输入TRUE.如果不是输.
                    //入FALSE这里通过判断是否到文件尾来决定是否为
                    //最后一块。
                    0,              //保留
                    pbBuffer,       //输入被加密数据,输出加密后的数据
                    &dwCount,       //输入被加密数据实际长度,输出加密后数据长度
                    dwBufferLen))   //pbBuffer的大小。
        {
            HandleError("Error during CryptEncrypt. \n");
        }
        //--------------------------------------------------------------------
        // Write data to the destination file.
        fwrite(pbBuffer, 1, dwCount, hDestination);
        if(ferror(hDestination)) {
            HandleError("Error writing ciphertext.");
        }
    } while(!feof(hSource));
    //--------------------------------------------------------------------
    //  End the do loop when the last block of the source file has been
    //  read, encrypted, and written to the destination file.
    //--------------------------------------------------------------------
    // Close files.
    if(hSource)
        fclose(hSource);
    if(hDestination)
        fclose(hDestination);
    //--------------------------------------------------------------------
    // Free memory.
    if(pbBuffer)
        free(pbBuffer);
    //--------------------------------------------------------------------
    // Destroy session key.
    if(hKey)
        CryptDestroyKey(hKey);
    //--------------------------------------------------------------------
    // Destroy hash object.
    if(hHash)
        CryptDestroyHash(hHash);
    //--------------------------------------------------------------------
    // Release provider handle.
    if(hCryptProv)
        CryptReleaseContext(hCryptProv, 0);
    return(TRUE);
} // End of Encryptfile
//--------------------------------------------------------------------
//  This example uses the function HandleError, a simple error
//  handling function, to print an error message to the standard error
//  (stderr) file and exit the program.
//  For most applications, replace this function with one
//  that does more extensive error reporting.
void HandleError(char *s) {
    fprintf(stderr,"An error occurred in running the program. \n");
    fprintf(stderr,"%s\n",s);
    fprintf(stderr, "Error number %x.\n", GetLastError());
    fprintf(stderr, "Program terminating. \n");
    exit(1);
} // End of HandleError

Crypt有好多加密算法可以搞,今天看到用这个做AES算法的,回头研究一下
赵4老师 2016-12-30
  • 打赏
  • 举报
回复
仅供参考:
#pragma comment(lib, "crypt32.lib")
#pragma comment(lib, "advapi32.lib")
#define _WIN32_WINNT 0x0400
#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>
#define KEYLENGTH  0x00800000
void HandleError(char *s);
//--------------------------------------------------------------------
//  These additional #define statements are required.
#define ENCRYPT_ALGORITHM CALG_RC4
#define ENCRYPT_BLOCK_SIZE 8
//   Declare the function EncryptFile. The function definition
//   follows main.
BOOL EncryptFile(
    PCHAR szSource,
    PCHAR szDestination,
    PCHAR szPassword);
//--------------------------------------------------------------------
//   Begin main.
void main(void) {
    CHAR szSource[100];
    CHAR szDestination[100];
    CHAR szPassword[100];
    printf("Encrypt a file. \n\n");
    printf("Enter the name of the file to be encrypted: ");
    scanf("%s",szSource);
    printf("Enter the name of the output file: ");
    scanf("%s",szDestination);
    printf("Enter the password:");
    scanf("%s",szPassword);
    //--------------------------------------------------------------------
    // Call EncryptFile to do the actual encryption.
    if(EncryptFile(szSource, szDestination, szPassword)) {
        printf("Encryption of the file %s was a success. \n", szSource);
        printf("The encrypted data is in file %s.\n",szDestination);
    } else {
        HandleError("Error encrypting file!");
    }
} // End of main
//--------------------------------------------------------------------
//   Code for the function EncryptFile called by main.
static BOOL EncryptFile(
    PCHAR szSource,
    PCHAR szDestination,
    PCHAR szPassword)
//--------------------------------------------------------------------
//   Parameters passed are:
//     szSource, the name of the input, a plaintext file.
//     szDestination, the name of the output, an encrypted file to be
//         created.
//     szPassword, the password.
{
    //--------------------------------------------------------------------
    //   Declare and initialize local variables.
    FILE *hSource;
    FILE *hDestination;
    HCRYPTPROV hCryptProv;
    HCRYPTKEY hKey;
    HCRYPTHASH hHash;
    PBYTE pbBuffer;
    DWORD dwBlockLen;
    DWORD dwBufferLen;
    DWORD dwCount;
    //--------------------------------------------------------------------
    // Open source file.
    if(hSource = fopen(szSource,"rb")) {
        printf("The source plaintext file, %s, is open. \n", szSource);
    } else {
        HandleError("Error opening source plaintext file!");
    }
    //--------------------------------------------------------------------
    // Open destination file.
    if(hDestination = fopen(szDestination,"wb")) {
        printf("Destination file %s is open. \n", szDestination);
    } else {
        HandleError("Error opening destination ciphertext file!");
    }
    //以下获得一个CSP句柄
    if(CryptAcquireContext(
                &hCryptProv,
                NULL,               //NULL表示使用默认密钥容器,默认密钥容器名
                //为用户登陆名
                NULL,
                PROV_RSA_FULL,
                0)) {
        printf("A cryptographic provider has been acquired. \n");
    } else {
        if(CryptAcquireContext(
                    &hCryptProv,
                    NULL,
                    NULL,
                    PROV_RSA_FULL,
                    CRYPT_NEWKEYSET))//创建密钥容器
        {
            //创建密钥容器成功,并得到CSP句柄
            printf("A new key container has been created.\n");
        } else {
            HandleError("Could not create a new key container.\n");
        }
    }
    //--------------------------------------------------------------------
    // 创建一个会话密钥(session key)
    // 会话密钥也叫对称密钥,用于对称加密算法。
    // (注: 一个Session是指从调用函数CryptAcquireContext到调用函数
    //   CryptReleaseContext 期间的阶段。会话密钥只能存在于一个会话过程)
    //--------------------------------------------------------------------
    // Create a hash object.
    if(CryptCreateHash(
                hCryptProv,
                CALG_MD5,
                0,
                0,
                &hHash)) {
        printf("A hash object has been created. \n");
    } else {
        HandleError("Error during CryptCreateHash!\n");
    }
    //--------------------------------------------------------------------
    // 用输入的密码产生一个散列
    if(CryptHashData(
                hHash,
                (BYTE *)szPassword,
                strlen(szPassword),
                0)) {
        printf("The password has been added to the hash. \n");
    } else {
        HandleError("Error during CryptHashData. \n");
    }
    //--------------------------------------------------------------------
    // 通过散列生成会话密钥
    if(CryptDeriveKey(
                hCryptProv,
                ENCRYPT_ALGORITHM,
                hHash,
                KEYLENGTH,
                &hKey)) {
        printf("An encryption key is derived from the password hash. \n");
    } else {
        HandleError("Error during CryptDeriveKey!\n");
    }
    //--------------------------------------------------------------------
    // Destroy the hash object.
    CryptDestroyHash(hHash);
    hHash = NULL;
    //--------------------------------------------------------------------
    //  The session key is now ready.
    //--------------------------------------------------------------------
    // 因为加密算法是按ENCRYPT_BLOCK_SIZE 大小的块加密的,所以被加密的
    // 数据长度必须是ENCRYPT_BLOCK_SIZE 的整数倍。下面计算一次加密的
    // 数据长度。
    dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;
    //--------------------------------------------------------------------
    // Determine the block size. If a block cipher is used,
    // it must have room for an extra block.
    if(ENCRYPT_BLOCK_SIZE > 1)
        dwBufferLen = dwBlockLen + ENCRYPT_BLOCK_SIZE;
    else
        dwBufferLen = dwBlockLen;
    //--------------------------------------------------------------------
    // Allocate memory.
    if(pbBuffer = (BYTE *)malloc(dwBufferLen)) {
        printf("Memory has been allocated for the buffer. \n");
    } else {
        HandleError("Out of memory. \n");
    }
    //--------------------------------------------------------------------
    // In a do loop, encrypt the source file and write to the destination file.
    do {
        //--------------------------------------------------------------------
        // Read up to dwBlockLen bytes from the source file.
        dwCount = fread(pbBuffer, 1, dwBlockLen, hSource);
        if(ferror(hSource)) {
            HandleError("Error reading plaintext!\n");
        }
        //--------------------------------------------------------------------
        // 加密数据
        if(!CryptEncrypt(
                    hKey,           //密钥
                    0,              //如果数据同时进行散列和加密,这里传入一个
                    //散列对象
                    feof(hSource),  //如果是最后一个被加密的块,输入TRUE.如果不是输.
                    //入FALSE这里通过判断是否到文件尾来决定是否为
                    //最后一块。
                    0,              //保留
                    pbBuffer,       //输入被加密数据,输出加密后的数据
                    &dwCount,       //输入被加密数据实际长度,输出加密后数据长度
                    dwBufferLen))   //pbBuffer的大小。
        {
            HandleError("Error during CryptEncrypt. \n");
        }
        //--------------------------------------------------------------------
        // Write data to the destination file.
        fwrite(pbBuffer, 1, dwCount, hDestination);
        if(ferror(hDestination)) {
            HandleError("Error writing ciphertext.");
        }
    } while(!feof(hSource));
    //--------------------------------------------------------------------
    //  End the do loop when the last block of the source file has been
    //  read, encrypted, and written to the destination file.
    //--------------------------------------------------------------------
    // Close files.
    if(hSource)
        fclose(hSource);
    if(hDestination)
        fclose(hDestination);
    //--------------------------------------------------------------------
    // Free memory.
    if(pbBuffer)
        free(pbBuffer);
    //--------------------------------------------------------------------
    // Destroy session key.
    if(hKey)
        CryptDestroyKey(hKey);
    //--------------------------------------------------------------------
    // Destroy hash object.
    if(hHash)
        CryptDestroyHash(hHash);
    //--------------------------------------------------------------------
    // Release provider handle.
    if(hCryptProv)
        CryptReleaseContext(hCryptProv, 0);
    return(TRUE);
} // End of Encryptfile
//--------------------------------------------------------------------
//  This example uses the function HandleError, a simple error
//  handling function, to print an error message to the standard error
//  (stderr) file and exit the program.
//  For most applications, replace this function with one
//  that does more extensive error reporting.
void HandleError(char *s) {
    fprintf(stderr,"An error occurred in running the program. \n");
    fprintf(stderr,"%s\n",s);
    fprintf(stderr, "Error number %x.\n", GetLastError());
    fprintf(stderr, "Program terminating. \n");
    exit(1);
} // End of HandleError

笨狗先飞 2016-12-28
  • 打赏
  • 举报
回复
舉杯邀明月 2016-12-28
  • 打赏
  • 举报
回复
'Select Case LCase(CryptMode)
'    Case "md2"
'        Algorithm = ALG_CLASS_HASH Or ALG_TYPE_ANY Or ALG_SID_MD2
'    Case "md4"
'        Algorithm = ALG_CLASS_HASH Or ALG_TYPE_ANY Or ALG_SID_MD4
'    Case "md5"
'        Algorithm = ALG_CLASS_HASH Or ALG_TYPE_ANY Or ALG_SID_MD5
'    Case "sha1"
'        Algorithm = ALG_CLASS_HASH Or ALG_TYPE_ANY Or ALG_SID_SHA1
'    Case Else
'        Exit Function
'End Select
lLen = InStr(1, "md2,md4,md5,sha1", LCase$(CryptMode))
If (0& = lLen) Then Exit Function
Algorithm = ALG_CLASS_HASH Or ALG_TYPE_ANY Or (1& + lLen \ 4&)
舉杯邀明月 2016-12-28
  • 打赏
  • 举报
回复

1,486

社区成员

发帖
与我相关
我的任务
社区描述
VB API
社区管理员
  • API
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧