---
# System prepended metadata

title: 13_EZAES

---

---
title : 13_EZAES
---


# EZAES

by WL, Liu
Date : 2021-10-22

---
## 壹、簡介
此程式碼包括加密與解密功能，主要目標為執行配置所需配置，包括加密區塊大小、初始向量、產生金鑰物件，然後進行加密，本程式碼利用函式庫BCrypt中的AES進行撰寫。

## 標頭檔
```cpp=
#pragma once

#include <Windows.h>
#include <bcrypt.h>

class EZAES
{
	BCRYPT_HANDLE m_hProv;
	BCRYPT_KEY_HANDLE m_hKey;
	ULONG m_cbBlock;
	PUCHAR m_pbIV;
	ULONG m_cbIV;
	PUCHAR m_pbKeyObject;
	ULONG m_cbKeyObject;
```
* 第8行，演算提供者之handle。
* 第9行，金鑰的handle。
* 第10行，區塊大小。
* 第11行，初始向量的記憶體位置。
* 第12行，初始向量的記憶體大小。
* 第13行，金鑰的記憶體位置。
* 第14行，金鑰的記憶體大小。
```cpp=15
public:
	EZAES();
	~EZAES();
	BOOL GenKey(PUCHAR, ULONG);
	BOOL Init();
	BOOL Encrypt(PUCHAR, ULONG, PUCHAR, ULONG, PULONG);
	BOOL Decrypt(PUCHAR, ULONG, PUCHAR, ULONG, PULONG);

};

typedef EZAES* PEZAES;
```
* 第18行，產生金鑰。
* 第20行，執行加密。
* 第21行，執行解密。

