I thought I had posted this already but cannot seem to find it.

I have tried by all means to figure out the API to create a PKCS7 for a
signature file.
Basically I have a signature file and want to wrapper it in a PKCS7. The
Signature is an
ECDSA and uses a SHA256 digest of a file that needs to be Authenticated. 

So I wrote an
abstract program and have some dead ends as I cannot figure what API
functions to use
and the meaning behind them from their names, too many vague
interpretations.

So please look at the  bold comments, I thinks lots of people can benefit
from the forum results

/**
 Platform: Mac OSX 10.7 
    cc -o stuff -Wno-deprecated-declarations stuff.c -lcrypto

This is sample prototype code for questions how to use a PKCS7 to envelope a 
ECDSA (signature) to verify the contents of a file.

The current process is that a file contents is sent to a user which has a
signature 
(ECDSA) for the file that was created using message digest algorithm SHA256
from its contents.

Basically the file data is extracted and an SHA256 message digest (md) is
created 
then the signature file data is extracted (sig) and verified using the x509
public key.

  ret = ECDSA_verify(0, md ,SHA256_DIGEST_LENGTH, sig, siglen,
x509pubeckey);

Instead a PKCS7 is to be used as it can envelope the ECDSA with an x509 cert
for identification best practices.  But is is not really clear how this is
done so schaffolding code is shown below as we walk through it.

This file information can be compiled.

*****************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include <openssl/ssl.h>
#include <openssl/evp.h>


/***
 * Get the data from file and return a malloced buffer and size.
 * This code does not need to be digested it simply returns the whole
contents if data
 * from reading a file.
 **/
unsigned char *getdata(char *filename, int *length){
    FILE *fp =fopen(filename, "rb");
    long avail;

    *length=0;
    if (fp==(FILE *)0){
      printf("Get Data %s File error %d\n",filename,errno);
      return NULL;
    }

    fseek(fp, 0L, SEEK_END);
    avail = ftell(fp);
    fseek(fp, 0L, SEEK_SET);
    unsigned char *b= (unsigned char *) malloc(avail+1);
    if (fread (b,1,avail,fp)!=avail){
        printf("INPUT JPG fail %s read error %d\n",filename, errno);    
        return NULL;
    }
    b[avail]=0;    // added one byte for debug if you use a text file
    *length=(int)avail;  // but length returned is true length of data
    fclose(fp);
    return b;
}




void help(){
        printf("\n");
        printf("Usage  infile\n");
        printf("eg:\n");
        printf("   stuff  sample.data \n\n");
}


