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