Add 'rsautl' low level RSA utility.
authorDr. Stephen Henson <steve@openssl.org>
Sun, 3 Sep 2000 23:13:48 +0000 (23:13 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Sun, 3 Sep 2000 23:13:48 +0000 (23:13 +0000)
Add DER public key routines.

Add -passin argument to 'ca' utility.

Document sign and verify options to dgst.

12 files changed:
CHANGES
apps/Makefile.ssl
apps/apps.c
apps/apps.h
apps/ca.c
apps/progs.h
apps/progs.pl
apps/rsautl.c [new file with mode: 0644]
crypto/x509/x509.h
crypto/x509/x_all.c
doc/apps/ca.pod
doc/apps/dgst.pod

diff --git a/CHANGES b/CHANGES
index dde9f64..424a25c 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,11 @@
 
  Changes between 0.9.5a and 0.9.6  [xx XXX 2000]
 
+  *) New openssl application 'rsautl'. This utility can be
+     used for low level RSA operations. DER public key
+     BIO/fp routines also added.
+     [Steve Henson]
+
   *) New Configure entry and patches for compiling on QNX 4.
      [Andreas Schneider <andreas@ds3.etech.fh-hamburg.de>]
 
index 7681d24..85fae40 100644 (file)
@@ -35,7 +35,7 @@ SCRIPTS=CA.sh CA.pl der_chop
 EXE= $(PROGRAM)
 
 E_EXE= verify asn1pars req dgst dh dhparam enc passwd gendh errstr \
-       ca crl rsa dsa dsaparam \
+       ca crl rsa rsautl dsa dsaparam \
        x509 genrsa gendsa s_server s_client speed \
        s_time version pkcs7 crl2pkcs7 sess_id ciphers nseq pkcs12 \
        pkcs8 spkac smime rand
@@ -51,14 +51,14 @@ RAND_SRC=app_rand.c
 
 E_OBJ= verify.o asn1pars.o req.o dgst.o dh.o dhparam.o enc.o passwd.o gendh.o errstr.o \
        ca.o pkcs7.o crl2p7.o crl.o \
-       rsa.o dsa.o dsaparam.o \
+       rsa.o rsautl.o dsa.o dsaparam.o \
        x509.o genrsa.o gendsa.o s_server.o s_client.o speed.o \
        s_time.o $(A_OBJ) $(S_OBJ) $(RAND_OBJ) version.o sess_id.o \
        ciphers.o nseq.o pkcs12.o pkcs8.o spkac.o smime.o rand.o
 
 E_SRC= verify.c asn1pars.c req.c dgst.c dh.c enc.c passwd.c gendh.c errstr.c ca.c \
        pkcs7.c crl2p7.c crl.c \
-       rsa.c dsa.c dsaparam.c \
+       rsa.c rsautl.c dsa.c dsaparam.c \
        x509.c genrsa.c gendsa.c s_server.c s_client.c speed.c \
        s_time.c $(A_SRC) $(S_SRC) $(RAND_SRC) version.c sess_id.c \
        ciphers.c nseq.c pkcs12.c pkcs8.c spkac.c smime.c rand.c
index 7ae7c77..e5a42d4 100644 (file)
@@ -592,6 +592,47 @@ EVP_PKEY *load_key(BIO *err, char *file, int format, char *pass)
        return(pkey);
        }
 
