KeePass
密码管理器




Package

如何为KeePass 1.x开发关键的提供程序插件


 介绍

截图从KeePass 1.10开始,KeePass支持密钥提供程序API。插件可以通过新设备(如USB设备ID,证书,智能卡等)轻松扩展内置密钥方法(主密码和/或密钥文件)。

密钥提供程序插件可以提供一个或多个密钥。在右侧的屏幕截图中,插件已将选项“证书”“智能卡” 和“用户凭据”添加到密钥文件组合框中。您的插件可能会显示其他文件选择对话框等,但建议您直接提供密钥,以便用户只需从组合框中选择它(如KeePass已提供多个文件位置)。

每次主密钥对话框打开时,KeePass首先使用KPM_KEYPROV_QUERY_INFO_FIRST和 KPM_KEYPROV_QUERY_INFO_NEXT消息查询所有插件的信息。您为响应这些消息而提供的信息显示在密钥文件组合框中。当用户选择您提供的其中一个选项并单击[确定]时,KeePass将向KPM_KEYPROV_QUERY_KEY您的插件发送一条消息,以实际获取该密钥。有关详细信息,请参阅以下部分。关闭对话框后,您会收到一条KPM_KEYPROV_FINALIZE消息,您可以在其中清除所有缓存的密钥。

信息  示例源代码

这是KeePass非常简单的密钥提供程序插件的源代码。请注意,此源代码无法按原样编译,因为省略了一些代码块。完整版本是可下载的 包 示例密钥提供程序Visual C ++ 2005项目的一部分

static  std :: vector <KP_KEYPROV_INFO> g_vKeyProv;
static  DWORD g_dwIterPos = 0;

初始化
{
	g_vKeyProv.clear();
	_ProvAdd(_T(“证书”),10);
	_ProvAdd(_T(“智能卡”),20);
	_ProvAdd(_T(“用户凭据”),9);

	返回 TRUE;
}

void _ProvAdd(LPCTSTR lpProvDisplayName,DWORD dwImageIndex)
{
	KP_KEYPROV_INFO c;
	ZeroMemory(&c,sizeofKP_KEYPROV_INFO));

	c.lpName = lpProvDisplayName;
	c.dwImageIndex = dwImageIndex;

	g_vKeyProv.push_back(C);
}

的onMessage
{
	开关(dwCode)
	{
	案例 KPM_KEYPROV_QUERY_INFO_FIRST:
		g_dwIterPos = 0;
		*((KP_KEYPROV_INFO *)lParamL)= g_vKeyProv [0];
		打破 ;

	案例 KPM_KEYPROV_QUERY_INFO_NEXT:
		++ g_dwIterPos;
		if(g_dwIterPos == 1)
			*((KP_KEYPROV_INFO *)lParamL)= g_vKeyProv [1];
		否则如果(g_dwIterPos == 2)
			*((KP_KEYPROV_INFO *)lParamL)= g_vKeyProv [2];
		打破 ;

	案例 KPM_KEYPROV_QUERY_KEY:
		_QueryProvKey((LPCTSTR)lParamW,(KP_KEYPROV_KEY *)lParamL);
		打破 ;

	case KPM_KEYPROV_FINALIZE:
		 //这个小样本
		中断没有什么可以清理的 ;

	默认值break ;
	}

	返回 TRUE;
}

void _QueryProvKey(LPCTSTR lpProvDisplayName,KP_KEYPROV_KEY * lpKey)
{
	//一些示例键。在真正的密钥提供者插件中,密钥
	//将从智能卡,USB设备,... 
	静态 BYTE vKey1 [4] = {1,2,3,4}中检索 ;
	static  BYTE vKey2 [8] = {2,4,6,8,10,12,14,16};
	static  BYTE vKey3 [10] = {2,3,5,7,11,13,17,19,23,29};

	if(_tcscmp(g_vKeyProv [0] .lpName,lpProvDisplayName)== 0)
	{
		lpKey-> lpData =&vKey1 [0];
		lpKey-> dwDataSize = 4;
	}
	否则if(_tcscmp(g_vKeyProv [1] .lpName,lpProvDisplayName)== 0)
	{
		lpKey-> lpData =&vKey2 [0];
		lpKey-> dwDataSize = 8;
	}
	else if(_tcscmp(g_vKeyProv [2] .lpName,lpProvDisplayName)== 0)
	{
		lpKey-> lpData =&vKey3 [0];
		lpKey-> dwDataSize = 10;
	}
}

