Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

base64 file digest calculation with openssl

Tags:

c

openssl

I am trying to figure out the way to code the following openssl commands:

Scenario:

Given: Base64 encoded value of a file (b64.txt)

Base64 encoded sha1 digest of the file(exactly 20 byte sha1 digest of this file).

Problem: I have to verify with a C program if the given digest for the file is correct.

My method:

  • I first tried openssl commands to verify the digest before writing a code. Here is how I did it.
  • I decoded this base64 file first and then found the sha1 digest of the file.

I wasn't sure why I never got the 20byte value as output. And with trial and error only these worked:

On a linux system I did the following:

  • base64 -d b64.txt > dec.out (dec.out was a mix of textual and binary(undecipherable) text)
  • openssl dgst -sha1 -binary dec.out > sha1.bin (I found out the digest in binary form assuming the dec.out as binary input)
  • base64 sha1.bin > sha1.b64 (encoding the sha1 result in base64)

Now my sha1.b64 gave a 20byte digest which was the same as that given to me.

First of all I would like to know if the sequence of commands are correct in the first place and if there are easier ways to do it.

Also, with EVP_Digest* how to program this( I mean what input format of the file is specified in these?)

Please clarify.

Thanks

like image 336
user489152 Avatar asked Apr 25 '26 05:04

user489152


1 Answers

That sequence of commands looks correct. You can simplify it by using shell redirection instead of temporary files:

base64 -d b64.txt | openssl dgst -sha1 -binary | base64

To do the same thing in C using the OpenSSL library, you can use the BIO abstraction to good effect:

#include <stdio.h>
#include <openssl/bio.h>
#include <openssl/evp.h>

int main(int argc, char *argv[])
{
    BIO *bio_in, *b64, *md, *bio_out;
    char buf[1024];
    char mdbuf[EVP_MAX_MD_SIZE];
    int mdlen;

    /* setup input BIO chain */
    bio_in = BIO_new_fp(stdin, BIO_NOCLOSE);

    b64 = BIO_new(BIO_f_base64());
    bio_in = BIO_push(b64, bio_in);

    md = BIO_new(BIO_f_md());
    BIO_set_md(md, EVP_sha1());
    bio_in = BIO_push(md, bio_in);

    /* reading through the MD BIO calculates the digest */
    while (BIO_read(bio_in, buf, sizeof buf) > 0)
        ;

    /* retrieve the message digest */
    mdlen = BIO_gets(md, mdbuf, sizeof mdbuf);

    /* setup output BIO chain */
    bio_out = BIO_new_fp(stdout, BIO_NOCLOSE);

    b64 = BIO_new(BIO_f_base64());
    bio_out = BIO_push(b64, bio_out);

    /* write out digest */
    BIO_write(bio_out, mdbuf, mdlen);
    BIO_flush(bio_out);

    BIO_free_all(bio_in);
    BIO_free_all(bio_out);

    return 0;
}

The above program will read base64 input on stdin, and write the base64 encoded SHA1 hash to stdout.

like image 55
caf Avatar answered Apr 27 '26 17:04

caf