信息安全:使用 Openssl 加密库进行编程
-
提示文档:
实验已给出明文和密文,如下所示,并且已知加密方法为 aes-128-cbc,IV 全由 0 组成,以及 key 的长度小于 16 个字母,该单词可以从一般的英文词典中得到。由于该单词小于 16 个字母(128bits)所以在其后追加了空格字符(对应 0x20)以达到 128bit 的长度。本例中词典已给出,文件名为word.txt. -
任务:
写一个程序找到加***key。鼓励自己写程序,也可以使用实验楼中的代码,本实验即文件key.c,请调通key.c,给程序中每条语句添加注释,并画出程序的流程图。
明文 (21 个字符): This is a top secret.
密文 (十六进制形式): 8d20 e505 6a8d 24d0 462c e74e 4904 c1b5 13e1 0d1d f4a2 ef2a d454 0fae 1ca0 aaf9 -
备注:
1: 明、密文对都直接放在了程序中。如果你打算将明文存储在文件中读取,可能会有一些麻烦。
2: 为了编译代码,可以在linux平台需要写 makefile,如下。
NC=/usr/local/ssl/include/
LIB=/usr/local/ssl/lib/
all:
gcc -I$(INC) -L$(LIB) -o enc yourcode.c -lcrypto –ldl
也可以直接在linux平台下直接运行带有相关参数的gcc命令。
如果使用另一种情形在windows平台下,可以使用codeblocks来作为编辑器,并加载已编译好的带有OpenSSL的MinGW编译器来编译你写的代码,编译的过程和普通的C程序是一样的。
3:编写的程序代码可以参考实验楼平台的《**加解密实验 下》,本实验中给出该程序key.c,作为参考。但程序运行中可能会出现语法错误,需调试。Linux平台上key.c的错误可能少些,windows平台错误可能多些。此类错误均为由于不同平台下的C的语法稍有不同产生的语法错,而不是程序的逻辑错误。
- 代码如下:
#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define True 1
#define False 0
void handleErrors(void) {
ERR_print_errors_fp(stderr);
abort();
}
int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, unsigned char *iv, unsigned char *ciphertext) {
EVP_CIPHER_CTX *ctx;
int len;
int ciphertext_len;
//创建和初始化
if(!(ctx = EVP_CIPHER_CTX_new()))
handleErrors();
//初始化加密操作,确保使用key和iv是256位key,128位vi
if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv))
handleErrors();
//提供要加密的消息,并获得加密输出
if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
handleErrors();
ciphertext_len = len;
//最终加密,可缩写进一步的密文字节
if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
handleErrors();
ciphertext_len += len;
//清空
EVP_CIPHER_CTX_free(ctx);
return ciphertext_len;
}
//判断buffer是否符合密码长度的要求,并将buffer数组全部置空
int append(char* buffer){
int length = (int)strlen(buffer);
//设置key的长度小于 16 个字母,该单词可以从一般的英文词典中得到。
if (length > 16)
return False;
//单词小于16个字母(128bits)时,在其后追加了空格字符(对应 0x20)以达到 128bit 的长度。
memset(buffer+strlen(buffer),' ', 16-length);
buffer[16] = '\0';
return True;
}
int main(int argc, char const *argv[]) {
//key的存储空间
char buffer[50];
//循环标志
int i = 0;
//向量
char iv[17];
//初始化
memset(iv, 0, 17);
//待加密的文件内容 (明文)
unsigned char *plaintext = "This is a top secret.";
//密文文本空间
unsigned char ciphertext[100];
//密文
unsigned char *cryptotext="8d20e5056a8d24d0462ce74e4904c1b513e10d1df4a2ef2ad4540fae1ca0aaf9";
//加载可读的错误字符串
ERR_load_crypto_strings();
//将所有的算法添加到表中(摘要和密码),无返回值
OpenSSL_add_all_algorithms();
//加载配置文件,以及其他重要的初始化,使用默认名称配置openssl
OPENSSL_config(NULL);
//密文长度
int ciphertext_len;
//以只读方式打开word.txt
FILE* fp = fopen("words.txt", "r");
//从fp中读取一行字符放入buffer中
while (fscanf(fp, "%s\n", buffer) != EOF){
//判断buffer是否符合密码要求
if (!append(buffer))
continue;
//加密plaintext
ciphertext_len = encrypt(plaintext, strlen(plaintext), buffer, iv, ciphertext);
//加密十六进制
unsigned char cryptohex[50];
for (i = 0; i < ciphertext_len; i++) {
//以2位十六进制形式将加密结果ciphertext格式化输出到cryptohex中、ciphertext格式化输出到cryptohex中。
sprintf(cryptohex+i*2,"%02x", ciphertext[i]);
}
//设置结束符
cryptohex[ciphertext_len*2] = '\0';
//判断加密后生成的十六进制文件cryptohex和给定的cryptotext是否相同
if (0 == strcmp(cryptohex, cryptotext)){
//如果相同则当前的key为**,即返回找的秘钥
printf("The key is: %s\n", buffer);
break;
}
}
//删除所有摘要和密码
EVP_cleanup();
//删除错误的字符串
ERR_free_strings();
return 0;
}
上一篇: Vue子组件绑定事件无效
下一篇: a链接上绑定事件,点击无效