+EVP_PKEY *load_pubkey(BIO *err, char *file, int format)
+       {
+       BIO *key=NULL;
+       EVP_PKEY *pkey=NULL;
+
+       if (file == NULL)
+               {
+               BIO_printf(err,"no keyfile specified\n");
+               goto end;
+               }
+       key=BIO_new(BIO_s_file());
+       if (key == NULL)
+               {
+               ERR_print_errors(err);
+               goto end;
+               }
+       if (BIO_read_filename(key,file) <= 0)
+               {
+               perror(file);
+               goto end;
+               }
+       if (format == FORMAT_ASN1)
+               {
+               pkey=d2i_PUBKEY_bio(key, NULL);
+               }
+       else if (format == FORMAT_PEM)
+               {
+               pkey=PEM_read_bio_PUBKEY(key,NULL,NULL,NULL);
+               }
+       else
+               {
+               BIO_printf(err,"bad input format specified for key\n");
+               goto end;
+               }
+ end:
+       if (key != NULL) BIO_free(key);
+       if (pkey == NULL)
+               BIO_printf(err,"unable to load Public Key\n");
+       return(pkey);
+       }
+
 STACK_OF(X509) *load_certs(BIO *err, char *file, int format)
        {
        BIO *certs;
index c44b214..151a94e 100644 (file)
@@ -152,6 +152,7 @@ int app_passwd(BIO *err, char *arg1, char *arg2, char **pass1, char **pass2);
 int add_oid_section(BIO *err, LHASH *conf);
 X509 *load_cert(BIO *err, char *file, int format);
 EVP_PKEY *load_key(BIO *err, char *file, int format, char *pass);
+EVP_PKEY *load_pubkey(BIO *err, char *file, int format);
 STACK_OF(X509) *load_certs(BIO *err, char *file, int format);
 
 #define FORMAT_UNDEF    0
index d28cde9..0931401 100644 (file)
--- a/apps/ca.c
+++ b/apps/ca.c
@@ -216,7 +216,7 @@ int MAIN(int, char **);
 
 int MAIN(int argc, char **argv)
        {
-       char *key=NULL;
+       char *key=NULL,*passargin=NULL;
        int total=0;
        int total_done=0;
        int badops=0;
@@ -333,6 +333,11 @@ EF_ALIGNMENT=0;
                        if (--argc < 1) goto bad;
                        keyfile= *(++argv);
                        }
+               else if (strcmp(*argv,"-passin") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       passargin= *(++argv);
+                       }
                else if (strcmp(*argv,"-key") == 0)
                        {
                        if (--argc < 1) goto bad;
@@ -526,6 +531,11 @@ bad:
                lookup_fail(section,ENV_PRIVATE_KEY);
                goto err;
                }
+       if(!key && !app_passwd(bio_err, passargin, NULL, &key, NULL))
+               {
+               BIO_printf(bio_err,"Error getting password\n");
+               goto err;
+               }
        if (BIO_read_filename(in,keyfile) <= 0)
                {
                perror(keyfile);
index 66fe42e..fbc65de 100644 (file)
@@ -14,6 +14,7 @@ extern int errstr_main(int argc,char *argv[]);
 extern int ca_main(int argc,char *argv[]);
 extern int crl_main(int argc,char *argv[]);
 extern int rsa_main(int argc,char *argv[]);
+extern int rsautl_main(int argc,char *argv[]);
 extern int dsa_main(int argc,char *argv[]);
 extern int dsaparam_main(int argc,char *argv[]);
 extern int x509_main(int argc,char *argv[]);
@@ -67,6 +68,9 @@ FUNCTION functions[] = {
 #ifndef NO_RSA
        {FUNC_TYPE_GENERAL,"rsa",rsa_main},
 #endif
+#ifndef NO_RSA
+       {FUNC_TYPE_GENERAL,"rsautl",rsautl_main},
+#endif
 #ifndef NO_DSA
        {FUNC_TYPE_GENERAL,"dsa",dsa_main},
 #endif
index 3d5e8de..214025c 100644 (file)
@@ -29,7 +29,7 @@ foreach (@ARGV)
        $str="\t{FUNC_TYPE_GENERAL,\"$_\",${_}_main},\n";
        if (($_ =~ /^s_/) || ($_ =~ /^ciphers$/))
                { print "#if !defined(NO_SOCK) && !(defined(NO_SSL2) && defined(NO_SSL3))\n${str}#endif\n"; } 
-       elsif ( ($_ =~ /^rsa$/) || ($_ =~ /^genrsa$/) ) 
+       elsif ( ($_ =~ /^rsa$/) || ($_ =~ /^genrsa$/) || ($_ =~ /^rsautl$/)
                { print "#ifndef NO_RSA\n${str}#endif\n";  }
        elsif ( ($_ =~ /^dsa$/) || ($_ =~ /^gendsa$/) || ($_ =~ /^dsaparam$/))
                { print "#ifndef NO_DSA\n${str}#endif\n"; }
diff --git a/apps/rsautl.c b/apps/rsautl.c
new file mode 100644 (file)
index 0000000..3a58b45
--- /dev/null
@@ -0,0 +1,276 @@
+/* rsautl.c */
+/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+#include "apps.h"
+#include <openssl/err.h>
+#include <openssl/pem.h>
+
+#define RSA_SIGN       1
+#define RSA_VERIFY     2
+#define RSA_ENCRYPT    3
+#define RSA_DECRYPT    4
+
+#define KEY_PRIVKEY    1
+#define KEY_PUBKEY     2
+#define KEY_CERT       3
+
+static void usage(void);
+
+#undef PROG
+
+#define PROG rsautl_main
+
+int MAIN(int argc, char **);
+
+int MAIN(int argc, char **argv)
+{
+       BIO *in = NULL, *out = NULL;
+       char *infile = NULL, *outfile = NULL;
+       char *keyfile = NULL;
+       char rsa_mode = RSA_VERIFY, key_type = KEY_PRIVKEY;
+       int keyform = FORMAT_PEM;
+       char need_priv = 0, badarg = 0, rev = 0;
+       char hexdump = 0, asn1parse = 0;
+       X509 *x;
+       EVP_PKEY *pkey = NULL;
+       RSA *rsa = NULL;
+       unsigned char *rsa_in = NULL, *rsa_out = NULL, pad;
+       int rsa_inlen, rsa_outlen = 0;
+       int keysize;
+
+       int ret = 1;
+
+       argc--;
+       argv++;
+
+       if(!bio_err) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
+       ERR_load_crypto_strings();
+       OpenSSL_add_all_algorithms();
+       pad = RSA_PKCS1_PADDING;
+       
+       while(argc >= 1)
+       {
+               if (!strcmp(*argv,"-in")) {
+                       if (--argc < 1) badarg = 1;
+                        infile= *(++argv);
+               } else if (!strcmp(*argv,"-out")) {
+                       if (--argc < 1) badarg = 1;
+                       outfile= *(++argv);
+               } else if(!strcmp(*argv, "-inkey")) {
+                       if (--argc < 1) badarg = 1;
+                       keyfile = *(++argv);
+               } else if(!strcmp(*argv, "-pubin")) {
+                       key_type = KEY_PUBKEY;
+               } else if(!strcmp(*argv, "-certin")) {
+                       key_type = KEY_CERT;
+               } 
+               else if(!strcmp(*argv, "-asn1parse")) asn1parse = 1;
+               else if(!strcmp(*argv, "-hexdump")) hexdump = 1;
+               else if(!strcmp(*argv, "-raw")) pad = RSA_NO_PADDING;
+               else if(!strcmp(*argv, "-ssl")) pad = RSA_SSLV23_PADDING;
+               else if(!strcmp(*argv, "-pkcs")) pad = RSA_PKCS1_PADDING;
+               else if(!strcmp(*argv, "-sign")) {
+                       rsa_mode = RSA_SIGN;
+                       need_priv = 1;
+               } else if(!strcmp(*argv, "-verify")) rsa_mode = RSA_VERIFY;
+               else if(!strcmp(*argv, "-rev")) rev = 1;
+               else if(!strcmp(*argv, "-encrypt")) rsa_mode = RSA_ENCRYPT;
+               else if(!strcmp(*argv, "-decrypt")) {
+                       rsa_mode = RSA_DECRYPT;
+                       need_priv = 1;
+               } else badarg = 1;
+               if(badarg) {
+                       usage();
+                       goto end;
+               }
+               argc--;
+               argv++;
+       }
+
+       if(need_priv && (key_type == KEY_PRIVKEY)) {
+               BIO_printf(bio_err, "A private key is needed for this operation\n");
+               goto end;
+       }
+
+       switch(key_type) {
+               case KEY_PRIVKEY:
+               pkey = load_key(bio_err, keyfile, keyform, NULL);
+               break;
+
+               case KEY_PUBKEY:
+               pkey = load_pubkey(bio_err, keyfile, keyform);
+               break;
+
+               case KEY_CERT:
+               x = load_cert(bio_err, keyfile, keyform);
+               if(x) {
+                       pkey = X509_get_pubkey(x);
+                       X509_free(x);
+               }
+               break;
+       }
+
+       if(!pkey) {
+               BIO_printf(bio_err, "Error loading key\n");
+               return 1;
+       }
+
+       rsa = EVP_PKEY_get1_RSA(pkey);
+       EVP_PKEY_free(pkey);
+
+       if(!rsa) {
+               BIO_printf(bio_err, "Error getting RSA key\n");
+               ERR_print_errors(bio_err);
+               goto end;
+       }
+
+
+       if(infile) {
+               if(!(in = BIO_new_file(infile, "rb"))) {
+                       BIO_printf(bio_err, "Error Reading Input File\n");
+                       ERR_print_errors(bio_err);      
+                       goto end;
+               }
+       } else in = BIO_new_fp(stdin, BIO_NOCLOSE);
+
+       if(outfile) {
+               if(!(out = BIO_new_file(outfile, "wb"))) {
+                       BIO_printf(bio_err, "Error Reading Output File\n");
+                       ERR_print_errors(bio_err);      
+                       goto end;
+               }
+       } else out = BIO_new_fp(stdout, BIO_NOCLOSE);
+
+       keysize = RSA_size(rsa);
+
+       rsa_in = OPENSSL_malloc(keysize * 2);
+       rsa_out = OPENSSL_malloc(keysize);
+
+       /* Read the input data */
+       rsa_inlen = BIO_read(in, rsa_in, keysize * 2);
+       if(rsa_inlen <= 0) {
+               BIO_printf(bio_err, "Error reading input Data\n");
+               exit(1);
+       }
+       if(rev) {
+               int i;
+               unsigned char ctmp;
+               for(i = 0; i < rsa_inlen/2; i++) {
+                       ctmp = rsa_in[i];
+                       rsa_in[i] = rsa_in[rsa_inlen - 1 - i];
+                       rsa_in[rsa_inlen - 1 - i] = ctmp;
+               }
+       }
+       switch(rsa_mode) {
+
+               case RSA_VERIFY:
+                       rsa_outlen  = RSA_public_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
+               break;
+
+               case RSA_SIGN:
+                       rsa_outlen  = RSA_private_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
+               break;
+
+               case RSA_ENCRYPT:
+                       rsa_outlen  = RSA_public_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
+               break;
+
+               case RSA_DECRYPT:
+                       rsa_outlen  = RSA_private_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
+               break;
+
+       }
+
+       if(rsa_outlen <= 0) {
+               BIO_printf(bio_err, "RSA operation error\n");
+               ERR_print_errors(bio_err);
+               goto end;
+       }
+       ret = 0;
+       if(asn1parse) {
+               if(!ASN1_parse_dump(out, rsa_out, rsa_outlen, 1, -1)) {
+                       ERR_print_errors(bio_err);
+               }
+       } else if(hexdump) BIO_dump(out, (char *)rsa_out, rsa_outlen);
+       else BIO_write(out, rsa_out, rsa_outlen);
+       end:
+       RSA_free(rsa);
+       BIO_free(in);
+       BIO_free(out);
+       if(rsa_in) OPENSSL_free(rsa_in);
+       if(rsa_out) OPENSSL_free(rsa_out);
+       return ret;
+}
+
+static void usage()
+{
+       BIO_printf(bio_err, "Usage: rsautl [options]\n");
+       BIO_printf(bio_err, "-in file        input file\n");
+       BIO_printf(bio_err, "-out file       output file\n");
+       BIO_printf(bio_err, "-inkey file     input key\n");
+       BIO_printf(bio_err, "-pubin          input is an RSA public\n");
+       BIO_printf(bio_err, "-certin         input is a certificate carrying an RSA public key\n");
+       BIO_printf(bio_err, "-ssl            use SSL v2 padding\n");
+       BIO_printf(bio_err, "-raw            use no padding\n");
+       BIO_printf(bio_err, "-pkcs           use PKCS#1 padding (default)\n");
+       BIO_printf(bio_err, "-sign           sign with private key\n");
+       BIO_printf(bio_err, "-verify         verify with public key\n");
+       BIO_printf(bio_err, "-encrypt        encrypt with public key\n");
+       BIO_printf(bio_err, "-decrypt        decrypt with private key\n");
+       BIO_printf(bio_err, "-hexdump        hex dump output\n");
+}
+
index ffa6e01..7808b6a 100644 (file)
@@ -744,6 +744,8 @@ int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp,PKCS8_PRIV_KEY_INFO *p8inf);
 int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key);
 int i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *pkey);
 EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a);
