> From: owner-openssl-us...@openssl.org  On Behalf Of PVi1
> Sent: Sunday, 19 April, 2009 13:12

> i am trying to write application used for verifying digest 
> signature of text files.
> I have used this command to create sign of file e.g. index.php:
> openssl dgst -sha1 -sign private_key.pem -out sign.sha1 
> /var/www/index.php I have many files with signatures from 
> many users signed by its private keys.
> Right now, when i am trying to verify signature, first of all 
> I find who is owner of "index.php" file and ask the database 
> for path to its public key.
> After that I use this key to verify sign of file with:
> It works OK.

Barely; see below.

> ///-----------------------------------------
> //begin of verification code
> sig_handle = VCWD_FOPEN(sign,"rb"))==NULL signature = (char 
> *) emalloc(fst_sig.st_size + 2) signature_len = 
> fread(signature, sizeof(char), fst_sig.st_size + 1, 
> sig_handle); while(!feof(sig_handle)){
>               j++;
>               if ((signature = erealloc(signature, 
> (fst_sig.st_size * j) +1)) == NULL){
>                       php_printf("error");
>                       return;
>               }
>               signature_len += fread(signature, sizeof(char), 
> fst_sig.st_size, sig_handle);
>               signature[signature_len]='\0';
>       }

This was garbled, but I guess it's something like
  fh = fopen
  fstat (fileno(fh), &fst_sig)
  sig_buf = malloc (fst_sig.st_size)
  sig_len = fread (sig_buf,1, fst_sig.st_size, fh)
  while( !feof(fh) )
    realloc, fread more?
  sig_buf[sig_len] = null

If fst_sig.st_size is indeed the size of the file,
that while !feof loop is useless; the first fread 
will always get the entire file. If not, it's wrong;
it repeatedly replaces the beginning of the buffer 
with chunks of the file, leaving the rest garbage.

You don't need the added null byte for OpenSSL;
crypto data like this cannot safely be treated as 
a C string (null terminated, using strlen() et al) 
because it can validly contain zero bytes.

> mdtype = EVP_get_digestbyname("sha1");
> if (!mdtype) {
>               php_error_docref(NULL TSRMLS_CC, E_WARNING, 
> "Unknown signature algorithm.");
>               exit -1;
>       }
> EVP_VerifyInit   (&md_ctx, mdtype);
> while((data_len = fread(data, sizeof(char), fst.st_size, 
> orig_handle)) > 0){
>       data[data_len]='\0';
>       EVP_VerifyUpdate (&md_ctx, data, data_len);
>       data = "";
>       }
> err = EVP_VerifyFinal (&md_ctx, signature, signature_len, 
> pkey); //end of code -------------------------------------
> 
Similarly, if fst.st_size is the size of the data file,
and data points to a buffer at least that large, that loop 
will only execute once. If not, it will screw up badly;
data = "" sets the pointer to a literal string, leaking the 
presumably malloc'ed buffer and causing the next fread 
to try to trash memory you aren't allowed to write.

> My question is: Is there any other way of selecting right 
> public key(without querying database)? I have read smth about 
> load_verify_locations but i dont know if i can use this for 
> public keys?Maybe i can edit signature file to add some 
> identification which can be used when selecting right public key.
> 
> Could somebody write me if i am going the right way,when 
> getting path to user public key from database?
> Or this is wrong concept and it can be done more effectively?
> 
Associating parties with keys is a need of essentially all 
publickey/asymmetric cryptosystems (and nearly all symmetric also) 
and there are lots of methods. Probably the most common 
and best supported by OpenSSL is X.509 certificates.

The purpose of certificates is to 'bind' an entity to its pubkey 
in a 'trustworthy' way. To do this the cert contains the name of the 
'subject' -- standardly in a form called a 'distinguished' name, and 
optionally in other forms for example an email address -- plus the pubkey 
and some control information, all signed by a Certificate Authority.
(In the simple case the entity cert is signed directly by the CA root.
There is also the possibility of intermediate CA keys/certs, but 
I will skip over that as it doesn't change the fundamental principles.)

The relier is configured explicitly with the CAs (roots) it trusts.
If you receive a cert that is correctly signed by a given CA (issuer), 
and whose subject matches the person or system you are receiving 
data from (or sending to, for encryption), and you (are configured to) 
trust that the given CA issues certificates correctly, then you (can) 
trust that the pubkey in the cert is the correct pubkey for that 
sender=signer (or receiver=decrypter). Each piece of signed data 
(e.g. file) must be associated either with the actual cert (or chain),
or with an identifier of the cert you already have stored.
In these cases, load_verify_locations (or set_default_verify_paths
if you use the defaults) will cause OpenSSL's builtin verify logic 
to find the certs for you, without any explicit coding.

There are many other solutions, basically similar. The important point 
in all methods is to identify either the pubkey, or the party to whom 
the key belongs and map that to the key -- usually one, sometimes 
a few and then you just try all of them to find the correct one.
PEM did one way, PGP did somewhat different, and so on.
It sounds like you have a database mapping filesource=party to pubkey;
that is a possible solution that may well be reasonable for you.



______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to