作业:
为了保障用户的本地笔记数据安全,决定构建了一个安全可靠的加密笔记本程序,利用了多种加密技术和防护措施,确保用户数据不受未经受权的用户拜访或获取。这个加密笔记本领有以下技术特点:
1. 加密数据
为了保障用户笔记的安全性和保密性,咱们应用 AES 加密算法对数据进行加密。AES(Advanced Encryption Standard)是一种高级加密规范,已被广泛应用于商业和政府畛域。相比于其余算法,AES 算法更加安全可靠,能够提供更高的数据安全性。在加密笔记本中,咱们采纳了 AES-256-CBC 算法,提供了更高的安全性。同时,咱们还应用随机生成的初始化向量(IV),进一步加强了加密算法的安全性。
2. 明码哈希
为了防止用户明码被其他人获取或窃取,咱们应用 bcrypt 明码哈希算法对用户明码进行加密。bcrypt 是一种比 MD5 和 SHA- 1 等哈希算法更加平安和牢靠的明码哈希算法,可能提供更高的密码保护。在加密笔记本中,咱们将用户输出明码进行 bcrypt 哈希,而后再保留到数据库中。这样,即便黑客获取到了加密笔记本的数据库,也无奈轻易地取得明文明码。
3. 防重放攻打
防重放攻打是一种黑客攻击形式,攻击者会利用已知的数据包重放来达到攻打的目标。在加密笔记本中,咱们引入了随机数和工夫戳,以避免重放攻打。每个申请都会生成一个惟一的随机数和工夫戳,并与其余申请进行辨别。这样,黑客就无奈在短时间内重放申请,从而保障了应用程序的安全性。
4. 严格的输出验证
因为用户输出谬误或歹意攻打是导致应用程序呈现问题的次要起因之一,因而咱们在加密笔记本中退出了对用户名和明码的字符长度和复杂度等方面的严格验证,保障了输出的正确性和安全性。如果用户输出不符合规范,应用程序就会提醒用户从新输出。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/bcrypt.h>
#define MAX_NOTES 100
void encrypt(const unsigned char *input, int input_len, unsigned char *key, unsigned char *iv, unsigned char *output) {EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
int output_len;
EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv);
EVP_EncryptUpdate(ctx, output, &output_len, input, input_len);
EVP_EncryptFinal_ex(ctx, output + output_len, &output_len);
EVP_CIPHER_CTX_free(ctx);
}
void decrypt(const unsigned char *input, int input_len, unsigned char *key, unsigned char *iv, unsigned char *output) {EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
int output_len;
EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv);
EVP_DecryptUpdate(ctx, output, &output_len, input, input_len);
EVP_DecryptFinal_ex(ctx, output + output_len, &output_len);
EVP_CIPHER_CTX_free(ctx);
}
// 验证明码复杂度(至多蕴含 8 个字符,其中必须包含数字、大写字母、小写字母和特殊字符)bool check_password(const char* password) {int password_len = strlen(password);
if (password_len < 8) {return false;}
bool has_digit = false;
bool has_upper = false;
bool has_lower = false;
bool has_special = false;
for (int i = 0; i < password_len; i++) {if (isdigit(password[i])) {has_digit = true;} else if (isupper(password[i])) {has_upper = true;} else if (islower(password[i])) {has_lower = true;} else {has_special = true;}
}
if (!has_digit || !has_upper || !has_lower || !has_special) {return false;}
return true;
}
// 验证用户名和明码是否匹配
bool check_user(const char* username, const char* password) {
// 增加自定义的用户名和明码认证逻辑代码
return true;
}
// 加载并解密笔记数据
bool load_notes(const char* filename, unsigned char* key, unsigned char* iv, unsigned char* notes_buf, int notes_buf_len) {FILE* fp = fopen(filename, "rb");
if (fp == NULL) {printf("Note file not found or unable to open.\n");
return false;
}
fseek(fp, 0, SEEK_END);
int file_size = ftell(fp);
rewind(fp);
if (file_size > notes_buf_len) {printf("Notes buffer size is too small. %d bytes are required.\n", file_size);
fclose(fp);
return false;
}
unsigned char* encrypted_notes = malloc(file_size);
fread(encrypted_notes, 1, file_size, fp);
fclose(fp);
decrypt(encrypted_notes, file_size, key, iv, notes_buf);
free(encrypted_notes);
return true;
}
// 保留并加密新笔记数据
bool save_notes(const char* filename, unsigned char* key, unsigned char* iv, unsigned char* notes_buf, int notes_len) {unsigned char* encrypted_notes = malloc(notes_len);
encrypt(notes_buf, notes_len, key, iv, encrypted_notes);
FILE* fp = fopen(filename, "wb");
if (fp == NULL) {printf("Unable to open file for writing.\n");
free(encrypted_notes);
return false;
}
if (fwrite(encrypted_notes, 1, notes_len, fp) != notes_len) {printf("Unable to write notes data to file.\n");
fclose(fp);
free(encrypted_notes);
return false;
}
fclose(fp);
free(encrypted_notes);
return true;
}
int main() {char username[80];
char password[80];
// 输出验证
while(true) {printf("Please enter your username:");
scanf("%s", username);
printf("Please enter a strong password (at least 8 characters with numbers, uppercase/lowercase letters, and special characters):");
scanf("%s", password);
if (!check_password(password)) {printf("Password does not meet complexity requirements. Please try again.\n");
continue;
}
if (!check_user(username, password)) {printf("Invalid username or password. Please try again.\n");
continue;
}
break;
}
// 随机数和工夫戳,用于防重放攻打
int timestamp = time(NULL);
RAND_add(×tamp, sizeof(timestamp));
unsigned char nonce[8];
RAND_bytes(nonce, sizeof(nonce));
// 加载并解密笔记数据
unsigned char iv[EVP_MAX_IV_LENGTH];
memset(iv, 0x00, EVP_MAX_IV_LENGTH);
unsigned char* notes_buf = malloc(MAX_NOTES);
unsigned char salt[BCRYPT_SALTSPACE];
RAND_bytes(salt, sizeof(salt));
unsigned char* hash = malloc(BCRYPT_HASHSPACE);
bcrypt(password, strlen(password), salt, hash, BCRYPT_HASHSPACE);
if (!load_notes("notes.enc", hash, iv, notes_buf, MAX_NOTES)) {free(notes_buf);
return 1;
}
// 显示笔记
printf("%s\n", notes_buf);
// 输出新笔记
printf("Enter new notes:\n");
char new_notes[MAX_NOTES];
fgets(new_notes, MAX_NOTES, stdin);
// 保留并加密新笔记数据
int new_notes_len = strlen(new_notes);
if (!save_notes("notes.enc", hash, iv, (unsigned char*)new_notes, new_notes_len)) {free(notes_buf);
return 1;
}
free(notes_buf);
free(hash);
return 0;
}