微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Microsoft Crypto API禁用使用RSAES-OAEP密钥传输algorithm

我正在使用CryptEncryptMessage来生成一个PKCS#7封装的消息。 我使用szOID_NIST_AES256_CBC作为encryptionalgorithm。

生成的消息似乎是有效的,但密钥传输algorithm的RSAES-OAEP在野外有限的支持(Thunderbird,OpenSSL SMIME模块等众多不支持它的)。

我想让CAPI恢复到旧的RSAEncryptionencryption密钥传输。

有没有办法做到这一点,我可以恢复到低级消息传递函数,如果有一种方法,而不是使用CryptEncryptMessage但我找不到一种方法,即使使用低级函数

用cygwin的Git存储https密码

用于在服务器上存储Openssl密码的安全选项(Linux,Python,CherryPy)

如何在Linux上可靠地存储密码

Active Directory如何模拟用户login并更改密码

Windows Server 2008 R2的密码

码:

CRYPT_ENCRYPT_MESSAGE_Para EncryptMessageParams; EncryptMessageParams.cbSize = sizeof(CMSG_ENVELOPED_ENCODE_INFO); EncryptMessageParams.dwMsgEncodingType = PKCS_7_ASN_ENCODING; EncryptMessageParams.ContentEncryptionAlgorithm.pszObjId = szOID_NIST_AES256_CBC; EncryptMessageParams.ContentEncryptionAlgorithm.Parameters.cbData = 0; EncryptMessageParams.ContentEncryptionAlgorithm.Parameters.pbData = 0; EncryptMessageParams.hCryptProv = NULL; EncryptMessageParams.pvEncryptionAuxInfo = NULL; EncryptMessageParams.dwFlags = 0; EncryptMessageParams.dwInnerContentType = 0; BYTE pbEncryptedBlob[640000]; DWORD pcbEncryptedBlob = 640000; BOOL retval = CryptEncryptMessage(&EncryptMessageParams,cRecipientCert,pRecipCertContextArray,pbMsgText,dwMsgTextSize,pbEncryptedBlob,&pcbEncryptedBlob);

如何在Windows上重置Ubuntu的pipe理员密码

用户设置密码,忽略密码策略

Windows无人参与安装 – Unattended.xml AdministratorPasswordencryption/哈希

黑客可以攻击一个网站的FTP,SSH和/或.htaccess文件吗?

在linux上添加bash脚本来创build用户

密钥传输算法处理起来有点棘手,可能无法达到目的(我看到你注意到,你希望CAPI支持RSAEncryption ;相信我,我也是)。 它看起来像你已经检测到你的问题的大部分 – 生成的消息显示是有效的,但是你的方法使得有必要使用CryptEncryptMessage ,从长远来看,这将不会工作得很好。

第1步 – 检查代码

CRYPT_ENCRYPT_MESSAGE_Para EncryptMessageParams; EncryptMessageParams.cbSize = sizeof(CMSG_ENVELOPED_ENCODE_INFO); EncryptMessageParams.dwMsgEncodingType = PKCS_7_ASN_ENCODING; EncryptMessageParams.ContentEncryptionAlgorithm.pszObjId = szOID_NIST_AES256_CBC; EncryptMessageParams.ContentEncryptionAlgorithm.Parameters.cbData = 0; EncryptMessageParams.ContentEncryptionAlgorithm.Parameters.pbData = 0; EncryptMessageParams.hCryptProv = NULL; EncryptMessageParams.pvEncryptionAuxInfo = NULL; EncryptMessageParams.dwFlags = 0; EncryptMessageParams.dwInnerContentType = 0; BYTE pbEncryptedBlob[640000]; DWORD pcbEncryptedBlob = 640000; BOOL retval = CryptEncryptMessage(&EncryptMessageParams,&pcbEncryptedBlob);

很基本,不是吗? 尽管高效,但并没有真正解决问题。 如果你看看这个:

EncryptMessageParams.dwFlags = 0; EncryptMessageParams.dwInnerContentType = 0;

你会看到它是预定义的,但只用于retval的定义。 但是,我可以肯定地认为这是一个微型优化,如果我们要重写代码,那么这个优化并不是很有用。 不过,我已经概述了在不重新编码的情况下集成这个基本步骤(所以你可以继续使用相同的参数):

第2步 – 编辑参数

正如@owlstead在他的评论中提到的,Crypto API不是非常用户友好的。 然而,你用有限的资源做了很棒的工作。 你想添加的是一个加密枚举提供商,以帮助缩小密钥。 确保您有Microsoft Base Cryptographic Provider版本1.0或Microsoft Enhanced Cryptographic Provider版本1.0以有效地使用这些。 否则,你需要添加如下功能

DWORD cbName; DWORD dwType; DWORD dwIndex; CHAR *pszName = NULL; (regular crypt calls here)