+int i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey);
+EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a);
 #endif
 
 #ifndef NO_BIO
@@ -775,6 +777,8 @@ int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp,PKCS8_PRIV_KEY_INFO *p8inf);
 int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key);
 int i2d_PrivateKey_bio(BIO *bp, EVP_PKEY *pkey);
 EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a);
+int i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey);
+EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a);
 #endif
 
 X509 *X509_dup(X509 *x509);
index dd5796e..9bd6e2a 100644 (file)
@@ -504,6 +504,17 @@ EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a)
                (char *(*)())d2i_AutoPrivateKey, (fp),(unsigned char **)(a)));
 }
 
+int i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey)
+       {
+       return(ASN1_i2d_fp(i2d_PUBKEY,fp,(unsigned char *)pkey));
+       }
+
+EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a)
+{
+       return((EVP_PKEY *)ASN1_d2i_fp((char *(*)())EVP_PKEY_new,
+               (char *(*)())d2i_PUBKEY, (fp),(unsigned char **)(a)));
+}
+
 #endif
 
 PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp,
@@ -541,3 +552,14 @@ EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a)
        return((EVP_PKEY *)ASN1_d2i_bio((char *(*)())EVP_PKEY_new,
                (char *(*)())d2i_AutoPrivateKey, (bp),(unsigned char **)(a)));
        }
