论坛用的是调用md5 class的ComputeHash方法直接生成的。
现在想在c++中也用md5加密和c#里统一起来。
atl server的c++不是托管代码所以不支持md5 class的ComputeHash方法直接生成。
现在问题是C#中md5 class的ComputeHash方法直接生成密码时,它默认的salt是多少(因为数据库中不需要保存salt,所以肯定不是随机生成的)谢谢各位大侠。
6 个解决方案
#1
http://www.obviex.com/samples/EncryptionWithSalt.aspx
#2
Md5算法已经被破解,不要再用它了。用SHA1吧。
#3
SHA1也不远了
#4
Visual C++ 概念:添加功能
确保用户密码的安全
在这一步中,您将创建一些 Helper 函数以简化散列和比较密码的过程。这些代码将使用 ATL Server 提供的加密类。
为加密的 Helper 函数创建新的头文件
在解决方案资源管理器中,右击 Tutorial 项目。
在快捷菜单上,单击“添加”,然后单击“添加新项”。
将出现“添加新项”对话框。
在“模板”窗格中,单击“头文件 (.h)”,并在“名称”框中输入“Encrypt.h”。
单击“打开”。
Visual Studio 在磁盘上创建文件并将它添加到您的项目中。
将下列代码添加到 Encrypt.h:
#pragma once
#include <atlcrypt.h>
namespace VCUE
{
inline HRESULT EnsureAcquire(
CCryptProv& prov,
LPCTSTR pszContainer = NULL,
LPCTSTR pszProvider = MS_DEF_PROV,
DWORD dwProvType = PROV_RSA_FULL,
DWORD dwFlags = CRYPT_VERIFYCONTEXT | CRYPT_SILENT
)
{
HRESULT hr = prov.Initialize(dwProvType, pszContainer,
pszProvider, dwFlags);
if (hr == NTE_KEYSET_NOT_DEF)
hr = prov.Initialize(dwProvType, pszContainer, pszProvider,
dwFlags | CRYPT_NEWKEYSET);
return hr;
}
}
EnsureAcquire 是初始化加密提供程序(一个提供加密函数的对象)的 Helper 函数。该函数通过设置下面两个标记,提供用于服务器应用程序的灵敏默认参数:一个是禁用加密提供程序可能向用户显示的任何用户界面的标记 (CRYPT_SILENT),另一个是通知提供程序不需要访问私钥的标记 (CRYPT_VERIFYCONTEXT)。该函数还确保在初始化因容器不存在而失败时尝试创建容器。有关更多信息,请参见 CCryptProv::Initialize。将下列代码添加到 Encrypt.h:
inline HRESULT CreateSaltedHash(
CCryptProv& Provider,
const BYTE* Secret, DWORD SecretLength,
const BYTE* Salt, DWORD SaltLength,
BYTE* Hash, DWORD& HashLength
)
{
HRESULT hr = E_FAIL;
HCRYPTHASH hHash = 0;
if (CryptCreateHash(Provider.GetHandle(), CALG_MD5,
0, 0, &hHash))
{
CCryptHash oHash(hHash, TRUE);
hr = oHash.AddData(Secret, SecretLength);
if (SUCCEEDED(hr))
{
hr = oHash.AddData(Salt, SaltLength);
if (SUCCEEDED(hr))
{
DWORD Size = 0;
hr = oHash.GetSize(&Size);
if (SUCCEEDED(hr))
{
if (Size <= HashLength)
hr = oHash.GetValue(Hash, &HashLength);
else
hr = E_OUTOFMEMORY;
}
}
}
}
return hr;
}
CreateSaltedHash 使用 MD5 哈希算法从机密(如密码)和 salt(一个随机数)生成哈希。这些代码创建 CCryptHash 对象,将机密和 salt 添加到哈希,然后在调用方所提供缓冲区的大小可以容纳哈希值时获取该值。将下列代码添加到 Encrypt.h:
inline HRESULT HashSecret(
const BYTE* Secret, DWORD SecretLength,
BYTE* Salt, DWORD& SaltLength,
BYTE* Hash, DWORD& HashLength
)
{
CCryptProv Provider;
HRESULT hr = EnsureAcquire(Provider);
if (SUCCEEDED(hr))
{
hr = Provider.GenRandom(SaltLength, Salt);
if (SUCCEEDED(hr))
{
hr = CreateSaltedHash( Provider,
Secret, SecretLength,
Salt, SaltLength,
Hash, HashLength);
}
}
return hr;
}
HashSecret 获取机密并返回 salt 以及通过合并机密和 salt 所生成的哈希。它包装获取加密提供程序所需的调用,生成随机 salt 值并在单个函数中创建哈希。将下列代码添加到 Encrypt.h:
inline HRESULT CompareSecret(
const BYTE* Secret, DWORD SecretLength,
const BYTE* Salt, DWORD SaltLength,
const BYTE* Hash, DWORD HashLength
)
{
DWORD CalculatedHashLength = HashLength;
BYTE* CalculatedHash = new BYTE[HashLength];
if (!CalculatedHash)
return E_OUTOFMEMORY;
CCryptProv Provider;
HRESULT hr = EnsureAcquire(Provider);
if (SUCCEEDED(hr))
{
hr = CreateSaltedHash( Provider,
Secret, SecretLength,
Salt, SaltLength,
CalculatedHash, CalculatedHashLength);
if (SUCCEEDED(hr))
{
hr = S_FALSE;
if (CalculatedHashLength == HashLength)
{
if (0 == memcmp(Hash, CalculatedHash, HashLength))
hr = S_OK;
}
}
}
delete [] CalculatedHash;
return hr;
}
} // namespace VCUE
CompareSecret 接受机密、salt 和哈希。如果机密和 salt 的散列结果与传递给该函数的哈希相同,则 CompareSecret 返回 S_OK。如果哈希不同,则该函数返回 S_FALSE。否则,该函数返回错误 HRESULT。
这些函数就是验证用户密码所需要的全部函数。HashSecret 用于从用户的密码生成将存储在数据库中的 salt 和哈希。CompareSecret 将存储的 salt 和哈希与密码进行比较并通知您它们是否匹配。
以上是msdn里的例子,可是我按照它写了个程序,可是生成不了密码,症状是密码改变,生成的字符串不变。
求大侠们,帮帮忙,看看怎么回事,要整合,上面程序该怎么改。
确保用户密码的安全
在这一步中,您将创建一些 Helper 函数以简化散列和比较密码的过程。这些代码将使用 ATL Server 提供的加密类。
为加密的 Helper 函数创建新的头文件
在解决方案资源管理器中,右击 Tutorial 项目。
在快捷菜单上,单击“添加”,然后单击“添加新项”。
将出现“添加新项”对话框。
在“模板”窗格中,单击“头文件 (.h)”,并在“名称”框中输入“Encrypt.h”。
单击“打开”。
Visual Studio 在磁盘上创建文件并将它添加到您的项目中。
将下列代码添加到 Encrypt.h:
#pragma once
#include <atlcrypt.h>
namespace VCUE
{
inline HRESULT EnsureAcquire(
CCryptProv& prov,
LPCTSTR pszContainer = NULL,
LPCTSTR pszProvider = MS_DEF_PROV,
DWORD dwProvType = PROV_RSA_FULL,
DWORD dwFlags = CRYPT_VERIFYCONTEXT | CRYPT_SILENT
)
{
HRESULT hr = prov.Initialize(dwProvType, pszContainer,
pszProvider, dwFlags);
if (hr == NTE_KEYSET_NOT_DEF)
hr = prov.Initialize(dwProvType, pszContainer, pszProvider,
dwFlags | CRYPT_NEWKEYSET);
return hr;
}
}
EnsureAcquire 是初始化加密提供程序(一个提供加密函数的对象)的 Helper 函数。该函数通过设置下面两个标记,提供用于服务器应用程序的灵敏默认参数:一个是禁用加密提供程序可能向用户显示的任何用户界面的标记 (CRYPT_SILENT),另一个是通知提供程序不需要访问私钥的标记 (CRYPT_VERIFYCONTEXT)。该函数还确保在初始化因容器不存在而失败时尝试创建容器。有关更多信息,请参见 CCryptProv::Initialize。将下列代码添加到 Encrypt.h:
inline HRESULT CreateSaltedHash(
CCryptProv& Provider,
const BYTE* Secret, DWORD SecretLength,
const BYTE* Salt, DWORD SaltLength,
BYTE* Hash, DWORD& HashLength
)
{
HRESULT hr = E_FAIL;
HCRYPTHASH hHash = 0;
if (CryptCreateHash(Provider.GetHandle(), CALG_MD5,
0, 0, &hHash))
{
CCryptHash oHash(hHash, TRUE);
hr = oHash.AddData(Secret, SecretLength);
if (SUCCEEDED(hr))
{
hr = oHash.AddData(Salt, SaltLength);
if (SUCCEEDED(hr))
{
DWORD Size = 0;
hr = oHash.GetSize(&Size);
if (SUCCEEDED(hr))
{
if (Size <= HashLength)
hr = oHash.GetValue(Hash, &HashLength);
else
hr = E_OUTOFMEMORY;
}
}
}
}
return hr;
}
CreateSaltedHash 使用 MD5 哈希算法从机密(如密码)和 salt(一个随机数)生成哈希。这些代码创建 CCryptHash 对象,将机密和 salt 添加到哈希,然后在调用方所提供缓冲区的大小可以容纳哈希值时获取该值。将下列代码添加到 Encrypt.h:
inline HRESULT HashSecret(
const BYTE* Secret, DWORD SecretLength,
BYTE* Salt, DWORD& SaltLength,
BYTE* Hash, DWORD& HashLength
)
{
CCryptProv Provider;
HRESULT hr = EnsureAcquire(Provider);
if (SUCCEEDED(hr))
{
hr = Provider.GenRandom(SaltLength, Salt);
if (SUCCEEDED(hr))
{
hr = CreateSaltedHash( Provider,
Secret, SecretLength,
Salt, SaltLength,
Hash, HashLength);
}
}
return hr;
}
HashSecret 获取机密并返回 salt 以及通过合并机密和 salt 所生成的哈希。它包装获取加密提供程序所需的调用,生成随机 salt 值并在单个函数中创建哈希。将下列代码添加到 Encrypt.h:
inline HRESULT CompareSecret(
const BYTE* Secret, DWORD SecretLength,
const BYTE* Salt, DWORD SaltLength,
const BYTE* Hash, DWORD HashLength
)
{
DWORD CalculatedHashLength = HashLength;
BYTE* CalculatedHash = new BYTE[HashLength];
if (!CalculatedHash)
return E_OUTOFMEMORY;
CCryptProv Provider;
HRESULT hr = EnsureAcquire(Provider);
if (SUCCEEDED(hr))
{
hr = CreateSaltedHash( Provider,
Secret, SecretLength,
Salt, SaltLength,
CalculatedHash, CalculatedHashLength);
if (SUCCEEDED(hr))
{
hr = S_FALSE;
if (CalculatedHashLength == HashLength)
{
if (0 == memcmp(Hash, CalculatedHash, HashLength))
hr = S_OK;
}
}
}
delete [] CalculatedHash;
return hr;
}
} // namespace VCUE
CompareSecret 接受机密、salt 和哈希。如果机密和 salt 的散列结果与传递给该函数的哈希相同,则 CompareSecret 返回 S_OK。如果哈希不同,则该函数返回 S_FALSE。否则,该函数返回错误 HRESULT。
这些函数就是验证用户密码所需要的全部函数。HashSecret 用于从用户的密码生成将存储在数据库中的 salt 和哈希。CompareSecret 将存储的 salt 和哈希与密码进行比较并通知您它们是否匹配。
以上是msdn里的例子,可是我按照它写了个程序,可是生成不了密码,症状是密码改变,生成的字符串不变。
求大侠们,帮帮忙,看看怎么回事,要整合,上面程序该怎么改。
#5
用sha512 应当是安全的了吧 呵呵
#6
学习啊
#1
http://www.obviex.com/samples/EncryptionWithSalt.aspx
#2
Md5算法已经被破解,不要再用它了。用SHA1吧。
#3
SHA1也不远了
#4
Visual C++ 概念:添加功能
确保用户密码的安全
在这一步中,您将创建一些 Helper 函数以简化散列和比较密码的过程。这些代码将使用 ATL Server 提供的加密类。
为加密的 Helper 函数创建新的头文件
在解决方案资源管理器中,右击 Tutorial 项目。
在快捷菜单上,单击“添加”,然后单击“添加新项”。
将出现“添加新项”对话框。
在“模板”窗格中,单击“头文件 (.h)”,并在“名称”框中输入“Encrypt.h”。
单击“打开”。
Visual Studio 在磁盘上创建文件并将它添加到您的项目中。
将下列代码添加到 Encrypt.h:
#pragma once
#include <atlcrypt.h>
namespace VCUE
{
inline HRESULT EnsureAcquire(
CCryptProv& prov,
LPCTSTR pszContainer = NULL,
LPCTSTR pszProvider = MS_DEF_PROV,
DWORD dwProvType = PROV_RSA_FULL,
DWORD dwFlags = CRYPT_VERIFYCONTEXT | CRYPT_SILENT
)
{
HRESULT hr = prov.Initialize(dwProvType, pszContainer,
pszProvider, dwFlags);
if (hr == NTE_KEYSET_NOT_DEF)
hr = prov.Initialize(dwProvType, pszContainer, pszProvider,
dwFlags | CRYPT_NEWKEYSET);
return hr;
}
}
EnsureAcquire 是初始化加密提供程序(一个提供加密函数的对象)的 Helper 函数。该函数通过设置下面两个标记,提供用于服务器应用程序的灵敏默认参数:一个是禁用加密提供程序可能向用户显示的任何用户界面的标记 (CRYPT_SILENT),另一个是通知提供程序不需要访问私钥的标记 (CRYPT_VERIFYCONTEXT)。该函数还确保在初始化因容器不存在而失败时尝试创建容器。有关更多信息,请参见 CCryptProv::Initialize。将下列代码添加到 Encrypt.h:
inline HRESULT CreateSaltedHash(
CCryptProv& Provider,
const BYTE* Secret, DWORD SecretLength,
const BYTE* Salt, DWORD SaltLength,
BYTE* Hash, DWORD& HashLength
)
{
HRESULT hr = E_FAIL;
HCRYPTHASH hHash = 0;
if (CryptCreateHash(Provider.GetHandle(), CALG_MD5,
0, 0, &hHash))
{
CCryptHash oHash(hHash, TRUE);
hr = oHash.AddData(Secret, SecretLength);
if (SUCCEEDED(hr))
{
hr = oHash.AddData(Salt, SaltLength);
if (SUCCEEDED(hr))
{
DWORD Size = 0;
hr = oHash.GetSize(&Size);
if (SUCCEEDED(hr))
{
if (Size <= HashLength)
hr = oHash.GetValue(Hash, &HashLength);
else
hr = E_OUTOFMEMORY;
}
}
}
}
return hr;
}
CreateSaltedHash 使用 MD5 哈希算法从机密(如密码)和 salt(一个随机数)生成哈希。这些代码创建 CCryptHash 对象,将机密和 salt 添加到哈希,然后在调用方所提供缓冲区的大小可以容纳哈希值时获取该值。将下列代码添加到 Encrypt.h:
inline HRESULT HashSecret(
const BYTE* Secret, DWORD SecretLength,
BYTE* Salt, DWORD& SaltLength,
BYTE* Hash, DWORD& HashLength
)
{
CCryptProv Provider;
HRESULT hr = EnsureAcquire(Provider);
if (SUCCEEDED(hr))
{
hr = Provider.GenRandom(SaltLength, Salt);
if (SUCCEEDED(hr))
{
hr = CreateSaltedHash( Provider,
Secret, SecretLength,
Salt, SaltLength,
Hash, HashLength);
}
}
return hr;
}
HashSecret 获取机密并返回 salt 以及通过合并机密和 salt 所生成的哈希。它包装获取加密提供程序所需的调用,生成随机 salt 值并在单个函数中创建哈希。将下列代码添加到 Encrypt.h:
inline HRESULT CompareSecret(
const BYTE* Secret, DWORD SecretLength,
const BYTE* Salt, DWORD SaltLength,
const BYTE* Hash, DWORD HashLength
)
{
DWORD CalculatedHashLength = HashLength;
BYTE* CalculatedHash = new BYTE[HashLength];
if (!CalculatedHash)
return E_OUTOFMEMORY;
CCryptProv Provider;
HRESULT hr = EnsureAcquire(Provider);
if (SUCCEEDED(hr))
{
hr = CreateSaltedHash( Provider,
Secret, SecretLength,
Salt, SaltLength,
CalculatedHash, CalculatedHashLength);
if (SUCCEEDED(hr))
{
hr = S_FALSE;
if (CalculatedHashLength == HashLength)
{
if (0 == memcmp(Hash, CalculatedHash, HashLength))
hr = S_OK;
}
}
}
delete [] CalculatedHash;
return hr;
}
} // namespace VCUE
CompareSecret 接受机密、salt 和哈希。如果机密和 salt 的散列结果与传递给该函数的哈希相同,则 CompareSecret 返回 S_OK。如果哈希不同,则该函数返回 S_FALSE。否则,该函数返回错误 HRESULT。
这些函数就是验证用户密码所需要的全部函数。HashSecret 用于从用户的密码生成将存储在数据库中的 salt 和哈希。CompareSecret 将存储的 salt 和哈希与密码进行比较并通知您它们是否匹配。
以上是msdn里的例子,可是我按照它写了个程序,可是生成不了密码,症状是密码改变,生成的字符串不变。
求大侠们,帮帮忙,看看怎么回事,要整合,上面程序该怎么改。
确保用户密码的安全
在这一步中,您将创建一些 Helper 函数以简化散列和比较密码的过程。这些代码将使用 ATL Server 提供的加密类。
为加密的 Helper 函数创建新的头文件
在解决方案资源管理器中,右击 Tutorial 项目。
在快捷菜单上,单击“添加”,然后单击“添加新项”。
将出现“添加新项”对话框。
在“模板”窗格中,单击“头文件 (.h)”,并在“名称”框中输入“Encrypt.h”。
单击“打开”。
Visual Studio 在磁盘上创建文件并将它添加到您的项目中。
将下列代码添加到 Encrypt.h:
#pragma once
#include <atlcrypt.h>
namespace VCUE
{
inline HRESULT EnsureAcquire(
CCryptProv& prov,
LPCTSTR pszContainer = NULL,
LPCTSTR pszProvider = MS_DEF_PROV,
DWORD dwProvType = PROV_RSA_FULL,
DWORD dwFlags = CRYPT_VERIFYCONTEXT | CRYPT_SILENT
)
{
HRESULT hr = prov.Initialize(dwProvType, pszContainer,
pszProvider, dwFlags);
if (hr == NTE_KEYSET_NOT_DEF)
hr = prov.Initialize(dwProvType, pszContainer, pszProvider,
dwFlags | CRYPT_NEWKEYSET);
return hr;
}
}
EnsureAcquire 是初始化加密提供程序(一个提供加密函数的对象)的 Helper 函数。该函数通过设置下面两个标记,提供用于服务器应用程序的灵敏默认参数:一个是禁用加密提供程序可能向用户显示的任何用户界面的标记 (CRYPT_SILENT),另一个是通知提供程序不需要访问私钥的标记 (CRYPT_VERIFYCONTEXT)。该函数还确保在初始化因容器不存在而失败时尝试创建容器。有关更多信息,请参见 CCryptProv::Initialize。将下列代码添加到 Encrypt.h:
inline HRESULT CreateSaltedHash(
CCryptProv& Provider,
const BYTE* Secret, DWORD SecretLength,
const BYTE* Salt, DWORD SaltLength,
BYTE* Hash, DWORD& HashLength
)
{
HRESULT hr = E_FAIL;
HCRYPTHASH hHash = 0;
if (CryptCreateHash(Provider.GetHandle(), CALG_MD5,
0, 0, &hHash))
{
CCryptHash oHash(hHash, TRUE);
hr = oHash.AddData(Secret, SecretLength);
if (SUCCEEDED(hr))
{
hr = oHash.AddData(Salt, SaltLength);
if (SUCCEEDED(hr))
{
DWORD Size = 0;
hr = oHash.GetSize(&Size);
if (SUCCEEDED(hr))
{
if (Size <= HashLength)
hr = oHash.GetValue(Hash, &HashLength);
else
hr = E_OUTOFMEMORY;
}
}
}
}
return hr;
}
CreateSaltedHash 使用 MD5 哈希算法从机密(如密码)和 salt(一个随机数)生成哈希。这些代码创建 CCryptHash 对象,将机密和 salt 添加到哈希,然后在调用方所提供缓冲区的大小可以容纳哈希值时获取该值。将下列代码添加到 Encrypt.h:
inline HRESULT HashSecret(
const BYTE* Secret, DWORD SecretLength,
BYTE* Salt, DWORD& SaltLength,
BYTE* Hash, DWORD& HashLength
)
{
CCryptProv Provider;
HRESULT hr = EnsureAcquire(Provider);
if (SUCCEEDED(hr))
{
hr = Provider.GenRandom(SaltLength, Salt);
if (SUCCEEDED(hr))
{
hr = CreateSaltedHash( Provider,
Secret, SecretLength,
Salt, SaltLength,
Hash, HashLength);
}
}
return hr;
}
HashSecret 获取机密并返回 salt 以及通过合并机密和 salt 所生成的哈希。它包装获取加密提供程序所需的调用,生成随机 salt 值并在单个函数中创建哈希。将下列代码添加到 Encrypt.h:
inline HRESULT CompareSecret(
const BYTE* Secret, DWORD SecretLength,
const BYTE* Salt, DWORD SaltLength,
const BYTE* Hash, DWORD HashLength
)
{
DWORD CalculatedHashLength = HashLength;
BYTE* CalculatedHash = new BYTE[HashLength];
if (!CalculatedHash)
return E_OUTOFMEMORY;
CCryptProv Provider;
HRESULT hr = EnsureAcquire(Provider);
if (SUCCEEDED(hr))
{
hr = CreateSaltedHash( Provider,
Secret, SecretLength,
Salt, SaltLength,
CalculatedHash, CalculatedHashLength);
if (SUCCEEDED(hr))
{
hr = S_FALSE;
if (CalculatedHashLength == HashLength)
{
if (0 == memcmp(Hash, CalculatedHash, HashLength))
hr = S_OK;
}
}
}
delete [] CalculatedHash;
return hr;
}
} // namespace VCUE
CompareSecret 接受机密、salt 和哈希。如果机密和 salt 的散列结果与传递给该函数的哈希相同,则 CompareSecret 返回 S_OK。如果哈希不同,则该函数返回 S_FALSE。否则,该函数返回错误 HRESULT。
这些函数就是验证用户密码所需要的全部函数。HashSecret 用于从用户的密码生成将存储在数据库中的 salt 和哈希。CompareSecret 将存储的 salt 和哈希与密码进行比较并通知您它们是否匹配。
以上是msdn里的例子,可是我按照它写了个程序,可是生成不了密码,症状是密码改变,生成的字符串不变。
求大侠们,帮帮忙,看看怎么回事,要整合,上面程序该怎么改。
#5
用sha512 应当是安全的了吧 呵呵
#6
学习啊