这主要用于防止NTE_BAD_FLAGS错误,尽管从技术上讲,您可以通过更低级的声明来避免这种错误。 如果你想的话,你也可以创建一个全新的散列(尽管只有在上述实现不能缩放到时间/速度的必要因素时才需要)。

DWORD dwBufferLen = strlen((char *)pbBuffer)+1*(0+5); HCRYPTHASH hHash; HCRYPTKEY hKey; HCRYPTKEY hPubKey; BYTE *pbKeyBlob; BYTE *pbSignature; DWORD dwSigLen; DWORD dwBlobLen; (use hash as normal w/ crypt calls and the pbKeyBlobs/Signatures)

在继续之前,请务必写出这段代码。 你可以很容易地这样做:

if(CryptAcquireContext(&hProv,NULL,PROV_RSA_FULL,0)) { printf("CSP context acquired.n"); }

如果您正在记录或释放,可能需要添加一个void MyHandleError(char *s)来捕获错误,以便编辑但失败的人可以快速捕获它。

顺便说一句,你第一次运行它,你将不得不创建一个新的集合,因为没有认值。 下面是一个很好的单行程序,可以弹出一个if :

CryptAcquireContext(&hCryptProv,CRYPT_NEWKEYSET)

请记住,同步服务器资源的效率不如我在第一步中所建议的那样重新工作。 这是我将在下面解释:

第3步 – 重新编码和重新启动

作为一名程序员,重新编码似乎是浪费时间,但从长远来看,它肯定会帮助你。 请记住,在编码/同步时,您仍然必须在自定义参数中编码; 我不会像婴儿一样亲手喂你所有的代码。 向您展示基本的轮廓应该足够了。

我肯定假设你正在尝试处理特定CSP中当前用户的密钥容器; 否则,我真的看不到这个用法。 如果不是的话,你可以做一些基本的编辑来适应你的需求。

请记住,我们将通过使用CryptReleaseContext来绕过CryptEncryptMessage , CryptReleaseContext直接释放由CryptAcquireContext函数获取的句柄。 微软在CAC上的标准如下:

BOOL WINAPI CryptAcquireContext( _Out_ HCRYPTPROV *PHProv,_In_ LPCTSTR pszContainer,_In_ LPCTSTR pszProvider,_In_ DWORD dwProvType,_In_ DWORD dwFlags );

请注意,如果您使用的是用户界面,微软会斥责你:

如果CSP必须显示要操作的UI,则调用将失败,并且将NTE_SILENT_CONTEXT错误代码设置为最后一个错误。 另外,如果使用CRYPT_USER_PROTECTED标志对CryptGenKey进行调用,并且使用CRYPT_SILENT标志获取的上下文,则调用将失败,并且CSP会设置NTE_SILENT_CONTEXT。

这主要是服务器代码,当有多个连接时, ERROR_BUSY肯定会显示新用户,特别是那些延迟较高的连接。 超过300毫秒只会导致一个NTE_BAD_KEYSET_ParaM或类似的被调用,由于超时没有收到正确的错误。 (传输问题,有我的人?)

除非你担心多个DLL(由于NTE_PROVIDER_DLL_FAIL错误,这不支持这个),所以设置为获取crypt服务的基本设置如下(直接从微软的例子中复制):

if (GetLastError() == NTE_BAD_KEYSET) { if(CryptAcquireContext( &hCryptProv,UserName,CRYPT_NEWKEYSET)) { printf("A new key container has been created.n"); } else { printf("Could not create a new key container.n"); exit(1); } } else { printf("A cryptographic service handle Could not be " "acquired.n"); exit(1); }

然而,看起来很简单,你肯定不希望把这个问题传递给密钥交换算法(或者其他任何你需要处理的)。 除非您使用对称会话密钥(Diffie-Hellman / KEA),否则交换密钥对可用于加密会话密钥,以便它们可以安全地存储并与其他用户交换。

一个名叫John Howard的人写了一个很好的Hyper-V远程管理配置工具(HVRemote),这是这里讨论的技术的一个大集合。 除了使用基本的crypt和keypairs,它们还可以用来允许ANONYMOUS logoN远程DCOM访问( cscript hvremote.wsf ,具体而言)。 你可以在他的博客中看到他最新的地下室中的许多功能和技巧(你必须缩小查询范围):

http://blogs.technet.com/b/jhoward/

如果您需要更多帮助,请留下评论或要求私下聊天。

结论

尽管一旦您意识到散列的基本服务器端方法以及客户端如何获取“隐藏”,但这很简单,您会质疑为什么您甚至在传输过程中尝试了加密。 但是,如果没有客户端的加密,加密一定是传输已经散列的唯一安全的方式。

虽然你可能会争辩说,数据包可以被解密和散列盐,考虑到,这两个内部将不得不被处理和存储在正确的时间和顺序必要重新哈希clientside。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