int main(int argc, char *args[])
{
  int length;
  unsigned char *data;
  EVP_MD_CTX mdctx;
  const EVP_MD *md;
  unsigned char md_value[EVP_MAX_MD_SIZE];
  unsigned int md_len, i;
  int rc;


  if (argc<2){
    help();
    return 1;
  }

  /**
   * Lets first compute a Message digest for a file contents to test out the
SHA256
   * data will have our file contents.
   ***/
    if  ( (data= getdata(args[1],&length))==NULL)
      return 1;
    printf("INPUT file %s length %d \n",args[1],length);


  //   OpenSSL_add_all_digests();
   EVP_add_digest(EVP_sha256());        //load our algorithm
   md = EVP_get_digestbyname("SHA256");
   printf("DIGEST is SHA256\n");

   EVP_MD_CTX_init(&mdctx);
   EVP_DigestInit_ex(&mdctx, md, NULL);
   EVP_DigestUpdate(&mdctx, data,length);   //use our file contents
   EVP_DigestFinal_ex(&mdctx, md_value, &md_len);
   EVP_MD_CTX_cleanup(&mdctx);

//Okay now we have a Message Digest from the file
   printf("Digest is: ");
   for(i = 0; i < md_len; i++) printf("%02x", md_value[i]);
   printf("\n");



 /**
  * Create a PKCS7 with x509 public CERT to use to envelope a 
  * ECDSA (signature) that used a SHA256 message digest
  * This convenience function below:
  *
  *       PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509)
*certs, BIO *data, int flags);
  *
  * cannot be used to create a PKCS7 as the signature process uses SHA1
  * and we require a SHA256 for our pevkey for an ECDSA 
  *
  * Our intent is the following, we have a ECDSA (signature) that was
created from a file's contents
  * using a SHA256 message digest. The ECDSA is stored in a file (raw). 
  * The file's contents is sent to others which have an x509 public key to
authenticate the file using the ECDSA for the file contents message digest
SHA256.
  *
  * For best Practices a PKCS7 should be used to envelop the ECDSA
signature; the PKCS7 contains an x509 cert to identify the PKCS7 instead of
just having the ECDSA in the raw as a file.
  *  I am not sure what this x509 object should be should it be the x509
with the public key of the ECDSA?
  *  We will not use this file in the PKCS7 but need something to identify
the PKCS7 like an x509 does.
  *  Overall all those that need to authenticate a file have a x509 public
key for the ECDSA obtained by
  *  a secure manner.
  *
  * So here goes some abstraction of code and hopefully someone can point
what functions to use to make it happen
  * correctly.
  **/

 /**
  * create a PKCS7
  **/
  PKCS7 *p7=PKCS7_new();
  if (p7==(PKCS7 *)0){
     printf("NULL PKCS7_new()\n");
     return 1;
  }

  /**
   * Not really sure what type this should be, initially I assumed
NID_pkcs7_data
   * but that  simply traps.
   **/
   rc = PKCS7_set_type(p7, NID_pkcs7_signedAndEnveloped); //
NID_pkcs7_signed); well NID_pkcs7_data will cause an error
   if (rc != 1) {
      printf("RC not good set_type\n");
      return 1;
   }else{
      printf("set type okay \n");
   }

  /**
   * Get our private key as it will be used from some other PKCS7 function
later I assume to sign data?
   * 
   * This key is an Elliptical Curve private key not an RSA.
   **/
   FILE * fp =fopen("ecdsapriv.pem", "rb");
   if (fp==NULL){
     printf("NULL fp \n");
     return 1;
   }

   EVP_PKEY *pevpkey= PEM_read_PrivateKey(fp, NULL, NULL, NULL);
   if (pevpkey==NULL){
      printf("PEM for read private failed\n");
      return 1;
    }
   else
       printf("PEM for read private SUCCESS\n");

   fclose(fp);


   /*
    * Get our x509 which is only contains a public key for EC_KEY, we want
an  x509 as to identify
    * the PKCS7 only. The x509 is not used by others to authenticate just to
identify the PKCS7 I guess
    * Maybe we have a different x509 for the PKCS7? But then what is int it
I simply need identity info for
    * the PKCS7.
    */
    fp =fopen("ecdsapublic.x509.1", "rb");
    X509 *x509=  PEM_read_X509(fp,&x509, NULL, NULL); //its public there is
no password
    if (x509==NULL){
        printf("X509 is null \n");
     }else
        printf("open X509 success\n");
     fclose(fp);


     /**
      * Set the message digest algorithm to use SHA256. The function name
add_signature is not
      * physically adding a signature but a x509 cert (public) and using a
pkey for private signing using 
      * a message digest algorithm of SHA256. Well thats what think. The
private key is not contained in the
      * PKCS7 we hope.
      *
      **/
     PKCS7_SIGNER_INFO *si =  PKCS7_add_signature(p7, x509, pevpkey,
EVP_sha256());
     if (si==NULL) {
        printf("add signature NULL\n");
        return 1;
      }else{
        printf("Add signature success\n");
      }

      BIO *in = NULL, *p7bio = NULL;
      /**
       * I guess we should create a content area for data
       * Not really sure how we use our file contents data contained in
variable data and length
       * to create a message digest for an ECDSA using a message digest
algorithm of SHA256
       **/
      PKCS7_content_new(p7, NID_pkcs7_data);
      p7bio = PKCS7_dataInit(p7, NULL);

      /**
       * I guess we will prime this PKCS7 content area with our message
digest?
       * or do we use our original data that a message digest is to be
constructed from?
       *
       * The point is to create a PKCS7 that has the ECDSA in it with a x509
Cert to indentify.
       **/
      in = BIO_new_mem_buf(md_value, md_len); 
      for (;;) {
                char buf[1024];
                int i = BIO_read(in, buf, sizeof(buf));
                if (i <= 0)
                        break;
                BIO_write(p7bio, buf, i);
        }
        if (!PKCS7_dataFinal(p7, p7bio)) {
             printf("error PKCS7_dataFinal\n");
             return 1;
        }
/**
(1)  I guess we can use these functions to write the PKCS7 out so we can 
  read it later as a PKCS7 file?

      int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags);
       PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont);

 (2)  Some how will use the SMIME_read_PKCS7 and use this object to verify 
  the file contents? How we do that is not known given the PKCS7 object.

  Currently our process is: a file contents is read and a SHA256 is
computed, anyone who needs
  to authenticate has the public EC_KEY which was obtained securely.

***/
     BIO_free(in);

-- 
View this message in context: 
http://old.nabble.com/How-to-create-a-PKCS7-for-a-Signature-using-SHA256-tp34609376p34609376.html
Sent from the OpenSSL - User mailing list archive at Nabble.com.

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

Reply via email to