		    /* do key generation stuff */
/*
 * PublicKeyAndChallenge ::= SEQUENCE {
 *     spki SubjectPublicKeyInfo,                                           
 *     challenge IA5STRING                                                  
 * }
 * 
 * SignedPublicKeyAndChallenge ::= SEQUENCE {                               
 *     publicKeyAndChallenge PublicKeyAndChallenge,                         
 *     signatureAlgorithm AlgorithmIdentifier,
 *     signature BIT STRING
 * }
 * 
 *    The public key and challenge string are DER encoded as               
 *    PublicKeyAndChallenge, and then digitally signed with the private key
 *    to produce a SignedPublicKeyAndChallenge. The                     
 *    SignedPublicKeyAndChallenge is base64 encoded, and the ascii data is
 *    finally submitted to the server as the value of a form name/value  
 *    pair, where the name is name as specified by the NAME= attribute of 
 *    the KEYGEN tag. If no challenge string is provided, then it will be
 *    encoded as a IA5STRING of length zero.                               
 */	
	FILE *fp = NULL; /* file to save key to */
	RSA *rsa = NULL; /* key object */
	NETSCAPE_SPKI *spki = NULL;
	EVP_PKEY *pkey = NULL;
	char tfile[256]; /* @@@ arb limit */

	int status = 0;

	char *chalstr = "this should be a challenge";
	int length    = 1024;

	char *passphrase = "this should be a pass phrase", *pp2 = NULL;

	sprintf( tfile, "%s/%s", Lynx_Dir(), PRIVATE_KEY_FILE );
	sprintf(buf, "<pre>");
	(*target->isa->put_block)(target, buf, strlen(buf));

	pkey = EVP_PKEY_new();
	
	/* @@@ obtain key size from someplace? */
	
	/* @@@ insert randomness here */
	sprintf(buf, "Obtaining randomness...\nGenerating key...\n");
	(*target->isa->put_block)(target, buf, strlen(buf));

	rsa = RSA_generate_key( length, RSA_F4, NULL );
	if (rsa == NULL) {
	    sprintf(buf, "Unable to generate rsa key.\n" ); 
	    (*target->isa->put_block)(target, buf, strlen(buf));
	    /* do something real to fail */
	}
	
	status = EVP_PKEY_assign_RSA(pkey, rsa);

	/* @@@ get password. write key to disk */
	sprintf(buf, "Getting password...\n" );
	(*target->isa->put_block)(target, buf, strlen(buf));
	do {
	    passphrase = HTPromptPassword("Please enter a pass phrase for your private key:" );
	    pp2 = HTPromptPassword("Please enter the same pass phrase again to confirm:" );
	} while (strcmp(passphrase,pp2));
	memset( (void *) pp2, '\0', strlen(pp2) );

	sprintf(buf, "Writing key to disk...\n");
	fp = fopen( tfile, "a" );
	status = PEM_write_RSAPrivateKey( fp, rsa, EVP_idea_cbc(),
		passphrase, strlen(passphrase), NULL );
	memset( (void *) passphrase, '\0', strlen(passphrase) );
	fclose(fp);

	if (!status) {
	    sprintf(buf, "Unable to save private key.\n" ); 
	    (*target->isa->put_block)(target, buf, strlen(buf));
	    /* do something real to fail */
	}

	rsa = NULL;

	spki = NETSCAPE_SPKI_new();
	if (spki == NULL) {
	    sprintf(buf, "Unable to generate SPKI.\n" ); 
	    (*target->isa->put_block)(target, buf, strlen(buf));
	    /* do something real to fail */
	}

	/* get the challenge from someplace. */
	ASN1_STRING_set( (ASN1_STRING *) spki->spkac->challenge,
			 chalstr, strlen(chalstr) );

	status = NETSCAPE_SPKI_sign(spki,pkey, EVP_md5());

	/* do something useful */
	sprintf(buf, "Submitting!\n</pre>\n" );
	(*target->isa->put_block)(target, buf, strlen(buf));

	FREE(passphrase);
	FREE(pp2);
	/* @@@ make sure the RSA key is nuked */
	NETSCAPE_SPKI_free( spki );
	EVP_PKEY_free(pkey);
