使用EVP和OpenSSL,用C编写代码

使用EVP和OpenSSL,用C编写代码,c,encryption,openssl,digital-signature,evp-cipher,C,Encryption,Openssl,Digital Signature,Evp Cipher,我看到了很多关于OpenSSL和EVP的问题,但没有太多明确的答案,但我想我还是把我的问题贴在这里,希望得到更好的反馈 给我的资料是一个签名文件“symmetrickey.bin”、一个RSA密钥集“privatekey_a.pem”、“publickey_a.pem”和另一个用户的公钥“publickey_B.pem” 我需要做的是: Unsignsymmetrickey.bin并将其存储到文本文件中 使用symmetrickey.txt和一些算法(例如AES)加密message.txt 使用

我看到了很多关于OpenSSL和EVP的问题,但没有太多明确的答案,但我想我还是把我的问题贴在这里,希望得到更好的反馈

给我的资料是一个签名文件“symmetrickey.bin”、一个RSA密钥集“privatekey_a.pem”、“publickey_a.pem”和另一个用户的公钥“publickey_B.pem”

我需要做的是:

  • Unsign
    symmetrickey.bin
    并将其存储到文本文件中
  • 使用
    symmetrickey.txt
    和一些算法(例如AES)加密
    message.txt
  • 使用
    privatekey_A.pem
    对加密邮件进行签名,并将其写入文件
    cipher.bin
  • 之后,我需要在
    cipher.bin
    上取消签名并验证签名
  • 然后用我们的对称密钥解密消息,然后写入另一个文件
  • 我面临的问题是理解如何实现OpenSSL EVP库。API页面不太清楚每个函数的值来自何处。例如,
    EVP\u OpenInit()?“prvi”是私钥吗?我怎么知道是哪种类型?这些都是我没有得到的东西


    我看过很多实现,大多数都没有回答我的问题,或者他们给出了疯狂的代码,几乎没有解释发生了什么或者值来自哪里。我在这里发帖作为最后手段…

    对于签名/未签名的关键部分,我需要进一步的信息,这个签名是如何完成的?例如,该签名在文件末尾是否为X字节长度,然后可以轻松删除

    对于列表中的项目2-5,下面的代码肯定会有所帮助,它基于openssl文档中的示例,提供了更多注释,并根据您的需要进行了修改。如果您有任何未被评论的问题,请随时提问

    crpytor.c 此代码不使用EVP_OpenInit()
    ,因为它仅用于解密,而我的方法(以及您的需要)需要加密或解密。虽然您可以使用
    EVP_OpenInit()
    初始化解密上下文,但我将仅适用于解密的单个调用替换为适用于加密和解密的两个调用

    从手册页:

    EVP_OpenInit()
    初始化密码上下文
    ctx
    ,以便使用 密码类型。它解密长度为
    ekl
    使用私钥
    priv
    ek
    参数中传递的字节数。四 在
    iv
    参数中提供
    EVP\u OpenUpdate()
    EVP\u OpenFinal()
    与EVP\U DecryptUpdate()具有完全相同的属性
    EVP_DecryptFinal()
    例程,如
    EVP_EncryptInit(3)
    手册页

    EVP\u OpenInit()
    用于密钥文件


    如果您所指的签名文件是RSA/DSA或类似格式的公钥文件,您可以使用比我更好的方法,因为它会自动从文件中提取密钥(并使用
    EVP_OpenInit()
    ,如您所需)

    对于第1部分,我没有确切地告诉您该文件是如何签名的。我得到的密钥对用作我自己的(“privatekey_A.pem”和“publickey_A.pem”),其中生成为RSA密钥。“symmetrickey.bin”包含一个对称会话密钥。然后,该文件由发送者私钥签名。我猜他们也有一个RSA密钥集,可能使用了EVP库来密封它。我在这一步的工作是使用EVP_open()取消签名并将会话密钥存储在.txt文件中。我的理解是,在取消签名后,此文件将用作加密密钥。嗨,克里斯,你检查了我提供的StackOverflow链接了吗?它包含了一个相当完整的例子,对您的案例进行了完整的解释。我相信是这样的,我遵循了该页面的一个链接,并给出了EVP_Seal()和EVP_Open()的例子。我将在接下来的几天开始编译代码,以确认所有代码都可以一起工作,但这给了我更多的澄清。我会在下一个被“man evp”页面弄糊涂的人完成所有工作后发布编辑:我记得我自己不止一次在与openssl文档作斗争。。。这确实需要一些工作
    #include <string.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <openssl/evp.h>
    
    #define APPNAME "C"
    
    #define CHUNK_SIZE 512
    int do_crypt(FILE *in, FILE *out, int do_encrypt)
    {
        /* Allow enough space in output buffer for additional block */
        unsigned char inbuf[CHUNK_SIZE];
        unsigned char outbuf[CHUNK_SIZE + EVP_MAX_BLOCK_LENGTH];
        int inlen;
        int outlen;
        EVP_CIPHER_CTX ctx;
        /* Bogus key and IV: we'd normally set these from
         * another source.
         */
        unsigned char key[] = { 0x13, 0xa3, 0xb4, 0xc1, 0x24, 0x19, 0xf5, 0x23, 0x18, 0xef, 0xca, 0x12, 0x4c, 0x9f, 0x14, 0xfe };
        unsigned char iv[] = { 0x92, 0x1c, 0x23, 0x3f, 0x5e, 0x10, 0x3d, 0x9a };
        /* Don't set key or IV because we will modify the parameters */
        EVP_CIPHER_CTX_init(&ctx);
        /* Using Blowfish encryption with cbc algorithm, you can use whichever is supported in openssl if you wish */
        EVP_CipherInit_ex(&ctx, EVP_bf_cbc(), NULL, NULL, NULL, do_encrypt);
        EVP_CIPHER_CTX_set_key_length(&ctx, 16);
        /* We finished modifying parameters so now we can set key and IV */
        EVP_CipherInit_ex(&ctx, NULL, NULL, key, iv, do_encrypt);
        for(;;)
        {
            inlen = fread(inbuf, 1, CHUNK_SIZE, in);
            if(inlen <= 0) break;
            if(!EVP_CipherUpdate(&ctx, outbuf, &outlen, inbuf, inlen))
            {
                /* Error */
                EVP_CIPHER_CTX_cleanup(&ctx);
                return -1;
            }
            fwrite(outbuf, 1, outlen, out);
        }
        if(!EVP_CipherFinal_ex(&ctx, outbuf, &outlen))
        {
            /* Error */
            EVP_CIPHER_CTX_cleanup(&ctx);
            return -1;
        }
        fwrite(outbuf, 1, outlen, out);
        EVP_CIPHER_CTX_cleanup(&ctx);
        rewind(in);
        rewind(out);
        return 0;
    }
    
    /* This is the standalone encryptor entry point */
    int main(int argc, char** argv)
    {
        FILE *encode_file;
        FILE *decode_file;
        int enc_or_dec;
        if (argc < 4)
        {
            printf("Usage: %s [plain file] [encrypted file] [0/1 deccrypt/encrypt]\n", argv[0]);
            return -1;
        }
        encode_file = fopen(argv[1], "r");
        decode_file = fopen(argv[2], "w+");
        /* Stupid decimal translation */
        enc_or_dec = *argv[3]-48;
    
        do_crypt(encode_file, decode_file, enc_or_dec);
        return 0;
    }
    
    all:
        gcc cryptor.c -o cryptor -g -lcrypto -I ../openssl-1.0.1f-host/include
    clean:
        rm cryptor