2021-04-25

密码引擎的汇总梳理
一、PKCS11
他是一套针对加密Token的应用编程接口,屏蔽了硬件细节,针对ANSI C编写的接口,也称作Cryptoki
总体模型:

函数接口概述:

应用实例:
通用目的函数:
1 .C_Initialize
CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(
CK_VOID_PTR pInitArgs
);
typedef struct CK_C_INITIALIZE_ARGS {
CK_CREATEMUTEX CreateMutex;
CK_DESTROYMUTEX DestroyMutex;
CK_LOCKMUTEX LockMutex;
CK_UNLOCKMUTEX UnlockMutex;
CK_FLAGS
flags;
CK_VOID_PTR pReserved;
} CK_C_INITIALIZE_ARGS;
2.C_Finalize
CK_DEFINE_FUNCTION(CK_RV, C_Finalize)(
CK_VOID_PTR pReserved
);
3. C_GetInfo
CK_DEFINE_FUNCTION(CK_RV, C_GetInfo)(
CK_INFO_PTR pInfo
);
4. C_GetFunctionList
CK_DEFINE_FUNCTION( CK_RV, C_GetFunctionList)(
CK_FUNCTION_LIST_PTR_PTR ppFunctionList
);
Sl ot/Token管理函数:
1 . C_GetSlotList
CK_DEFINE_FUNCTION( CK_RV,
C_GetSlotList)(
CK_BBOOL
tokenPresent,
CK_SLOT_ID_PTR pSlotList,
CK_ULONG_PTR pulCount
);
2. C_GetSlotInfo
CK_DEFINE_FUNCTION(CK_RV,
C_GetSlotInfo)(
CK_SLOT_ID
slotID,
CK_SLOT_INFO_PTR pInfo
);
二、Crypto API
微软公司在 NT4. 0 以上版本中提供了一套完整的 Crypto API 的函数,支持密钥交换,数据加密解密,数字签名,给程序员带来了很大方便,用户在对软件进行保护的时候可以直接利用 Crypto API 来完成这些工作,比如计算注册码,检查程序的完整性等。
首先, 是 Crypto API 运行的环境。
首先需要 Crypt32. lib, 将它加到 project->setting->link 下面, 当然你也可以在程序中用
#pragma comment (lib, “crypt32. lib”) 加入。
在程序开头, 你要加入两个头文件 windows. h 和 Wincrypt. h, 和一个
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
在正式应用 API 进行一系列的加密解密的时候, 需要有一些准备工作,下面是介绍一些在正式开始时所
需要了解和做的工作。
生成密钥和密钥容器
我们知道,在进行加密解密的时候, 我们需要一个密钥进行加密,和一个密钥进行解密, 加密密钥和解密密钥可能相同,也可能不同。 于是在我们进行加密解密的开始时, 我们首先需要有密钥。 下面这个程序,
完成了三个任务, 并且介绍了一些函数的用法。
任务一: 获取一个指定的密钥容器, 如果这个容器不存在, 创建一个。
任务二: 如果容器中不存在一个签名密钥对, 创建一个
任务三: 如果容器中不存在一个交换密钥对, 创建一个
CryptAcquireContext
CryptDestroyKey
CryptGenKey
CryptGetUserKey
// Copyright © Microsoft Corporation. All rights reserved.
#include <stdio. h>
#include <tchar. h>
#include <windows. h>
#include <Wincrypt. h>
//-------------------------------------------------------------------
void MyHandleError(LPTSTR psz)
{
_ftprintf(stderr, TEXT(“An error occurred in the program. \n”) ) ;
_ftprintf(stderr, TEXT("%s\n") , psz) ;
_ftprintf(stderr, TEXT(“Error number %x. \n”) , GetLastError() ) ;
_ftprintf(stderr, TEXT(“Program terminating. \n”) ) ;
exit(1) ;
} // End of MyHandleError.
上面这个函数是一个异常处理函数, 当出现错误的时候,出现提示, 并推出程序。以后的程序中都有这个函数,以后就会将这个函数的实现省去。现在这个函数的实现在后面。
void main(void)
{
HCRYPTPROV hCryptProv; //定义一个 CSP 模块的句柄。 “CSP 模块, 请查看《加密解密二》 222页LPCTSTR pszContainerName = TEXT(“My Sample Key Container”) ; //用一个 TEXT 宏定义一个容
器的名字,
if(CryptAcquireContext( //这个函数是获取有某个容器的 CSP 模块的指针, 成功返回 TRUE。
&hCryptProv, //指向一个 CSP 模块句柄指针, 里面用指定的容器
pszContainerName, //指定容器的名称
NULL, //这个参数这里用的是缺省值, 指得是缺省得 CSP 模块, 你也可以传入一个
LPCTSTR 类型的字符串,指定 CSP 模块
PROV_RSA_FULL, //确定密钥的类型
0) ) //常设为 0, 还有些其他的类型, 请看 MSDN
{
_tprintf(
TEXT("A crypto context with the %s key container ")
TEXT(“has been acquired. \n”) ,
pszContainerName) ;
}
else
{
//不成功的处理段
if(GetLastError() == NTE_BAD_KEYSET) // NTE_BAD_KEYSET 意味着密钥
//容器不存在, 下面就去创建一个
//新的密钥容器
{
if(CryptAcquireContext(
&hCryptProv,
pszContainerName,
NULL,
PROV_RSA_FULL,
CRYPT_NEWKEYSET) ) // CRYPT_NEWKEYSET 意味着当指定容器不存在的时候,
去创建一个容器。
{
_tprintf(TEXT("A new key container has been ")
TEXT(“created. \n”) ) ;
}
else
{
MyHandleError(TEXT("Could not create a new key ")
TEXT(“container. \n”) ) ;
}
}
else
{
MyHandleError(TEXT(“CryptAcquireContext failed. \n”) ) ;
}
}
HCRYPTKEY hKey; //创建一个密钥句柄
if(CryptGetUserKey( // CryptGetUserKey 是获取一个密钥//句柄的函
数, 成功返回 TRUE
hCryptProv, //指定容器的 CSP 模块句柄
AT_SIGNATURE, //指定私钥的类型
&hKey) ) //原来接收获取的密钥句柄
{
_tprintf(TEXT(“A signature key is available. \n”) ) ;
}
else
{
_tprintf(TEXT(“No signature key is available. \n”) ) ;
if(GetLastError() == NTE_NO_KEY) // NTE_NO_KEY 意味着密钥不存在, 下面就
生成一个密钥
{
_tprintf(TEXT(“The signature key does not exist. \n”) ) ;
_tprintf(TEXT(“Create a signature key pair. \n”) ) ;
if(CryptGenKey( // CryptGenKey 生成一个密钥
hCryptProv, //指定 CSP 模块的句柄
AT_SIGNATURE, //对于公钥密码系统, 生成一个私钥和一个公钥,
这个参数指定了这个密钥是公钥,于是生成了一个密码对。 如果不是公钥系统, 则指定了密码算法, 具体
看 MSDN。0,//指定了生成密钥的类型,这个参数的说明挺多
的,想获取更为详尽的资料请看 MSDN。
&hKey) )
{
_tprintf(TEXT(“Created a signature key pair. \n”) ) ;
}
else
{
MyHandleError(TEXT("Error occurred creating a ")
TEXT(“signature key. \n”) ) ;
}
}
else
{
MyHandleError(TEXT("An error other than NTE_NO_KEY ")
TEXT(“getting a signature key. \n”) ) ;
}
} // End if.
_tprintf(TEXT("A signature key pair existed, or one was ")
TEXT(“created. \n\n”) ) ;
if(hKey) //将密钥句柄销毁
{
if(!(CryptDestroyKey(hKey) ) )
{
MyHandleError(TEXT("Error during CryptDestroyKey. ") ) ;
}
hKey = NULL;
}
下面这部分和上面是类似的, 只不过密钥类型不相同而已。
if(CryptGetUserKey(
hCryptProv,
AT_KEYEXCHANGE,
&hKey) )
{
_tprintf(TEXT(“An exchange key exists. \n”) ) ;
}
else
{
_tprintf(TEXT(“No exchange key is available. \n”) ) ;
// Check to determine whether an exchange key
// needs to be created.
if(GetLastError() == NTE_NO_KEY)
{
// Create a key exchange key pair.
_tprintf(TEXT(“The exchange key does not exist. \n”) ) ;
_tprintf(TEXT("Attempting to create an exchange key ")
TEXT(“pair. \n”) ) ;
if(CryptGenKey(
hCryptProv,
AT_KEYEXCHANGE,
0,
&hKey) )
{
_tprintf(TEXT(“Exchange key pair created. \n”) ) ;
}
else
{
MyHandleError(TEXT("Error occurred attempting to ")
TEXT(“create an exchange key. \n”) ) ;
}
}
else
{
MyHandleError(TEXT("An error other than NTE_NO_KEY ")
TEXT(“occurred. \n”) ) ;
}
}
// Destroy the exchange key.
if(hKey)
{
if(!(CryptDestroyKey(hKey) ) )
{
MyHandleError(TEXT("Error during CryptDestroyKey. ") ) ;
}
hKey = NULL;
}
// Release the CSP.
if(hCryptProv)
{
if(!(CryptReleaseContext(hCryptProv, 0) ) )
{
MyHandleError(TEXT("Error during CryptReleaseContext. ") ) ;
}
}
_tprintf(TEXT("Everything is okay. A signature key ") ) ;
_tprintf(TEXT("pair and an exchange key exist in ") ) ;
_tprintf(TEXT(“the %skey container.\n”), pszContainerName) ;
} // End main.
三、GMT 0018-2012
下列缩略语适用于本部分:
ECC:椭圆曲线算法(Elliptic Curve Cryptography)
IPK:内部加密公钥(Internal Public Key)
ISK:内部加密私钥(Internal Private Key)
EPK:外部加密公钥(External Public Key)
KEK:密钥加密密钥(Key Encrypt Key)

