密码引擎加密API实现与测试20181308邵壮 [操作系统入门]
1、熟悉Windows CryptoAPI提供的常用函数接口。
2、掌握Windows CryptoAPI的使用。
3、利用Windows CryptoAPI设计和实现一个小型密码系统(如文件加密机),完成加解密、摘要运算、数字签名等功能。
1. 先编写一个加密的代码,使用Windows crypticAPI实现。
结果如图:
2.编写一个解密的代码,使用Windows crypticAPI实现。
3. 编写一个计算文件的代码,使用Windows crypticAPI实现文件的MD5计算。
用写好的代码测试123.dll,启动代码结果:
以下是代码共三个:分别是加密解密和计算MD5
加密
#include <stdio.h>
#define _WIN32_WINNT 0x0400
#include <windows.h>
#include <wincrypt.h>
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
#define KEYLENGTH 0x00800000
void HandleError(char *s);
#define ENCRYPT_ALGORITHM CALG_RC4
#define ENCRYPT_BLOCK_SIZE 8
BOOL EncryptFile(
PCHAR szSource,
PCHAR szDestination,
PCHAR szPassword);
void main(void)
{
CHAR szSource[100];
CHAR szDestination[100];
CHAR szPassword[100];
printf("Encrypt
a file.
");
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);
if(EncryptFile(szSource,
szDestination, szPassword))
{
printf("Encryption
of the file %s was a success.
", szSource);
printf("The
encrypted data is in file %s.
",szDestination);
}
else
{
HandleError("Error
encrypting file!");
}
}
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.
{
FILE
*hSource;
FILE
*hDestination;
HCRYPTPROV
hCryptProv;
HCRYPTKEY
hKey;
HCRYPTHASH
hHash;
PBYTE
pbBuffer;
DWORD
dwBlockLen;
DWORD
dwBufferLen;
DWORD
dwCount;
if(hSource
= fopen(szSource,"rb"))
{
printf("The
source plaintext file, %s, is open.
", szSource);
}
else
{
HandleError("Error
opening source plaintext file!");
}
if(hDestination
= fopen(szDestination,"wb"))
{
printf("Destination
file %s is open.
", szDestination);
}
else
{
HandleError("Error
opening destination ciphertext file!");
}
if(CryptAcquireContext(
&hCryptProv,
NULL,
NULL,
PROV_RSA_FULL,
0))
{
printf("A
cryptographic provider has been acquired.
");
}
else
{
if(CryptAcquireContext(
&hCryptProv,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_NEWKEYSET))//创建密钥容器
{
//创建密钥容器成功,并得到CSP句柄
printf("A
new key container has been created.
");
}
else
{
HandleError("Could
not create a new key container.
");
}
}
if(CryptCreateHash(
hCryptProv,
CALG_MD5,
0,
0,
&hHash))
{
printf("A hash object has been created.
");
}
else
{
HandleError("Error
during CryptCreateHash!
");
}
if(CryptHashData(
hHash,
(BYTE
*)szPassword,
strlen(szPassword),
0))
{
printf("The
password has been added to the hash.
");
}
else
{
HandleError("Error
during CryptHashData.
");
}
if(CryptDeriveKey(
hCryptProv,
ENCRYPT_ALGORITHM,
hHash,
KEYLENGTH,
&hKey))
{
printf("An
encryption key is derived from the password hash.
");
}
else
{
HandleError("Error
during CryptDeriveKey!
");
}
CryptDestroyHash(hHash);
hHash
= NULL;
dwBlockLen
= 1000 - 1000 % ENCRYPT_BLOCK_SIZE;
if(ENCRYPT_BLOCK_SIZE
> 1)
dwBufferLen
= dwBlockLen + ENCRYPT_BLOCK_SIZE;
else
dwBufferLen
= dwBlockLen;
if(pbBuffer
= (BYTE *)malloc(dwBufferLen))
{
printf("Memory
has been allocated for the buffer.
");
}
else
{
HandleError("Out
of memory.
");
}
do
{
dwCount
= fread(pbBuffer, 1, dwBlockLen, hSource);
if(ferror(hSource))
{
HandleError("Error
reading plaintext!
");
}
if(!CryptEncrypt(
hKey,
0,
feof(hSource),
0, //保留
pbBuffer, //输入被加密数据,输出加密后的数据
&dwCount, //输入被加密数据实际长度,输出加密后数据长度
dwBufferLen)) //pbBuffer的大小。
{
HandleError("Error
during CryptEncrypt.
");
}
fwrite(pbBuffer,
1, dwCount, hDestination);
if(ferror(hDestination))
{
HandleError("Error
writing ciphertext.");
}
}
while(!feof(hSource));
if(hSource)
fclose(hSource);
if(hDestination)
fclose(hDestination);
if(pbBuffer)
free(pbBuffer);
if(hKey)
CryptDestroyKey(hKey);
if(hHash)
CryptDestroyHash(hHash);
if(hCryptProv)
CryptReleaseContext(hCryptProv,
0);
return(TRUE);
}
void HandleError(char *s)
{
fprintf(stderr,"An error occurred in running the program.
");
fprintf(stderr,"%s
",s);
fprintf(stderr, "Error number %x.
", GetLastError());
fprintf(stderr, "Program terminating.
");
exit(1);
}
解密
#include <stdio.h>
#define _WIN32_WINNT 0x0400
#include <windows.h>
#include <wincrypt.h>
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
#define KEYLENGTH 0x00800000
void HandleError(char *s);
//--------------------------------------------------------------------
#define ENCRYPT_ALGORITHM CALG_RC4
#define ENCRYPT_BLOCK_SIZE 8
BOOL DecryptFile(
PCHAR szSource,
PCHAR szDestination,
PCHAR szPassword);
void main(void)
{
CHAR
szSource[100];
CHAR
szDestination[100];
CHAR
szPassword[100];
printf("Decrypt
a file.
");
printf("Enter
the name of the file to be decrypted: ");
scanf("%s",szSource);
printf("Enter
the name of the output file: ");
scanf("%s",szDestination);
printf("Enter
the password:");
scanf("%s",szPassword);
if(!DecryptFile(szSource,
szDestination, szPassword))
{
printf("
Error
decrypting file.
");
}
else
{
printf("
Decryption
of file %s succeeded.
", szSource);
printf("The
decrypted file is %s .
",szDestination);
}
}
static BOOL DecryptFile(
PCHAR
szSource,
PCHAR
szDestination,
PCHAR
szPassword)
{
FILE
*hSource;
FILE
*hDestination;
HCRYPTPROV
hCryptProv;
HCRYPTKEY
hKey;
HCRYPTHASH
hHash;
PBYTE
pbBuffer;
DWORD
dwBlockLen;
DWORD
dwBufferLen;
DWORD
dwCount;
BOOL
status = FALSE;
if(!(hSource
= fopen(szSource,"rb")))
{
HandleError("Error
opening ciphertext file!");
}
if(!(hDestination
= fopen(szDestination,"wb")))
{
HandleError("Error
opening plaintext file!");
}
if(!CryptAcquireContext(
&hCryptProv,
NULL,
NULL,
PROV_RSA_FULL,
0))
{
HandleError("Error
during CryptAcquireContext!");
}
if(!CryptCreateHash(
hCryptProv,
CALG_MD5,
0,
0,
&hHash))
{
HandleError("Error
during CryptCreateHash!");
}
if(!CryptHashData(
hHash,
(BYTE
*)szPassword,
strlen(szPassword),
0))
{
HandleError("Error
during CryptHashData!");
}
if(!CryptDeriveKey(
hCryptProv,
ENCRYPT_ALGORITHM,
hHash,
KEYLENGTH,
&hKey))
{
HandleError("Error
during CryptDeriveKey!");
}
CryptDestroyHash(hHash);
hHash
= 0;
dwBlockLen
= 1000 - 1000 % ENCRYPT_BLOCK_SIZE;
dwBufferLen
= dwBlockLen;
if(!(pbBuffer
= (BYTE *)malloc(dwBufferLen)))
{
HandleError("Out
of memory!
");
}
do
{
dwCount
= fread(
pbBuffer,
1,
dwBlockLen,
hSource);
if(ferror(hSource))
{
HandleError("Error
reading ciphertext!");
}
if(!CryptDecrypt(
hKey,
0,
feof(hSource),
0,
pbBuffer,
&dwCount))
{
HandleError("Error
during CryptDecrypt!");
}
fwrite(
pbBuffer,
1,
dwCount,
hDestination);
if(ferror(hDestination))
{
HandleError("Error
writing plaintext!");
}
}
while(!feof(hSource));
status
= TRUE;
if(hSource)
fclose(hSource);
if(hDestination)
fclose(hDestination);
if(pbBuffer)
free(pbBuffer);
if(hKey)
CryptDestroyKey(hKey);
if(hHash)
CryptDestroyHash(hHash);
if(hCryptProv)
CryptReleaseContext(hCryptProv,
0);
return
status;
}
void HandleError(char *s)
{
fprintf(stderr,"An error occurred in running the program.
");
fprintf(stderr,"%s
",s);
fprintf(stderr, "Error number %x.
", GetLastError());
fprintf(stderr, "Program terminating.
");
exit(1);
} // End of HandleError
MD5
#include <stdio.h>
#define _WIN32_WINNT 0x0400
#include <windows.h>
#include <wincrypt.h>
#define CHECK_NULL_RET(bCondition) if
(!bCondition) goto Exit0
#define BUFSIZE 1024
#define MD5LEN 16
BOOL GetContentMD5(
BYTE *pszFilePath,
BOOL bFile,
BOOL bUpperCase,
TCHAR *pszResult,
DWORD &dwStatus)
{
BOOL bResult = FALSE;
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
HANDLE hFile = NULL;
BYTE rgbFile[BUFSIZE];
DWORD cbRead = 0;
BYTE rgbHash[MD5LEN];
DWORD cbHash = 0;
CHAR rgbDigitsL[] = "0123456789abcdef";
CHAR rgbDigitsU[] = "0123456789ABCDEF";
CHAR *rgbDigits = bUpperCase ? rgbDigitsU : rgbDigitsL;
TCHAR szResult[MD5LEN*2+1] = {0};
dwStatus = 0;
bResult = CryptAcquireContext(&hProv,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT);
CHECK_NULL_RET(bResult);
bResult = CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
CHECK_NULL_RET(bResult);
if (bFile)
{
hFile = CreateFile((TCHAR *)pszFilePath,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
CHECK_NULL_RET(!(INVALID_HANDLE_VALUE == hFile));
while (bResult = ReadFile(hFile, rgbFile, BUFSIZE,
&cbRead, NULL))
{
if (0 == cbRead)
{
break;
}
bResult = CryptHashData(hHash, rgbFile, cbRead, 0);
CHECK_NULL_RET(bResult);
}
}
else
{
bResult = CryptHashData(hHash, pszFilePath, strlen((CHAR *)pszFilePath),
0);
CHECK_NULL_RET(bResult);
}
cbHash = MD5LEN;
if (bResult = CryptGetHashParam(hHash, HP_HASHVAL, rgbHash, &cbHash,
0))
{
TCHAR szTmpBuff[3] ;
for (DWORD i = 0; i < cbHash; i++)
{
sprintf (szTmpBuff,
TEXT("%c%c"), rgbDigits[rgbHash[i]>>4],
rgbDigits[rgbHash[i] &
0xf]);
lstrcat(szResult, szTmpBuff);
}
bResult = TRUE;
}
Exit0:
dwStatus = GetLastError();
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);
CloseHandle(hFile);
lstrcpy(pszResult, szResult);
return bResult;
}
int main(int argc, char* argv[])
{
DWORD dwStatus = 0;
TCHAR szResult[MD5LEN*2+1] = {0};
TCHAR szFilePath[] = TEXT("C:123.dll");
CHAR szContent[] = "explorer.exe";
GetContentMD5((BYTE *)szFilePath,
TRUE, TRUE, szResult, dwStatus);
MessageBox(NULL, szResult, TEXT("该文件的MD5"), MB_OK);
return 0;
}
这次实验难度很大,过程中遇到了很多的问题。感觉从一开始就无从下手,所以只能先去上网找资料和相关博客等学习。在看了很多的资料和相关解答之后虽然还是一头雾水,但是还算是有了不少的了解。在找到了相关代码之后,自己做了一些修改,也算是完成了这次的任务。也算是对Windows CryptoAPI有了一个初步的了解了。
利用Windows CryptoAPI进行加解密的一般步骤是怎样的?
CryptoAPI使用两种密钥:会话密钥与公共/私人密钥对。会话密钥使用相同的加密和解密密钥,这种算法较快,但必须保证密钥的安全传递。公共/私人密钥对使用一个公共密钥和一个私人密钥,私人密钥只有专人才能使用,公共密钥可以广泛传播。如果密钥对中的一个用于加密,另一个一定用于解密。公共/私人密钥对算法很慢,一般只用于加密小批数据,例如用于加密会话密钥。
CryptoAPI支持两种基本的编码方法:流式编码和块编码。流式编码在明码文本的每一位上创建编码位,速度较快,但安全性较低。块编码在一个完整的块上(一般为64位)上工作,需要使用填充的方法对要编码的数据进行舍入,以组成多个完整的块。这种算法速度较慢,但更安全。
加密:
1、打开源文件
2、取得密钥容器(CSP)句柄
3、根据用户输入的密码创建一个会话密钥(即对称密钥,用于对原文件加密)
4、加密数据文件
5、清理工作,如释放Buffer空间、密钥句柄、CSP句柄等。
解密:
1、打开源文件
2、取得密钥容器(CSP)句柄
3、根据用户输入的密码创建一个会话密钥(即对称密钥,用于对原文件解密,
这里要求用户输入的密码与加密时输入的密码相同。在实际应用中,这个所谓用户输入的“密码”其实只是一个产生密钥的种子,一旦产生完会话密钥,则用户完全
可以忘记当初输入的“密码”,接收方可以使用传过来的密钥直接对加密文件进行解密,而不用再重复一次“生成密钥”的过程。)
4、解密数据文件
5、清理工作,如释放Buffer空间、密钥句柄、CSP句柄等。
密码引擎-加密API实现与测试 20181308邵壮
以上是 密码引擎加密API实现与测试20181308邵壮 [操作系统入门] 的全部内容, 来源链接: utcz.com/z/519629.html