前言
主要是最近特别想写一个保密的网站系统。然后自己大概考虑了一个实现方法,然后经过测试发现有效。后来在网上找有没有更好的解决方案,然后惊奇地发现这方面居然没有人来提供教程。
然后本菜鸡就把自己的方法放送出来,方便大家在进行各种开发的时候使用动态密码算法。
实现原理
其实整个原理是比较简单的。
比如说现在有两个设备,服务端和客户端。
两部设备同时拥有时钟和一套相同的算法。当用户需要一个新的动态密码时,两个设备会通过各自的时钟,使用相同的算法来计算出两个密码。此时,用户手中的密码应该是客户端的密码。在两个设备的时钟相同时,对应生成的密码也相同。用户输入客户端提供的密码到服务器进行验证,若密码相同,则验证通过。
所以现在需要模拟生成密码的算法。我在这里提供了一个很菜的算法,大家可以拿来参考一下。
编程实现
核心函数
这里面最核心的函数是ctime库中的两个函数:
time_t tt=time(NULL);
tm *t=localtime(&tt);
time函数用于获取系统时间,而localtime函数则将time_t数据转换成可读的数据。
读取时间的方法如下:
t->tm_year+1900 //年
t->tm_mon+1 //月
t->tm_mday //日
t->tm_hour //小时
t->tm_min //分钟
t->tm_sec //秒
使用这些数据来计算一个密码出来。
每隔一段时间修改一次
这个可以通过对秒整除和取余来实现。
比如说,我想让这个代码20秒换一次,那么我就可以:
sec=sec/code_time+1;
这样一来,sec变量中存储的值只有20秒才会变化一次。
主程序
安全验证
这个并不是必要的,只是为了防止任何人都能轻易使用这套程序。
//以下为全局内容
string password="123456";
string input()
{
char geted=getch();
string outed;
while(geted!=13)
{
cout<<"*";
outed+=geted;
geted=getch();
}
cout<<endl;
return outed;
}
//以下为主程序中的内容
cout<<"Current security code : UNKNOWN"<<endl;
cout<<"Code change : UNKNOWN"<<endl;
string check;
int timesss=1;
for(timesss=1;timesss<=3;timesss++)
{
cout<<"Security pass required : ";
check=input();
if(check==password) break;
else cout<<"[ERROR]Invalid pass! Chances remained : "<<3-timesss<<endl;
}
if(timesss>3)
{
cout<<"[DENIED]SECURITY PASS FAILED!"<<endl;
getch();
return 0;
}
这个小型密码安全验证提供三次输入密码机会,并且自动将输入的密码变成“*”,以增加安全性。
生成器
使用这个函数来根据当前时间计算一个新的动态密码。
int code_time=20; //安全代码刷新时间
int code_len=6; //安全代码长度
string trim(string a,int len)
{
string b;
len=min(len,(int)a.length());
for(int i=0;i<len;i++)
{
b+=a[i];
}
return b;
}
string generate(tm *t,int len)
{
int year=t->tm_year+1900;
int mon=t->tm_mon+1;
int day=t->tm_mday;
int hour=t->tm_hour;
int min=t->tm_min;
int sec=t->tm_sec;
unsigned int result=(sec/code_time+1)*(sec/code_time+1)*(sec/code_time+1)*(sec/code_time+1)*(sec/code_time+1)*min*min*min*year*year*mon*mon*day*day+day*day*(sec/code_time+1)*(sec/code_time+1)*(hour+1)*(hour+1)*(min+1)-min;
int a=result%2147480000+100000;
char str[55];
itoa(a,str,10);//将数字转换成字符数组存储到str中
return trim(str,len);
}
trim(string)函数用于剪切字符串,提取字符串的前6位。
generate(tm,int)函数提供了一个非常暴力的算法,当然你也可以更换其中的算法,使得它随机性更高。
主循环
如果你想在程序启动的时候一直动态获取密码,并且显示还剩多长时间改变,那么你可以参照以下的代码:
while(true)
{
tt=time(NULL);
t=localtime(&tt);
int time_remain=code_time-(t->tm_sec)%code_time-1;
if(time_remain==code_time-1||!out)
{
out=true;
system("cls");
cout<<"Current security code : "<<generate(t,6)<<endl;
cout<<"Code change : "<<time_remain;
Sleep(100);
}
else
{
cout<<" \rCode change : "<<time_remain;
}
Sleep(100);
}
像这样。每隔100毫秒读取一次系统时间,如果系统察觉到了密码应该变化,那么就重新计算一组密码。
完整源代码
在这里放出程序的完整源代码,方便进行学习、交流。
如果有更好的建议或者我讲的东西有任何问题,欢迎私信我,谢谢!
#include<iostream>
#include<ctime>
#include<string>
#include<stdlib.h>
#include<stdio.h>
#include<windows.h>
#include<conio.h>
using namespace std;
int code_time=20; //安全代码刷新时间
int code_len=6; //安全代码长度
string password="123456";//保护密码
string input()
{
char geted=getch();
string outed;
while(geted!=13)
{
cout<<"*";
outed+=geted;
geted=getch();
}
cout<<endl;
return outed;
}
string trim(string a,int len)
{
string b;
len=min(len,(int)a.length());
for(int i=0;i<len;i++)
{
b+=a[i];
}
return b;
}
string generate(tm *t,int len)
{
int year=t->tm_year+1900;
int mon=t->tm_mon+1;
int day=t->tm_mday;
int hour=t->tm_hour;
int min=t->tm_min;
int sec=t->tm_sec;
unsigned int result=(sec/code_time+1)*(sec/code_time+1)*(sec/code_time+1)*(sec/code_time+1)*(sec/code_time+1)*min*min*min*year*year*mon*mon*day*day+day*day*(sec/code_time+1)*(sec/code_time+1)*(hour+1)*(hour+1)*(min+1)-min;
int a=result%2147480000+100000;
char str[55];
itoa(a,str,10);
return trim(str,len);
}
int main()
{
time_t tt=time(NULL);
tm *t=localtime(&tt);
bool out=false;
cout<<"Current security code : UNKNOWN"<<endl;
cout<<"Code change : UNKNOWN"<<endl;
string check;
int timesss=1;
for(timesss=1;timesss<=3;timesss++)
{
cout<<"Security pass required : ";
check=input();
if(check==password) break;
else cout<<"[ERROR]Invalid pass! Chances remained : "<<3-timesss<<endl;
}
if(timesss>3)
{
cout<<"[DENIED]SECURITY PASS FAILED!"<<endl;
getch();
return 0;
}
while(true)
{
tt=time(NULL);
t=localtime(&tt);
int time_remain=code_time-(t->tm_sec)%code_time-1;
if(time_remain==code_time-1||!out)
{
out=true;
system("cls");
cout<<"Current security code : "<<generate(t,6)<<endl;
cout<<"Code change : "<<time_remain;
Sleep(100);
}
else
{
cout<<" \rCode change : "<<time_remain;
}
Sleep(100);
}
return 0;
}