openssl做文件处理(base64,MD5,sha256等)

这次使用openssl,发现openssl不仅可以用来做加密和解密,实际上也可以用来做文件的处理,比如base64转码、解码,文件md5的计算等。实现这些,即可以从命令行去做,也可以通过代码去实现。

1. 命令行操作

        1. base64转码、解码       

        转码:

        openssl base64 -in file.bin -out file.b64 对file.bin文件进行转码,转码后的文件为file.b64

        上述命令转码生成的文件带有换行符,如果想要生成的base64文件不带换行符,那么使用

        openssl base64 -A -in file.bin -out file.b64。

        解码:

        openssl base64 -d -in file.b64 -out file.bin 对file.b64进行解码,解码后的文件为file.bin

        如果转码时有“-A”,那么解码时也要有-A。

        注:对于大文件,加A可能会有问题。我拿2.3G的绿皮书电影做测试,发现加A后,转码再解码,文件变更大了,电影也无法播放。不加A就没有问题。另外,man openssl-enc中,搜索Bug,也有如下描述:

        The -A option when used with large files doesn't work properly

        2. md5码的生成

        openssl dgst -md5 a.out  计算a.out文件的md5码

        如果生成sha256码,将上面的md5改为sha256即可。

2. 代码实现文件操作

        1. base64转码、解码

        有换行符的转码方式,使用的接口为:

        EVP_ENCODE_CTX_new,EVP_EncodeUpdate,EVP_EncodeFinal,和EVP_ENCODE_CTX_free。

static int t_tob64(char *dst, const unsigned char *src, int size)
{
    EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new();
    int outl = 0, outl2 = 0;

    if (ctx == NULL)
        return 0;

    EVP_EncodeInit(ctx);

    if (!EVP_EncodeUpdate(ctx, (unsigned char *)dst + outl, &outl2, src,
                          size)) {
        EVP_ENCODE_CTX_free(ctx);
        return 0;
    }
    cout<<"first len is "<

        这个函数将长度为size个字节的,地址为src的源数据,转码后保存在dst中。dst的地址长度应该是多大呢?

        我参考了一些资料,经过验证,用下面这个方法,计算出来的与实际需要使用的更加接近。inputLen是输入字符串的长度。outLen是预计输出字符串的长度。76是指根据RF2045,base64转码后,每超过76个字符,会添加回车换行。前面的%3操作,是补位操作。

    if(inputLen%3==0)
        outLen = inputLen/3 *4;
    else
        outLen = (inputLen/3 +1)*4;       
    outLen = outLen + (outLen-1)/76*2;

       按照这种方法来设计缓存,比实际需要的长度略大。而且我自己最后生成base64时发现,并不是76个字符有一个换行符,而是64个字符有一个换行符。如果把上面的76换成64,然后将回车符用一个字符计算,也就是outLen = outLen + (outLen-1)/64,这样预算的缓存长度最后与实际需要的缓存长度是匹配的。

        不带换行符的转码方式,使用的接口:

        EVP_EncodeBlock。

int t_tob64_block(char *dst, const unsigned char *src, int size)
{
    int outLen=0;

    outLen = EVP_EncodeBlock((unsigned char *)dst ,src,size);

    return outLen;
}

        这种的长度计算只要考虑补位的长度即可。

        2. md5等码值的计算

        使用的接口包括EVP_MD_CTX_new,EVP_DigestInit_ex,EVP_DigestUpdate,EVP_DigestFinal_ex和EVP_MD_CTX_free。

int main(int argc, char *argv[])
 {
     EVP_MD_CTX *mdctx;
     const EVP_MD *md;
     string content = "";
     readFile("file.bin",content);
     unsigned char md_value[EVP_MAX_MD_SIZE];
     unsigned int md_len, i;

     if (argv[1] == NULL) {
         printf("Usage: mdtest digestname\n");
         exit(1);
     }

     md = EVP_get_digestbyname(argv[1]);
     if (md == NULL) {
         printf("Unknown message digest %s\n", argv[1]);
         exit(1);
     }

     mdctx = EVP_MD_CTX_new();
     EVP_DigestInit_ex(mdctx, md, NULL);
     EVP_DigestUpdate(mdctx, (char*)content.c_str(), content.length());
     //EVP_DigestUpdate(mdctx, mess2, strlen(mess2));
     EVP_DigestFinal_ex(mdctx, md_value, &md_len);
     EVP_MD_CTX_free(mdctx);

     printf("Digest is: ");
     for (i = 0; i < md_len; i++)
         printf("%02x", md_value[i]);
     printf("\n");

     exit(0);
 }

        这里输入的参数是码值算法的名字,通过EVP_get_digestbyname函数,根据名字,找到对应的算法。名字怎么命名呢?openssl dgst -list就可以找出所有的支持的算法。如下所示:

        openssl做文件处理(base64,MD5,sha256等)_第1张图片

         因此使用md5,只要输入md5即可。

        

你可能感兴趣的:(linux,安全,ssl)