#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_PASSWORD_LEN 100
#define ENCRYPTED_LEN (MAX_PASSWORD_LEN * 8 + 1)
// 加密密码:每个字符ASCII+5后转为8位二进制
void encrypt_password(const char *password, char *encrypted) {
int pos = 0;
for (int i = 0; password[i] != '\0'; i++) {
unsigned char c = password[i] + 5;
for (int j = 7; j >= 0; j--) {
encrypted[pos++] = (c & (1 << j)) ? '1' : '0';
}
}
encrypted[pos] = '\0';
}
// 解密密码:二进制转ASCII后-5
int decrypt_password(const char *encrypted, char *password) {
int len = strlen(encrypted);
if (len % 8 != 0) return -1;
int num_chars = len / 8;
for (int i = 0; i < num_chars; i++) {
unsigned char c = 0;
for (int j = 0; j < 8; j++) {
c <<= 1;
if (encrypted[i*8 + j] == '1') c |= 1;
}
password[i] = c - 5;
}
password[num_chars] = '\0';
return 0;
}
// 读取配置文件
void read_config(char *encrypted, int *lock_enabled) {
FILE *fp = fopen("config.txt", "r");
if (!fp) {
strcpy(encrypted, "001101100011011100111000001110010011101000111011");
*lock_enabled = 1;
return;
}
if (!fgets(encrypted, ENCRYPTED_LEN, fp)) {
strcpy(encrypted, "001101100011011100111000001110010011101000111011");
*lock_enabled = 1;
fclose(fp);
return;
}
encrypted[strcspn(encrypted, "\n")] = '\0';
char line[16];
*lock_enabled = 1;
if (fgets(line, sizeof(line), fp)) sscanf(line, "%d", lock_enabled);
fclose(fp);
}
// 写入配置文件
void write_config(const char *encrypted, int lock_enabled) {
FILE *fp = fopen("config.txt", "w");
if (!fp) {
perror("保存失败");
return;
}
fprintf(fp, "%s\n%d\n", encrypted, lock_enabled);
fclose(fp);
}
void settings_menu();
// 主菜单
void main_menu() {
int choice;
while (1) {
printf("\n主菜单\n1.设置\n2.退出\n请选择: ");
scanf("%d", &choice);
getchar();
switch (choice) {
case 1: settings_menu(); break;
case 2: exit(0);
default: printf("无效选项\n");
}
}
}
// 切换密码锁状态
void toggle_lock() {
char encrypted[ENCRYPTED_LEN];
int lock_enabled;
read_config(encrypted, &lock_enabled);
lock_enabled = !lock_enabled;
write_config(encrypted, lock_enabled);
printf("密码锁已%s\n", lock_enabled ? "开启" : "关闭");
}
// 修改密码
void change_password() {
char encrypted[ENCRYPTED_LEN];
int lock_enabled;
read_config(encrypted, &lock_enabled);
char current_password[MAX_PASSWORD_LEN + 1];
if (decrypt_password(encrypted, current_password) != 0) {
printf("密码解析失败!\n");
return;
}
int attempts = 0;
char input[MAX_PASSWORD_LEN + 1];
while (attempts < 3) {
printf("请输入原密码: ");
fgets(input, sizeof(input), stdin);
input[strcspn(input, "\n")] = '\0';
if (strcmp(input, current_password) == 0) break;
printf("密码错误,剩余次数: %d\n", 2 - attempts++);
}
if (attempts >= 3) {
printf("验证失败!\n");
return;
}
char new_password[MAX_PASSWORD_LEN + 1], confirm[sizeof(new_password)];
printf("输入新密码: ");
fgets(new_password, sizeof(new_password), stdin);
new_password[strcspn(new_password, "\n")] = '\0';
printf("确认新密码: ");
fgets(confirm, sizeof(confirm), stdin);
confirm[strcspn(confirm, "\n")] = '\0';
if (strcmp(new_password, confirm) {
printf("两次输入不一致!\n");
return;
}
char new_encrypted[ENCRYPTED_LEN];
encrypt_password(new_password, new_encrypted);
write_config(new_encrypted, lock_enabled);
printf("密码修改成功!\n");
}
// 设置菜单
void settings_menu() {
int choice;
while (1) {
printf("\n设置菜单\n1.切换密码锁\n2.修改密码\n3.返回\n请选择: ");
scanf("%d", &choice);
getchar();
switch (choice) {
case 1: toggle_lock(); break;
case 2: change_password(); break;
case 3: return;
default: printf("无效选项\n");
}
}
}
int main() {
char encrypted[ENCRYPTED_LEN];
int lock_enabled;
read_config(encrypted, &lock_enabled);
if (lock_enabled) {
char current_password[MAX_PASSWORD_LEN + 1];
if (decrypt_password(encrypted, current_password) != 0) {
printf("使用默认密码123456\n");
strcpy(current_password, "123456");
}
int attempts = 0;
while (attempts < 3) {
printf("请输入密码: ");
char input[MAX_PASSWORD_LEN + 1];
fgets(input, sizeof(input), stdin);
input[strcspn(input, "\n")] = '\0';
if (strcmp(input, current_password) == 0) break;
printf("密码错误,剩余次数: %d\n", 2 - attempts++);
}
if (attempts >= 3) {
printf("超过尝试次数,程序退出!\n");
return 0;
}
}
main_menu();
return 0;
}
运行结果:
代码说明
-
加密与解密
-
encrypt_password
函数将每个字符的ASCII码加5后转换为8位二进制字符串。 -
decrypt_password
函数将二进制字符串转换回ASCII码并减5得到原始密码。
-
-
配置文件处理
-
read_config
读取配置文件,获取加密密码和密码锁状态,若文件不存在则使用初始密码。 -
write_config
将当前密码和状态写入配置文件。
-
-
主流程
-
程序启动时检查密码锁状态,若开启则验证密码(最多3次错误)。
-
主菜单提供设置和退出选项,设置菜单可切换密码锁状态或修改密码。
-
-
修改密码
-
修改密码时需要先验证原密码(3次机会),确认新密码一致性后加密保存。
-
-
安全性处理
-
密码存储时进行加密处理,避免明文存储。
-
输入密码时隐藏显示(未实现,可按需求扩展)。
-
该程序实现了题目要求的所有功能,并通过文件存储保持配置的持久化。
注:
1.题目来源优快云@Citrus-1120
2.初始密码为123456(可自行设置)