175210课设第三次报告

本周计划

  • 使用 openssl 原生 api 解析 asn.1 编码文件
  • 图形界面的勾画( QT5 )

完成情况

一、使用 openssl api 解析 asn.1 编码文件

有一个命令行工具叫做 openssl ans1parser,它使用的是 ASN1_parse_dump 函数,具体如下

int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent, int dump);

BIOopenssl 自定义的 IO 流,pp 指向要解析的文件。indent 用来设置打印出来列之间空格个数,ident越小,打印内容越紧凑。dump 指明当类型为 BIT STRINGOCTET STRING 时,打印内容的字节数。

1.1 所以先要学习 Bio

文档和源码很容易搜到,这里放小例子和注释

mem bio

#include <openssl/bio.h>
#include <openssl/asn1.h>

int main()
{
    BIO *bio = BIO_new(BIO_s_mem()); // 生成一个mem类型的BIO
    int len = BIO_write(bio, "mtmtmtmt", 6); // 将字符串写入 bio, 写 6 个字节
    len = BIO_printf(bio, "%s", "lyzlyzlyz"); // 也可以指定格式类型写入
    len = BIO_ctrl_pending(bio); // 得到 bio 缓冲区中待读的大小,只对 mem 类型的有效
    char *out = (char*)OPENSSL_malloc(len);
    BIO_read(bio, out, len); // 将 bio 中的内容读入 out 缓冲区中
    printf("%s\n", out);
    OPENSSL_free(out); // 记着释放内存
    BIO_free(bio);
    return 0;
}

编译的时候别忘了加上 -lcrypto 链接库

file bio

#include <openssl/bio.h>

int main()
{
    BIO *bio = BIO_new_file("mt.txt", "w");
    BIO_write(bio, "mtmtmt", 4);
    BIO_free(bio);
    bio = BIO_new_file("mt.txt", "r");
    char *out = (char*)OPENSSL_malloc(100);
    int len = 1, outlen = 0;
    while (len > 0)
    {
        len = BIO_read(bio, out + outlen, 1);
        outlen += len;
    }
    printf("%s\n", out);
    BIO_free(bio);
    OPENSSL_free(out);
    return 0;
}

正常人看懂了第一个程序就能看懂第二个,不解释了

1.2 使用 ASN1_parse_dump 函数

解析 asn.1 编码文件,并将解析后的结果写入 BIO 流中。具体参数解释见上文

读取并解析上篇文章中的 rubytest.der

#include <openssl/bio.h>
#include <openssl/asn1.h>

int main()
{
    BIO *bio = BIO_new(BIO_s_mem()); // 选择 file, socket 模式都可以,这里选择 mem 是为了迎合 qt 的操作
    // BIO_set_fp 函数可以为 bio 绑定输出流,如 stdout

    FILE *fp = fopen("rubytest.der", "rb");
    if (fp == NULL)
    {
        printf("%s", "fail to open file");
        return -1;
    }
    unsigned char buf[5000];
    long len = fread(buf, 1, 5000, fp); // 将待解析的内容读入 buf 中,返回内容长度
    fclose(fp);
    ASN1_parse_dump(bio, buf, len, 7, 20); // 解析 buf 中的数据并写入 bio 流

    int length = BIO_ctrl_pending(bio); // bio 中数据的长度
    char *out = (char*)OPENSSL_malloc(length);
    BIO_read(bio, out, length); // 将解析后的结果输入 out 中
    printf("%s\n", out);
    OPENSSL_free(out);
    BIO_free(bio);
    return 0;
}

二、QT5 编写界面

本来准备用 electron 的,但我懒得整 nodejs 调用 c 了。而且用 css + js 写出个可以折叠的树型结构,想想就恶心……

入门 qt,推荐这个知乎专栏
https://zhuanlan.zhihu.com/p/28472916。把信号,槽看看就差不多了,其他就是包装后的 c++

2.1 交互问题

BIO 流转 char*char* 转 QString。我写的函数如下:

QString MainWindow::parseAsn1(QString filename)
{
   std::string file_name = filename.toStdString();
   const char* fileName = file_name.c_str();
   // 以上两行是将 QString 类型的 文件名 转为 c 语言的 char* 类型
   FILE *fp = fopen(fileName, "rb");
   unsigned char buf[5000];
   int len = fread(buf, 1, 5000, fp);
   fclose(fp);
   BIO *bp = BIO_new(BIO_s_mem());
   ASN1_parse_dump(bp, buf, len, 7, 20);
   len = BIO_ctrl_pending(bp);
   char *out = (char*)OPENSSL_malloc(len);
   len = BIO_read(bp, out, len);
   BIO_free(bp);
   QString re = QString(out); // 再将 char* 类型转为 QString
   OPENSSL_free(out);
   qDebug() << re;
   return re;
}

2.2 树状结构

使用 TreeWidget 组件,这个在此没法具体说。网上资料很多,跟着做就行。

2.3 qt 编译

因为调用了 openssl 库,需要在项目的 .pro 文件中添加

INCLUDEPATH += $$quote(/usr/include/openssl)

LIBS += $$quote(/usr/lib/x86_64-linux-gnu/libcrypto.so)
LIBS += $$quote(/usr/lib/x86_64-linux-gnu/libssl.so)

openssl头文件动态链接库路径添加到项目配置中。

总结

做的很开心

posted @ 2020-05-01 17:12  175210闵天  阅读(271)  评论(1编辑  收藏  举报