+
+int i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey)
+       {
+       return(ASN1_i2d_bio(i2d_PUBKEY,bp,(unsigned char *)pkey));
+       }
+
+EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a)
+       {
+       return((EVP_PKEY *)ASN1_d2i_bio((char *(*)())EVP_PKEY_new,
+               (char *(*)())d2i_PUBKEY, (bp),(unsigned char **)(a)));
+       }
index efe1b3c..d352925 100644 (file)
@@ -23,6 +23,7 @@ B<openssl> B<ca>
 [B<-policy arg>]
 [B<-keyfile arg>]
 [B<-key arg>]
+[B<-passin arg>]
 [B<-cert file>]
 [B<-in file>]
 [B<-out file>]
@@ -99,6 +100,10 @@ the password used to encrypt the private key. Since on some
 systems the command line arguments are visible (e.g. Unix with
 the 'ps' utility) this option should be used with caution.
 
+=item B<-passin arg>
+
+the key password source. For more information about the format of B<arg>
+see the B<PASS PHRASE ARGUMENTS> section in L<openssl(1)|openssl(1)>.
 =item B<-verbose>
 
 this prints extra details about the operations being performed.
index fcfd3ec..6fbf433 100644 (file)
@@ -7,9 +7,16 @@ dgst, md5, md2, sha1, sha, mdc2, ripemd160 - message digests
 =head1 SYNOPSIS
 
 B<openssl> B<dgst> 