信息  KPM_KEYPROV_QUERY_INFO_FIRST 和KPM_KEYPROV_QUERY_INFO_NEXT消息

这两条消息用于查询有关您提供的密钥的信息。该KPM_KEYPROV_QUERY_INFO_FIRST消息被发送一次,事后KPM_KEYPROV_QUERY_INFO_NEXT消息被重复发送,直到你没有提供一个新的关键了。两条消息的参数相同:

lParamW [in]: NULL。保留供将来使用。

lParamL [out]:指向KP_KEYPROV_INFO结构的指针。

您需要KP_KEYPROV_INFOlParamL中填写结构 。如果您不想返回提供者,只需保持此结构不变。

信息  KPM_KEYPROV_QUERY_KEY 信息

当用户选择了您提供的其中一个键并单击[确定]后,此消息将发送到您的插件。参数:

lParamW [in]:指向字符串的指针:在已选择的组合框中显示的名称。

lParamL [out]:指向KP_KEYPROV_KEY结构的指针。

您应该KP_KEYPROV_KEYlParamL中填写结构以返回密钥。

在上面的示例源代码中,返回常量键。在实际的密钥提供程序插件中,您可以在此处根据USB设备ID,智能卡,…构建实际密钥。

信息  KPM_KEYPROV_QUERY_KEY_EX 信息

当用户选择了您提供的其中一个键并单击[确定]后,此消息将发送到您的插件。参数:

lParamW [in]:指向KP_KEYPROV_CONTEXT结构的指针。

lParamL [out]:指向KP_KEYPROV_KEY结构的指针。

您应该KP_KEYPROV_KEYlParamL中填写结构以返回密钥。

此消息是消息的扩展版本KPM_KEYPROV_QUERY_KEY 。它的lParamW是一个指向a的指针KP_KEYPROV_CONTEXT,它包含有关所请求的键和上下文的更多信息。

你的插件应该回复KPM_KEYPROV_QUERY_KEY 或KPM_KEYPROV_QUERY_KEY_EX

信息  KP_KEYPROV_INFO 结构体

您提供的每个密钥(证书,智能卡,……)必须 通过填写lParamL中的结构来响应KPM_KEYPROV_QUERY_INFO_FIRSTKPM_KEYPROV_QUERY_INFO_NEXT消息进行注册。此结构如下所示:

  • DWORD dwFlags:保留供将来使用,必须为0。
  • LPCTSTR lpName:密钥的唯一显示名称。
  • DWORD dwImageIndex:组合框中显示的图标的索引。
  • DWORD dwReserved:保留供将来使用,必须为0。

lpName当KeePass尝试从中读取时,确保返回的指针仍然有效。当KeePass读取指针时,消​​息处理函数已经完成,因此您应该将名称存储在某个全局/静态位置。

图标ID指定组合框中使用的KeePass内置图标列表中图标的索引。不支持自定义图标。

信息  归还钥匙 KP_KEYPROV_KEY

KPM_KEYPROV_QUERY_KEY消息中,您需要通过填写KP_KEYPROV_KEY结构 来返回实际的密钥lParamL

  • DWORD dwType:保留供将来使用,必须为0。
  • DWORD dwFormat:保留供将来使用,必须为0。
  • LPVOID lpData:关键数据指针。
  • DWORD dwDataSize:键的大小(lpData),以字节为单位。
  • DWORD dwReserved:保留供将来使用,必须为0。

lpData当KeePass尝试从中读取时,确保返回的指针仍然有效。当KeePass读取指针时,消​​息处理功能已经完成,因此您应该将关键数据存储在某个全局/静态位置。

您可以在收到KPM_KEYPROV_FINALIZE消息时清理全局/静态内存 (当对话框关闭且KeePass已成功复制您提供的密钥时发送消息)。强烈建议您在释放密钥内存之前将其归零。

上一页:
下一页:


沪ICP备19023926号-2 Copyright © 2003-2019 Dominik Reichl, [联系我们 / 版本说明] [团队 & 隐私政策]