![]() |
#2
rjsp2023-03-27 12:33
「容错时间差」当然是你自己定义了
![]() #include <stdio.h> #include <math.h> #include <windows.h> void InputPassword( size_t maxcount, char keys[], double timepoints[] ) { LARGE_INTEGER frequency, start_time; QueryPerformanceFrequency( &frequency ); start_time.QuadPart = 0; bool keys_down[128] = { false }; // 记录 char 0-127 的按键状态 HANDLE console = GetStdHandle(STD_INPUT_HANDLE); for( size_t i=0; i!=maxcount; ) { INPUT_RECORD input_record; DWORD events_read; if( !ReadConsoleInput(console,&input_record,1,&events_read) || events_read!=1 || input_record.EventType!=KEY_EVENT ) // 忽略非按键信息 continue; bool bKeyDown = input_record.Event.KeyEvent.bKeyDown!=0; char AsciiChar = input_record.Event.KeyEvent.uChar.AsciiChar; if( bKeyDown && AsciiChar=='\r' ) // 回车后不再记录 { keys[i++] = 0; break; } if( AsciiChar<' ' || AsciiChar>=127 ) // 忽略无法映射的字符(对应着locale("C")下的isprint) continue; AsciiChar = (AsciiChar>='a' && AsciiChar<'z') ? (AsciiChar-'a'+'A') : AsciiChar; // 忽略大小写(否则要监控Shift键和Caps键,过于复杂) if( bKeyDown && !keys_down[AsciiChar] ) { LARGE_INTEGER timepoint; QueryPerformanceCounter( &timepoint ); if( i == 0 ) start_time = timepoint; keys_down[AsciiChar] = true; keys[i] = AsciiChar; timepoints[i++] = (timepoint.QuadPart-start_time.QuadPart)/(frequency.QuadPart+0.0); putchar( '*' ); } else if( !bKeyDown && keys_down[AsciiChar] ) { LARGE_INTEGER timepoint; QueryPerformanceCounter( &timepoint ); keys_down[AsciiChar] = false; keys[i] = AsciiChar; timepoints[i++] = (timepoint.QuadPart-start_time.QuadPart)/(frequency.QuadPart+0.0); } } putchar( '\n' ); } void ShowPassword( size_t maxcount, char keys[], double timepoints[] ) { printf( "{\n" ); bool keys_down[128] = { false }; for( size_t i=0; i!=maxcount && keys[i]!=0; ++i ) { keys_down[keys[i]] = !keys_down[keys[i]]; printf( " '%c' %-4s at %10.6fs\n", keys[i], (keys_down[keys[i]]?"Down":"Up"), timepoints[i] ); } printf( "}\n" ); } bool ShowDifference( size_t maxcount, char a_keys[], double a_timepoints[], char b_keys[], double b_timepoints[] ) { for( size_t i=0; i!=maxcount && a_keys[i]!=0; ++i ) { if( a_keys[i] != b_keys[i] ) { puts( "{ 按键顺序不一致 }" ); return false; } } printf( "{\n" ); double a_keys_down[128] = { 0 }; double b_keys_down[128] = { 0 }; for( size_t i=0; i!=maxcount && a_keys[i]!=0; ++i ) { if( a_keys_down[a_keys[i]] == 0 ) { a_keys_down[a_keys[i]] = a_timepoints[i] + 1.0; b_keys_down[b_keys[i]] = b_timepoints[i] + 1.0; if( i == 0 ) printf( " '%c' Down:\n", a_keys[i] ); else printf( " '%c' Down: 按键时刻相差 %10.6fs (%4.2f%%)\n", a_keys[i], fabs(a_timepoints[i]-b_timepoints[i]), fabs(a_timepoints[i]-b_timepoints[i])*100/a_timepoints[i] ); } else { double d1 = fabs( a_timepoints[i]+1.0 - a_keys_down[a_keys[i]] ); double d2 = fabs( b_timepoints[i]+1.0 - b_keys_down[b_keys[i]] ); printf( " '%c' Up : 按键时长相差 %10.6fs (%4.2f%%)\n", a_keys[i], fabs(d1-d2), fabs(d1-d2)*100/d1 ); a_keys_down[a_keys[i]] = 0; b_keys_down[b_keys[i]] = 0; } } printf( "}\n" ); puts( "你认为这个偏差可以接受,就返回true;否则,返回false" ); return true; } int main( void ) { char a_keys[50]; double a_intervals[50]; InputPassword( 50, a_keys, a_intervals ); ShowPassword( 50, a_keys, a_intervals ); char b_keys[50]; double b_intervals[50]; InputPassword( 50, b_keys, b_intervals ); ShowPassword( 50, b_keys, b_intervals ); ShowDifference( 50, a_keys, a_intervals, b_keys, b_intervals ); } 测试时,两次输入都是「按下A,按下B,按下C,松开B,松开A,按下回车键」,然后程序输出 *** { 'A' Down at 0.000000s 'B' Down at 0.503053s 'C' Down at 1.165817s 'B' Up at 1.990602s 'A' Up at 2.470596s } *** { 'A' Down at 0.000000s 'B' Down at 0.529204s 'C' Down at 0.952299s 'B' Up at 1.359857s 'A' Up at 1.832545s } { 'A' Down: 'B' Down: 按键时刻相差 0.026151s (5.20%) 'C' Down: 按键时刻相差 0.213518s (18.31%) 'B' Up : 按键时长相差 0.656896s (44.16%) 'A' Up : 按键时长相差 0.638051s (25.83%) } 你认为这个偏差可以接受,就返回true;否则,返回false |
我想在原有程式的基础下再添加一个二次输入验证的机制(就有点像在注册帐号时的"请再输入一次密码"的感觉)
但因为我在先前有写一段纪录按键延迟的阵列,想把延迟也当作验证的一部份
大致流程
1.照"节奏"第一次输入密码时:显示输入的数(矩阵记录下密码与间隔时间),按下回车跳至第二次的验证
2.第二次验证密码:第二次验证需重复第一次的密码与节奏(考虑到人的节奏感,希望在第一次的节奏基础上有+-的容错时间差)
3.如果符合则跳至 Keys pressed/ intervals between key presses那一段,如不符合需再重复输入(希望至多5次)
麻烦各位老师了!

