155714SkrisFrom ssl-lists-owner@mincom.com Mon Sep 30 22:43:15 1996
255714SkrisReceived: from cygnus.mincom.oz.au by orb.mincom.oz.au with SMTP id AA12802
355714Skris  (5.65c/IDA-1.4.4 for eay); Mon, 30 Sep 1996 12:45:43 +1000
455714SkrisReceived: (from daemon@localhost) by cygnus.mincom.oz.au (8.7.5/8.7.3) id MAA25922 for ssl-users-outgoing; Mon, 30 Sep 1996 12:43:43 +1000 (EST)
555714SkrisReceived: from orb.mincom.oz.au (eay@orb.mincom.oz.au [192.55.197.1]) by cygnus.mincom.oz.au (8.7.5/8.7.3) with SMTP id MAA25900 for <ssl-users@listserv.mincom.oz.au>; Mon, 30 Sep 1996 12:43:39 +1000 (EST)
655714SkrisReceived: by orb.mincom.oz.au id AA12688
755714Skris  (5.65c/IDA-1.4.4 for ssl-users@listserv.mincom.oz.au); Mon, 30 Sep 1996 12:43:16 +1000
855714SkrisDate: Mon, 30 Sep 1996 12:43:15 +1000 (EST)
955714SkrisFrom: Eric Young <eay@mincom.com>
1055714SkrisX-Sender: eay@orb
1155714SkrisTo: Sampo Kellomaki <sampo@neuronio.pt>
1255714SkrisCc: ssl-users@mincom.com, sampo@brutus.neuronio.pt
1355714SkrisSubject: Re: Signing with envelope routines
1455714SkrisIn-Reply-To: <199609300037.BAA08729@brutus.neuronio.pt>
1555714SkrisMessage-Id: <Pine.SOL.3.91.960930121504.11800Y-100000@orb>
1655714SkrisMime-Version: 1.0
1755714SkrisContent-Type: TEXT/PLAIN; charset=US-ASCII
1855714SkrisSender: ssl-lists-owner@mincom.com
1955714SkrisPrecedence: bulk
2055714SkrisStatus: O
2155714SkrisX-Status: 
2255714Skris
2355714Skris
2455714SkrisOn Mon, 30 Sep 1996, Sampo Kellomaki wrote:
2555714Skris> I have been trying to figure out how to produce signatures with EVP_
2655714Skris> routines. I seem to be able to read in private key and sign some
2755714Skris> data ok, but I can't figure out how I am supposed to read in
2855714Skris> public key so that I could verify my signature. I use self signed
2955714Skris> certificate.
3055714Skris
3155714Skrishmm... a rather poorly documented are of the library at this point in time.
3255714Skris
3355714Skris> I figured I should use
3455714Skris> 	EVP_PKEY* pkey = PEM_ASN1_read(d2i_PrivateKey, PEM_STRING_EVP_PKEY,
3555714Skris> 	                               fp, NULL, NULL);
3655714Skris> to read in private key and this seems to work Ok.
3755714Skris> 
3855714Skris> However when I try analogous
3955714Skris> 	EVP_PKEY* pkey = PEM_ASN1_read(d2i_PublicKey, PEM_STRING_X509,
4055714Skris> 	                               fp, NULL, NULL);
4155714Skris
4255714SkrisWhat you should do is 
4355714Skris	X509 *x509=PEM_read_X509(fp,NULL,NULL);
4455714Skris	/* which is the same as PEM_ASN1_read(d2i_X509,PEM_STRING_X509,fp,
4555714Skris	 * NULL,NULL); */
4655714SkrisThen
4755714Skris	EVP_PKEY *pkey=X509_extract_key(x509);
4855714Skris
4955714SkrisThere is also a X509_REQ_extract_key(req);
5055714Skriswhich gets the public key from a certificate request.
5155714Skris
5255714SkrisI re-worked quite a bit of this when I cleaned up the dependancy on
5355714SkrisRSA as the private key.
5455714Skris
5555714Skris> I figured that the second argument to PEM_ASN1_read should match the
5655714Skris> name in my PEM encoded object, hence PEM_STRING_X509.
5755714Skris> PEM_STRING_EVP_PKEY seems to be somehow magical
5855714Skris> because it matches whatever private key there happens to be. I could
5955714Skris> not find a similar constant to use with getting the certificate, however.
6055714Skris
6155714Skris:-), PEM_STRING_EVP_PKEY is 'magical' :-).  In theory I should be using a
6255714Skrisstandard such as PKCS#8 to store the private key so that the type is 
6355714Skrisencoded in the asn.1 encoding of the object.
6455714Skris
6555714Skris> Is my approach of using PEM_ASN1_read correct? What should I pass in
6655714Skris> as name?  Can I use normal (or even self signed) X509 certificate for
6755714Skris> verifying the signature?
6855714Skris
6955714SkrisThe actual public key is kept in the certificate, so basically you have 
7055714Skristo load the certificate and then 'unpack' the public key from the 
7155714Skriscertificate.
7255714Skris
7355714Skris> When will SSLeay documentation be written ;-)? If I would contribute
7455714Skris> comments to the code, would Eric take time to review them and include
7555714Skris> them in distribution?
7655714Skris
7755714Skris:-) After SSLv3 and PKCS#7 :-).  I actually started doing a function list 
7855714Skrisbut what I really need to do is do quite a few 'this is how you do xyz' 
7955714Skristype documents.  I suppose the current method is to post to ssl-users and 
8055714SkrisI'll respond :-).
8155714Skris
8255714SkrisI'll add a 'demo' directory for the next release, I've appended a 
8355714Skrismodified version of your program that works, you were very close :-).
8455714Skris
8555714Skriseric
8655714Skris
8755714Skris/* sign-it.cpp  -  Simple test app using SSLeay envelopes to sign data
8855714Skris   29.9.1996, Sampo Kellomaki <sampo@iki.fi> */
8955714Skris
9055714Skris/* converted to C - eay :-) */
9155714Skris
9255714Skris#include <stdio.h>
9355714Skris#include "rsa.h"
9455714Skris#include "evp.h"
9555714Skris#include "objects.h"
9655714Skris#include "x509.h"
9755714Skris#include "err.h"
9855714Skris#include "pem.h"
9955714Skris#include "ssl.h"
10055714Skris
10155714Skrisvoid main ()
10255714Skris{
10355714Skris  int err;
10455714Skris  int sig_len;
10555714Skris  unsigned char sig_buf [4096];
10655714Skris  static char certfile[] = "plain-cert.pem";
10755714Skris  static char keyfile[]  = "plain-key.pem";
10855714Skris  static char data[]     = "I owe you...";
10955714Skris  EVP_MD_CTX     md_ctx;
11055714Skris  EVP_PKEY *      pkey;
11155714Skris  FILE *          fp;
11255714Skris  X509 *	x509;
11355714Skris
11455714Skris  /* Just load the crypto library error strings,
11555714Skris   * SSL_load_error_strings() loads the crypto AND the SSL ones */
11655714Skris  /* SSL_load_error_strings();*/
11755714Skris  ERR_load_crypto_strings();
11855714Skris  
11955714Skris  /* Read private key */
12055714Skris  
12155714Skris  fp = fopen (keyfile, "r");   if (fp == NULL) exit (1);
12255714Skris  pkey = (EVP_PKEY*)PEM_ASN1_read ((char *(*)())d2i_PrivateKey,
12355714Skris				   PEM_STRING_EVP_PKEY,
12455714Skris				   fp,
12555714Skris				   NULL, NULL);
12655714Skris  if (pkey == NULL) {  ERR_print_errors_fp (stderr);    exit (1);  }
12755714Skris  fclose (fp);
12855714Skris  
12955714Skris  /* Do the signature */
13055714Skris  
13155714Skris  EVP_SignInit   (&md_ctx, EVP_md5());
13255714Skris  EVP_SignUpdate (&md_ctx, data, strlen(data));
13355714Skris  sig_len = sizeof(sig_buf);
13455714Skris  err = EVP_SignFinal (&md_ctx,
13555714Skris		       sig_buf, 
13655714Skris		       &sig_len,
13755714Skris		       pkey);
13855714Skris  if (err != 1) {  ERR_print_errors_fp (stderr);    exit (1);  }
13955714Skris  EVP_PKEY_free (pkey);
14055714Skris  
14155714Skris  /* Read public key */
14255714Skris  
14355714Skris  fp = fopen (certfile, "r");   if (fp == NULL) exit (1);
14455714Skris  x509 = (X509 *)PEM_ASN1_read ((char *(*)())d2i_X509,
14555714Skris				   PEM_STRING_X509,
14655714Skris				   fp, NULL, NULL);
14755714Skris  if (x509 == NULL) {  ERR_print_errors_fp (stderr);    exit (1);  }
14855714Skris  fclose (fp);
14955714Skris  
15055714Skris  /* Get public key - eay */
15155714Skris  pkey=X509_extract_key(x509);
15255714Skris  if (pkey == NULL) {  ERR_print_errors_fp (stderr);    exit (1);  }
15355714Skris
15455714Skris  /* Verify the signature */
15555714Skris  
15655714Skris  EVP_VerifyInit   (&md_ctx, EVP_md5());
15755714Skris  EVP_VerifyUpdate (&md_ctx, data, strlen((char*)data));
15855714Skris  err = EVP_VerifyFinal (&md_ctx,
15955714Skris			 sig_buf,
16055714Skris			 sig_len,
16155714Skris			 pkey);
16255714Skris  if (err != 1) {  ERR_print_errors_fp (stderr);    exit (1);  }
16355714Skris  EVP_PKEY_free (pkey);
16455714Skris  printf ("Signature Verified Ok.\n");
16555714Skris}
16655714Skris
16755714Skris
16855714Skris
16955714Skris
17055714Skris
171