GM/T 0006设备定义信息如下:
image
实际数字结构定义:
typedef struct DeviceInfo_st{
unsigned char IssuerName[40];
unsigned char DeviceName[16];
unsigned char DeviceSerial[16];
unsigned int DeviceVersion;
unsigned int StandardVersion;
unsigned int AsymAlgAbility[2];
unsigned int SymAlgAbility;
unsigned int HashAlgAbility;
unsigned int BufferSize;
}DEVICEINFO;

GB/T 0018-2012
**# define RSAref_MAX_BIT S2048
**# define RSAref_MAX_LEN
((RSAref_MAX_BITS+7)/8)
**# define RSAref_MAX_PBITS
((RSAref_MAX_BITS+1)/2)
**#define RSAref_MAX_PLEN
((RSAref_MAX_PBITS+7)/8)
typedef struct RSArefPublicKey_st
unsigned int bits;
unsigned char m[RSAref_MAX_LEN];
unsigned char e[RSAref_MAX_LEN];
}RSArefPublicKey;
typedef struct RSArefPrivateKey_st
{
unsigned int bits;
unsigned char m[RSAref_MAX_LEN];
unsigned char e[RSAref_MAX_LEN];
unsigned char d[RSAref_MAX_LEN];
unsigned char prime[2][RSAref_MAX_PLEN]; unsigned char pexp[2][RSAref_MAX_PLEN]; unsigned char coef RSArefMAX_PLEN];
}RSArefPrivateKey;