-[B<-md5|-md2|-sha1|-sha|mdc2|-ripemd160>]
+[B<-md5|-md2|-sha1|-sha|-mdc2|-ripemd160|-dss1>]
 [B<-c>]
 [B<-d>]
+[B<-hex>]
+[B<-binary>]
+[B<-out filename>]
+[B<-sign filename>]
+[B<-verify filename>]
+[B<-prverify filename>]
+[B<-signature filename>]
 [B<file...>]
 
 [B<md5|md2|sha1|sha|mdc2|ripemd160>]
@@ -19,8 +26,8 @@ B<openssl> B<dgst>
 
 =head1 DESCRIPTION
 
-The digest functions print out the message digest of a supplied file or files
-in hexadecimal form.
+The digest functions output the message digest of a supplied file or files
+in hexadecimal form. They can also be used for digital signing and verification.
 
 =head1 OPTIONS
 
@@ -28,12 +35,51 @@ in hexadecimal form.
 
 =item B<-c>
 
-print out the digest in two digit groups separated by colons.
+print out the digest in two digit groups separated by colons, only relevant if
+B<hex> format output is used.
 
 =item B<-d>
 
 print out BIO debugging information.
 
+=item B<-hex>
+
+digest is to be output as a hex dump. This is the default case for a "normal"
+digest as opposed to a digital signature.
+
+=item B<-binary>
+
+output the digest or signature in binary form.
+
+=item B<-out filename>
+
+filename to output to, or standard output by default.
+
+=item B<-sign filename>
+
+digitally sign the digest using the private key in "filename".
+
+=item B<-verify filename>
+
+verify the signature using the the public key in "filename".
+The output is either "Verification OK" or "Verification Failure".
+
+=item B<-prverify filename>
+
+verify the signature using the  the private key in "filename".
+
+=item B<-signature filename>
+
+the actual signature to verify.
+
+=item B<-rand file(s)>
+
+a file or files containing random data used to seed the random number
+generator, or an EGD socket (see L<RAND_egd(3)|RAND_egd(3)>).
+Multiple files can be specified separated by a OS-dependent character.
+The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
+all others. 
+
 =item B<file...>
 
 file or files to digest. If no files are specified then standard input is
@@ -46,4 +92,13 @@ used.
 The digest of choice for all new applications is SHA1. Other digests are
 however still widely used.
 
+If you wish to sign or verify data using the DSA algorithm then the dss1
+digest must be used.
+
+A source of random numbers is required for certain signing algorithms, in
+particular DSA.
+
+The signing and verify options should only be used if a single file is
+being signed or verified.
+
 =cut