2022-2023-1 20222807《Linux内核原理与分析》第十三周作业

密钥加解密实验

1.实验描述

本实验的学习目的是让学生熟悉加密的概念,熟悉和了解加密算法(cipher)、加密模式(encryption mode)、 填充(padding)、以及初始向量(IV)的定义与作用。此外,学生还可以通过使用工具和编写程序加密/解密信息。

2.实验环境

本实验中,我们将使用 openssl 命令行工具及其库。实验环境中已自带命令行工具,需安装 openssl 开发库。

sudo apt-get update
sudo apt-get install -y libssl-dev

编辑器使用 bless 十六进制编辑器,需预先安装。

sudo apt-get install -y bless

3.实验内容

3.1 使用不同的加密算法与加密模式进行加密

在 /home/shiyanlou 目录下新建一个文件 plain.txt并输入shiyanlou,输入下列指令进行加密:

openssl enc ciphertype -e -in plain.txt -out cipher.bin \
-K 00112233445566778899aabbccddeeff \
-iv 0102030405060708

将其中的ciphertype替换成指定的加密类型,比如-aes-128-cbc, -aes-128-cfb, -bf-cbc 等,分别使用上述三种加密类型进行加密,如下所示:

在这里插入图片描述

3.2 加密模式——ECB 与 CBC 的区别

首先根据实验指导下载图片:

wget http://labfile.oss.aliyuncs.com/courses/241/pic_original.bmp

sudo apt-get install gpicview

使用 CBC 模式对这张图片进行加密,并用bless编辑器修改文件头:
在这里插入图片描述在这里插入图片描述
打开图片,结果如下所示:

在这里插入图片描述按照上述方法,再使用 ECB 模式对这张图片进行加密,结果如下所示:

在这里插入图片描述

3.3 加密模式——损坏的密文

首先新建一个长度至少是 64 字节的文本文件,输入vi /home/shiyanlou/corrupted.txt创建文件并输入四行i love shiyanlou作为内容。
然后对文本进行加密:
在这里插入图片描述然后使用bless编辑器打开密文,文件中第 30 位是 EA,我们将其改为 FA,以制造损坏的密文。

在这里插入图片描述
然后再进行解密:
在这里插入图片描述可以看到,这样得到的解密后的文件是有部分内容出现损坏的

3.4 填充

在 /home/shiyanlou 目录下新建一个文件 test20.txt,输入i love shiyanlou!!!
并对文件进行加密:
在这里插入图片描述
可以看出,加密文件的大小为 32 个字节,比原始文件多了 12 个字节。因为我使用了 AES-128-CBC,所以每个块都是 16 个字节。原始文件的内容是 20 个字节,所以第一个块是 16 个字节,第二个块是 4 个字节。第二个块不足 16 个字节,所以填充了 12 个字节。

3.5 使用 Openssl 加密库进行编程

首先下载我们的词典到 /home/shiyanlou 目录:

cd /home/shiyanlou
wget http://labfile.oss.aliyuncs.com/courses/241/words.txt

然后在 /home/shiyanlou 目录新建 fileKey.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();

  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;
}

int append(char* buffer){
    int length = (int)strlen(buffer);
    if (length > 16)
        return False;
    memset(buffer+strlen(buffer),' ', 16-length);
    buffer[16] = '\0';
    return True;

}

int main(int argc, char const *argv[])
{
    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_config(NULL);

    int ciphertext_len;

    FILE* fp = fopen("words.txt", "r");
    while (fscanf(fp, "%s\n", buffer) != EOF){
        if (!append(buffer))
            continue;

        ciphertext_len = encrypt(plaintext, strlen(plaintext), buffer, iv, ciphertext);

        unsigned char cryptohex[50];
        for (i = 0; i < ciphertext_len; i++)
        {
            sprintf(cryptohex+i*2,"%02x", ciphertext[i]);
        }
        cryptohex[ciphertext_len*2] = '\0';

        if (0 == strcmp(cryptohex, cryptotext)){
            printf("The key is: %s\n", buffer);
            break;
        }
    }
    EVP_cleanup();
    ERR_free_strings();
    return 0;
}

编译 fileKey.c:

gcc -I /usr/include/openssl -L /usr/lib/ssl -o enc fileKey.c -lcrypto -ldl

运行代码,结果如下所示:
在这里插入图片描述

3.6 生成伪随机数

计算机本身并不适合生成随机数,所以大多数系统通过物理资源获得随机性。比如 linux 通过以下函数获得随机性:

void add_keyboard_randomness(unsigned char scancode);
void add_mouse_randomness(__u32 mouse_data);
void add_interrupt_randomness(int irq);
void add_blkdev_randomness(int major);

前两个很好理解,第一个利用键盘按键时序和所按键的对应码,第二个利用鼠标的移动和中断时序。第三个利用所有的中断时序收集随机性,当然,并不是所有的中断都有好的随机性,比如时间中断就是可以预测的,而硬盘中断是一个好选择,第四个函数计算设备块请求的完成时间。

我们使用熵来衡量随机性,在这里熵只意味着计算机当前拥有多少位随机比特。以下命令可以得到系统当前拥有熵的数量:

cat /proc/sys/kernel/random/entropy_avail

进行一定的时间或动作后再次运行上述指令,会发现结果产生变化:
在这里插入图片描述
Linux 将从物理世界得到的随机数据存于一个随机池中,再由两个设备把随机数据转化成伪随机数。这两个设备有着不同的行为,我们先来学习 /dev/random。

可以使用以下命令从 /dev/random 得到 16 字节的伪随机数,我们把数据 pipe 到 hexdump 中查看内容

head -c 16 /dev/random | hexdump

多次运行该命令,会发现命令发生阻塞,因为每次取出伪随机数都会导致随机池的熵减少,当熵用完的时候,设备就会被阻塞直到获得足够的熵。

在这里插入图片描述
使用以下命令从/dev/urandom 获得 1600 字节的伪随机数

head -c  1600 /dev/urandom | hexdump

/dev/random 与 /dev/urandom 都是从池中取出随机数据来生成伪随机数的。当熵不够用的时候,/dev/random 会阻塞,而 /dev/urandom 则会持续生成新的数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值