ECC加密如下:
image

//******************************************
//设备管理
//******************************************
/*
功能:打开密码设备,返回设备句柄。
参数:
返回值:0(SDR OK) 成功
非0 失败,返回错误代码
/
int SDF_OpenDevice(void* phDeviceHandle);
/*
功能:关闭密码设备,并释放相关资源。
参数:hDeviceHandle[in] 已打开的设备句柄
返回值:0(SDR OK) 成功
非0 失败,返回错误代码
/
int SDF_CloseDevice(void hDeviceHandle);
/*
功能: 创建与密码设备的会话。
已打开的设备句柄
hDeviceHandlein]参数:h
phessionHiandle[out]
返回与密码设备建立的新会话句柄成功
返回值:0(SDR OK) 成功
非0 失败,返回错误代码
/
int SDF_OpenSession(void hDeviceHandle, void** phSessionHandle);

/*
功能:关闭与密码设备已建立的会话,并释放相关资源。
参数:hSessionHandle[in] 与密码设备已建立的会话句柄
返回值:0(SDR OK) 成功
非0 失败,返回错误代码
/
int SDF_CloseSesson(void hSessionHandle);

/*
功能:获取密码设备能力描述。
参数:hSessionHandle[in] 与设备建立的会话句柄
pstDevicelnfo[our] 设备能力描述信息,内容及格式见设备信息定义成功
返回值:0(SDR OK) 成功
非0 失败,返回错误代码
/
int SDF_GetDeviceInfo(
void hSessionHandle,
DEVICEINFO* pstDeviceInfo);

/*
功能:获取指定长度的随机数。
参数:
hSessonHandle[in] 与设备建立的会话句柄
uiLegth[in] 欲获取的随机数长度
pucRandom[out] 缓冲区指针,用于存放获取的随机数
返回值:0(SDR OK) 成功
非0 失败,返回错误代码
/
int SDF_GenerateRandom(
void hSessionHandle,
unsigned int uiLength,
unsigned char* pucRandom);

/*
功能:获取密码设备内部存储的指定索引私钥的使用权。
参数:
hSessionHandle[in] 与设备建立的会话句柄
uiKeyIndex[in] 密码设备存储私钥的索引值
pucPassword[in] 使用私钥权限的标识码
uiPwdLength[in] 私钥访问控制码长度,不少于8 字节
返回值:0(SDR OK) 成功
非0 失败,返回错误代码
/
int SDF_GetPrivateKeyAccessRight(
void hSessionHandle,
unsigned int uiKeyIndex,
unsigned char* pucPassword,
unsigned int uiPwdLength);

/*
功能:释放密码设备存储的指定索引私钥的使用授权。
参数:
hSessonHandle[in] 与设备建立的会话句柄
uiKeyIndex[in] 密码设备存储私钥索引值成功
返回值∶0(SDR OK) 成功
非0 失败,返回错误代码
/
int SDF_ReleasePrivateKeyAccessRight(
void hSessionHandle,
unsigned int uiKeyIndex);

上一篇:朴素贝叶斯算法


下一篇:ATT&CK红队评估实战靶场(一)