一种简单的登录设计,密码保存在本地。(直接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
// 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 writeif (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:主要用于检测数据传输或存储过程中的错误。
哈希算法的选择取决于具体的应用需求,如对速度、安全性或抗碰撞性的不同要求。在安全相关的应用中,选择一个经过时间检验且被广泛认可的安全哈希算法尤为重要。