## 主程式
```cpp=
#include "EZAES.h"
#include "../config.h"
#include <bcrypt.h>
#pragma comment(lib, "Bcrypt.lib")

```
### 開始加密
```cpp=6
EZAES::EZAES()
{
	m_hProv = INVALID_HANDLE_VALUE;
	m_hKey = INVALID_HANDLE_VALUE;
	m_pbIV = NULL;
	m_pbKeyObject = NULL;
	NTSTATUS status = STATUS_UNSUCCESSFUL;
	if (!NT_SUCCESS(status =
		BCryptOpenAlgorithmProvider(
			&m_hProv,
			BCRYPT_AES_ALGORITHM,
			NULL,
			0)))
	{
		DEBUG("BCryptOpenAlgorithmProvider returns 0x%x\n",
			status);
		return;
	}
```
* 第8到第12行，將參數初始化為0。
* 第14到第19行，開啟演算法提供者。
* 第16行，選擇AES演算法。
* 第20到第23行，若發生錯誤，則回傳錯誤代碼並標示錯誤"BCryptOpenAlgorithmProvider returns"，並且結束程式。
```cpp=24
	ULONG cbData;
	if (!NT_SUCCESS(status =
		BCryptGetProperty(
			m_hProv,
			BCRYPT_BLOCK_LENGTH,
			(PUCHAR)&m_cbBlock,
			sizeof(m_cbBlock),
			&cbData,
			0)))
	{
		DEBUG("BCryptGetProperty returns 0x%x\n",
			status);
		return;
	}
```
* 第26到第32行，取得加密區塊大小，並存放至第24行所設立之參數。
* 第34到第37行，若發生錯誤，則回傳錯誤代碼並標示錯誤"BCryptGetProperty returns"，並且結束程式。
```cpp=38
	m_cbIV = m_cbBlock;
	m_pbIV = (PUCHAR)HeapAlloc(
		GetProcessHeap(), 0, m_cbIV);
```
* 第38行，將初始向量大小設為加密區塊之大小。
* 第39及第40行，配置初始向量。
```cpp=41
	if (!NT_SUCCESS(status =
		BCryptGetProperty(
			m_hProv,
			BCRYPT_OBJECT_LENGTH,
			(PUCHAR)&m_cbKeyObject,
			sizeof(m_cbKeyObject),
			&cbData,
			0)))
	{
		DEBUG("BCryptGetProperty returns 0x%x\n",
			status);
		return;
	}
```
* 第42到第48行，取得金鑰大小，並存放至第24行所設立之參數。
* 第50到第52行，若發生錯誤，則回傳錯誤代碼並標示錯誤"BCryptGetProperty returns"，並且結束程式。
```cpp=54
	m_pbKeyObject = (PUCHAR)HeapAlloc(
		GetProcessHeap(), 0, m_cbKeyObject);
	if (NULL == m_pbKeyObject)
	{
		DEBUG("memory allocation failed\n");
		return;
	}
	return;
}

```
* 第54及第55行，配置金鑰。
* 第56到第61行，若發生錯誤，則回傳錯誤代碼並標示錯誤"memory allocation failed"，並且結束程式。
### 結束加密
```cpp=64
EZAES::~EZAES()
{
	if (m_pbIV) {
		HeapFree(GetProcessHeap(), 0, m_pbIV);
		m_pbIV = NULL;
	}
	m_cbIV = 0;
	if (m_pbKeyObject) {
		HeapFree(GetProcessHeap(), 0, m_pbKeyObject);
		m_pbKeyObject = NULL;
	}
	m_cbKeyObject = 0;
	if (m_hProv != INVALID_HANDLE_VALUE)
	{
		BCryptCloseAlgorithmProvider(m_hProv, 0);
		m_hProv = INVALID_HANDLE_VALUE;
	}
	if (m_hKey != INVALID_HANDLE_VALUE)
	{
		BCryptDestroyKey(m_hKey);
		m_hKey = INVALID_HANDLE_VALUE;
	}
	return;
}

```
* 第66到第69行，釋放初始向量。
* 第70行，參數歸零。
* 第71到第74行，釋放金鑰。
* 第75行，參數歸零。
* 第78行，關閉演算法提供者。
* 第79行，參數歸零。
* 第83行，銷毀金鑰。
* 第84行，參數歸零。
### 產生金鑰
```cpp=89
BOOL EZAES::GenKey(PUCHAR pbKey, ULONG cbKey)
{
	NTSTATUS status = STATUS_UNSUCCESSFUL;
	ULONG cbKeyObject = 0;
	if (!NT_SUCCESS(status =
		BCryptGenerateSymmetricKey(
			m_hProv,
			&m_hKey,
			m_pbKeyObject,
			m_cbKeyObject,
			pbKey,
			cbKey,
			0)))
	{
		DEBUG("BCryptGenerateSymmetricKey returns 0x%x\n",
			status);
		return FALSE;
	}
	Init();
	return TRUE;
}

```
* 第91及第92行，初始化參數為0;
* 第94到第101行，以密碼產生對應之金鑰。
* 第103到第105行，若發生錯誤，則回傳錯誤代碼並標示錯誤"BCryptGenerateSymmetricKey returns"，並且結束程式。
### 初始化
```cpp=111
BOOL EZAES::Init()
{
	if (m_pbIV && m_cbIV) {
		ZeroMemory(m_pbIV, m_cbIV);
	}
	return TRUE;
}

```
### 加密
```cpp=119
BOOL EZAES::Encrypt(
	PUCHAR pbPlain,
	ULONG cbPlain,
	PUCHAR pbCipher,
	ULONG cbCipher,
	PULONG pcbResult)
{
	NTSTATUS status = STATUS_UNSUCCESSFUL;
	ULONG cbData;
	if (!NT_SUCCESS(status =
		BCryptEncrypt(
			m_hKey,
			pbPlain,
			cbPlain,
			NULL,
			m_pbIV,
			m_cbIV,
			NULL,
			0,
			&cbData,
			0)))
	{
		DEBUG("AES BCryptEncrypt#1 0x%x\n",
			status);
		return NULL;
	}
    if (pcbResult) {
		*pcbResult = cbData;
	}
	if (cbCipher < cbData) {
		return FALSE;
	}
```
* 第129到第139行，取得加密所需空間，並儲存至第127行參數。
* 第141到第143行，若發生錯誤，則回傳錯誤代碼並標示錯誤"AES BCryptEncrypt#1"，並且結束程式。
* 第148到第150行，若記憶體大小小於所需空間，則回傳錯誤。
```cpp=151
	if (!NT_SUCCESS(status =
		BCryptEncrypt(
			m_hKey,
			pbPlain,
			cbPlain,
			NULL,
			m_pbIV,
			m_cbIV,
			pbCipher,
			cbData,
			&cbData,
			0)))
	{
		DEBUG("AES BCryptEncrypt#2 0x%x\n",
			status);
		return NULL;
	}
	if (pcbResult) {
		*pcbResult = cbData;
	}
	return TRUE;
}
```
* 第152到第162行，執行加密。
* 第141到第143行，若發生錯誤，則回傳錯誤代碼並標示錯誤"AES BCryptEncrypt#2"，並且結束程式。
* 第168到第170行，設置為加密結果之大小。
### 解密
```cpp=173
BOOL EZAES::Decrypt(
	PUCHAR pbCipher,
	ULONG cbCipher,
	PUCHAR pbPlain,
	ULONG cbPlain,
	PULONG pcbResult)
{
	NTSTATUS status = STATUS_UNSUCCESSFUL;
	ULONG cbData;
	if (!NT_SUCCESS(status =
		BCryptDecrypt(
			m_hKey,
			pbCipher,
			cbCipher,
			NULL,
			m_pbIV,
			m_cbIV,
			NULL,
			0,
			&cbData,
			0)))
	{
		DEBUG("EZAES::BCryptDecrypt#1 returns 0x%x\n",
			status);
		return NULL;
	}
	if (pcbResult) {
		*pcbResult = cbData;
	}
	if (cbPlain < cbData) {
		return FALSE;
	}
```
* 第183到第193行，取得解密所需空間，並儲存至第181行參數。
* 第195到第197行，若發生錯誤，則回傳錯誤代碼並標示錯誤"AES BCryptDecrypt#1"，並且結束程式。
* 第202到第204行，若記憶體大小小於所需空間，則回傳錯誤。
```cpp=205
	if (!NT_SUCCESS(status =
		BCryptDecrypt(
			m_hKey,
			pbCipher,
			cbCipher,
			NULL,
			m_pbIV,
			m_cbIV,
			pbPlain,
			cbData,
			&cbData,
			0)))
	{
		DEBUG("EZAES::BCryptDecrypt#2 returns 0x%x\n",
			status);
		return NULL;
	}
	return TRUE;
}
```
* 第206到第216行，執行加密。
* 第218到第220行，若發生錯誤，則回傳錯誤代碼並標示錯誤"AES BCryptEncrypt#2"，並且結束程式。