一种简单的登录设计,密码保存在本地。(直接MD5不安全,别人可以更换本地的密码,得再加一层算法就相对安全一点)
当然也可以用加密机或专门存密码的系统来实现,就过于复杂。
目标:1、为了避免密码直接写在代码里或本地,通过软件评估报告。2、知道初始密码的人,才能改密码及登录。只知道登录密码只能登录。
密码
1.初始密码暂时先用这个ASDEedsa@123321,转为MD5写在应用里:5329B69272930C2F9E9F743B11215AFD。修改的密码用MD5计算后保存到注册表 https://www.sojson.com/md5/
2.首次登录或点重置密码先输入初始密码,再修改密码,再进入主界面。再次登录就可以使用新密码。
3. 密码规则:数字,字母,大小写,及符号组成的不少于6位的密码。
4. 如果工具在idle 状态下15分钟以上没动,再用工具时,需要用户重新Login。
界面
条件1实现:https://blog.csdn.net/chenhao0568/article/details/134654801?spm=1001.2014.3001.5501
条件2实现:逻辑了。
条件3实现:https://blog.csdn.net/chenhao0568/article/details/134654768?spm=1001.2014.3001.5501
条件4实现:https://blog.csdn.net/chenhao0568/article/details/134654747?spm=1001.2014.3001.5501
cpp
// CPasswordDlg.cpp: 实现文件
//
#include "stdafx.h"
#include "afxdialogex.h"
#include "CPasswordDlg.h"
#include "Resource.h"
static int status = 0;//0输入初始密码 1输入新密码 2正常登录(注册表有密码)
static CString registerPassword = "";
#include "md5.h"
#define MD5_INIT_PASSWORD "5329B69272930C2F9E9F743B11215AFD"
#define KEY_PATH _T("Software\\MyApplication5329B69272930C2F9E9F743B11215AFD")
#define VALUE_NAME _T("PW_MD5")
void WriteRegistryValue(const CString& keyPath, const CString& valueName, const CString& value) {
CRegKey key;
if (key.Create(HKEY_CURRENT_USER, keyPath) == ERROR_SUCCESS) {
key.SetStringValue(valueName, value);
key.Close();
}
}
CString ReadRegistryValue(const CString& keyPath, const CString& valueName) {
CString value;
CRegKey key;
if (key.Open(HKEY_CURRENT_USER, keyPath, KEY_READ) == ERROR_SUCCESS) {
TCHAR buffer[256];
ULONG len = 256;
if (key.QueryStringValue(valueName, buffer, &len) == ERROR_SUCCESS) {
value = buffer;
}
key.Close();
}
return value;
}
bool IsPasswordValid(const CString& password) {
if (password.GetLength() < 6) {
return false; // 密码长度不足6位
}
bool hasDigit = false;
bool hasLower = false;
bool hasUpper = false;
bool hasSymbol = false;
for (int i = 0; i < password.GetLength(); ++i) {
TCHAR ch = password[i];
if (_istdigit(ch)) {
hasDigit = true;
}
else if (_istlower(ch)) {
hasLower = true;
}
else if (_istupper(ch)) {
hasUpper = true;
}
else if (_istpunct(ch)) {
hasSymbol = true;
}
}
return hasDigit && hasLower && hasUpper && hasSymbol;
}
// CPasswordDlg 对话框
IMPLEMENT_DYNAMIC(CPasswordDlg, CDialogEx)
CPasswordDlg::CPasswordDlg(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_DIALOG1, pParent)
{
}
CPasswordDlg::~CPasswordDlg()
{
}
void CPasswordDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CPasswordDlg, CDialogEx)
ON_BN_CLICKED(IDOK, &CPasswordDlg::OnBnClickedOk)
ON_BN_CLICKED(IDR_GERTEC_ADBKEY11, &CPasswordDlg::OnBnClickedGertecAdbkey11)
END_MESSAGE_MAP()
// CPasswordDlg 消息处理程序
void CPasswordDlg::OnBnClickedOk()
{
CString password="";
GetDlgItem(IDC_EDIT1)->GetWindowText(password);
unsigned char out[MD5_MAX_LEN] = { 0 };
md5((const unsigned char*)password.GetBuffer(), strlen(password), out);
char hex_md5[MD5_MAX_LEN] = { 0 };
byteToHexStr(out, 16, (char*)hex_md5);
if (status == 0)
{
if (memcmp(MD5_INIT_PASSWORD, hex_md5, strlen(MD5_INIT_PASSWORD)) == 0)
{
status = 1;
this->SetWindowText("Please enter a new password");
}
else
{
AfxMessageBox("Password error");
}
GetDlgItem(IDC_EDIT1)->SetWindowText("");
GetDlgItem(IDC_EDIT1)->SetFocus();
return;
}
else if (status == 1)
{
//check and write
if (IsPasswordValid(password))
{
memcpy(registerPassword.GetBuffer(strlen(MD5_INIT_PASSWORD)), hex_md5, strlen(MD5_INIT_PASSWORD)); registerPassword.ReleaseBuffer();
WriteRegistryValue(KEY_PATH, VALUE_NAME, registerPassword);
AfxMessageBox("Password set successfully");
CDialogEx::OnOK();
}
else
{
AfxMessageBox("Password error,the password must be at least 6 characters long and include numbers, letters, both upper and lower case, and symbols.");
GetDlgItem(IDC_EDIT1)->SetWindowText("");
GetDlgItem(IDC_EDIT1)->SetFocus();
}
}
else
{
if (memcmp(registerPassword, hex_md5, strlen(MD5_INIT_PASSWORD)) == 0)
{
CDialogEx::OnOK();
}
else
{
AfxMessageBox("Password error");
GetDlgItem(IDC_EDIT1)->SetWindowText("");
GetDlgItem(IDC_EDIT1)->SetFocus();
}
}
}
BOOL CPasswordDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
//WriteRegistryValue(KEY_PATH, VALUE_NAME, MD5_INIT_PASSWORD);
//WriteRegistryValue(KEY_PATH, VALUE_NAME, "");
registerPassword = ReadRegistryValue(KEY_PATH, VALUE_NAME); registerPassword.ReleaseBuffer();
if (registerPassword.GetLength() > 0)
{
status = 2;
this->SetWindowText("Please input password");
}
else
{
status = 0;
this->SetWindowTextA("Please enter the initial password");
}
return TRUE; // return TRUE unless you set the focus to a control
// 异常: OCX 属性页应返回 FALSE
}
void CPasswordDlg::OnBnClickedGertecAdbkey11()
{
status = 0;
this->SetWindowTextA("Please enter the initial password");
GetDlgItem(IDC_EDIT1)->SetWindowText("");
GetDlgItem(IDC_EDIT1)->SetFocus();
}
再加一层算法,比如写前按一组随机的数字相加,读后再反操作。
哈希算法(Hash Algorithm)是一种从任意长度的消息中创建小的固定长度"哈希值"(或"哈希代码")的算法。哈希算法在计算机科学中有着广泛的应用,例如数据检索、安全加密和数据完整性验证。以下是一些主要的特点和应用场景:
特点
- 确定性:相同的输入总是产生相同的哈希值。
- 高效计算:能够快速计算出任意输入数据的哈希值。
- 抗碰撞性:找到两个不同的输入但产生相同哈希值的情况非常困难。
- 原像抗性:从哈希值很难反推出原始输入数据。
应用场景
- 数据存储:数据库和其他数据结构(如哈希表)使用哈希算法快速定位和检索数据。
- 安全加密:在密码学中,哈希函数用于加密数据,确保信息传输的安全。
- 数据完整性验证:用于检查文件或数据传输过程中是否被篡改。
- 数字签名:用于验证文件或消息的真实性。
常见哈希算法
- MD5:一种广泛使用的哈希算法,但现在被认为是不安全的。
- SHA系列(如SHA-256):提供更高安全性的哈希算法,广泛用于加密货币和网络安全。
- CRC32:主要用于检测数据传输或存储过程中的错误。
哈希算法的选择取决于具体的应用需求,如对速度、安全性或抗碰撞性的不同要求。在安全相关的应用中,选择一个经过时间检验且被广泛认可的安全哈希算法尤为重要。