程式碼如下:

#include <stdio.h>
#include <windows.h>
#define MAX_KEYS 50
#define MAX_INTERVALS (MAX_KEYS - 1)
int main()
{
INPUT_RECORD input_record;
HANDLE console = GetStdHandle(STD_INPUT_HANDLE);
DWORD events_read;
LARGE_INTEGER start_time, end_time, frequency;
BOOL last_event_was_release = FALSE;
LARGE_INTEGER last_release_time;
int key_count = 0;
char keys[MAX_KEYS] = {0};
char password[50];
char verify_password[50];
double intervals[MAX_INTERVALS - 1] = {0};
QueryPerformanceFrequency(&frequency);
printf("請設定節拍密碼\n\n");
while (1) {
if (ReadConsoleInput(console, &input_record, 1, &events_read)) {
if (input_record.EventType == KEY_EVENT) {
if (input_record.Event.KeyEvent.bKeyDown) {
if (last_event_was_release && input_record.Event.KeyEvent.wVirtualKeyCode != VK_RETURN) {
LARGE_INTEGER press_time;
QueryPerformanceCounter(&press_time);
double interval = (double)(press_time.QuadPart - last_release_time.QuadPart) / frequency.QuadPart * 1.0;
intervals[key_count - 1] = interval;
printf("Time since last release: %.3fs\n", (double)(press_time.QuadPart - last_release_time.QuadPart) / frequency.QuadPart * 1.0);
}
QueryPerformanceCounter(&start_time);
last_event_was_release = FALSE;
if (key_count < MAX_KEYS) {
keys[key_count++] = input_record.Event.KeyEvent.uChar.AsciiChar;
}
} else {
LARGE_INTEGER release_time;
QueryPerformanceCounter(&release_time);
last_release_time = release_time;
last_event_was_release = TRUE;
if (input_record.Event.KeyEvent.uChar.AsciiChar != '\0') {
printf("'%c' key pressed for %.3f ms\n", input_record.Event.KeyEvent.uChar.AsciiChar,
(double)(release_time.QuadPart - start_time.QuadPart) / frequency.QuadPart * 1.0);
} else {
printf("Key pressed for %.3f s\n", (release_time.QuadPart - start_time.QuadPart) / frequency.QuadPart * 1.0);
}
}
}
}
if (GetAsyncKeyState(VK_RETURN) & 1) {
printf("\n==============================================================================\n");
printf("\n Keys pressed ");
for (int i = 0; i < key_count; i++) {
printf("%c ", keys[i]);
}
printf("\n");
// Output the intervals between key presses
printf(" intervals between key presses: ");
for (int i = 0; i < key_count - 2; i++) {
printf("%.3fs ", intervals[i]);
}
printf("\n");
break;
}
}
return 0;
}