• 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
    ", 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
    ", 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
    ", 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头文件动态链接库路径添加到项目配置中。

    总结

    做的很开心

  • 相关阅读:
    python mysql Connect Pool mysql连接池 (201
    mysql: see all open connections to a given database?
    mysql int(3)与int(11)的区别
    Configure Amazon RDS mysql to store Chinese Characters
    Maximum length of a table name in MySQL
    JDBC Tutorials: Commit or Rollback transaction in finally block
    Java transient关键字使用小记
    Java构造和解析Json数据的两种方法详解二
    精选30道Java笔试题解答
    Visual Studio最好用的快捷键(你最喜欢哪个)
  • 原文地址:https://www.cnblogs.com/mtzf/p/12814041.html
Copyright © 2020-2023  润新知