void printPubKey(feePubKey pubKey)
{
	pubKeyInst *pkinst = pubKey;

	printf("\ncurveParams:\n");
	printCurveParams(pkinst->cp);
	printf("plus:\n");
	printKey(pkinst->plus);
	printf("minus:\n");
	printKey(pkinst->minus);
	if(pkinst->privGiant != NULL) {
	    printf("privGiant : ");
	    printGiant(pkinst->privGiant);
	}
}
feeReturn feeSigVerify(feeSig sig,
	const unsigned char *data,
	unsigned dataLen,
	feePubKey pubKey)
{
	pointProjStruct Q;
	giant 		messageGiant = NULL;
	pointProjStruct	scratch;
	sigInst 	*sinst = (sigInst*) sig;
	feeReturn	frtn;
	curveParams	*cp;
	key		origKey;		// may be plus or minus key

	if(sinst->PmX == NULL) {
		dbgLog(("sigVerify without parse!\n"));
		return FR_IllegalArg;
	}

	cp = feePubKeyCurveParams(pubKey);
	if(cp->curveType != FCT_Weierstrass) {
		return feeSigVerifyNoProj(sig, data, dataLen, pubKey);
	}

	borrowPointProj(&Q, cp->maxDigits);
	borrowPointProj(&scratch, cp->maxDigits);

	/*
	 * Q := P1
	 */
	gtog(cp->x1Plus, Q.x);
	gtog(cp->y1Plus, Q.y);
	int_to_giant(1, Q.z);

	messageGiant = 	giant_with_data(data, dataLen);	// M(ciphertext)

	/* Q := u 'o' P1 */
	ellMulProjSimple(&Q, sinst->u, cp);

	/* scratch := theirPub */
	origKey = feePubKeyPlusCurve(pubKey);
	gtog(origKey->x, scratch.x);
	gtog(origKey->y, scratch.y);
	int_to_giant(1, scratch.z);

	#if	SIG_DEBUG
	if(sigDebug) {
		printf("verify origKey:\n");
		printKey(origKey);
		printf("messageGiant: ");
		printGiant(messageGiant);
		printf("curveParams:\n");
		printCurveParams(cp);
	}
	#endif	// SIG_DEBUG

	/* scratch := M 'o' theirPub */
	ellMulProjSimple(&scratch, messageGiant, cp);

	#if	SIG_DEBUG
	if(sigDebug) {
		printf("signature_compare, with\n");
		printf("p0 = Q:\n");
		printGiant(Q.x);
		printf("p1 = Pm:\n");
		printGiant(sinst->PmX);
		printf("p2 = scratch = R:\n");
		printGiant(scratch.x);
	}
	#endif	// SIG_DEBUG

	if(signature_compare(Q.x, sinst->PmX, scratch.x, cp)) {

		frtn = FR_InvalidSignature;
		#if	LOG_BAD_SIG
		printf("***yup, bad sig***\n");
		#endif	// LOG_BAD_SIG
	}
	else {
		frtn = FR_Success;
	}
	freeGiant(messageGiant);

    	returnPointProj(&Q);
    	returnPointProj(&scratch);
	return frtn;
}
/*
 * FEE_SIG_USING_PROJ true  : this is the "no Weierstrass" case
 * feeSigVerifyNoProj false : this is redefined to feeSigVerify
 */
feeReturn feeSigVerifyNoProj(feeSig sig,
	const unsigned char *data,
	unsigned dataLen,
	feePubKey pubKey)
{
	giant 		Q = NULL;
	giant 		messageGiant = NULL;
	giant 		scratch = NULL;
	sigInst 	*sinst = (sigInst*) sig;
	feeReturn	frtn;
	curveParams	*cp;
	key		origKey;		// may be plus or minus key

	if(sinst->PmX == NULL) {
		dbgLog(("sigVerify without parse!\n"));
		frtn = FR_IllegalArg;
		goto out;
	}

	cp = feePubKeyCurveParams(pubKey);
	Q = newGiant(cp->maxDigits);

	/*
	 * pick a key (+/-)
	 * Q := P1
	 */
	if(SIG_CURVE == CURVE_PLUS) {
		origKey = feePubKeyPlusCurve(pubKey);
		gtog(cp->x1Plus, Q);
	}
	else {
		origKey = feePubKeyMinusCurve(pubKey);
		gtog(cp->x1Minus, Q);
	}

	messageGiant = 	giant_with_data(data, dataLen);	// M(ciphertext)

	/* Q := u 'o' P1 */
	elliptic_simple(Q, sinst->u, cp);

	/* scratch := theirPub */
	scratch = newGiant(cp->maxDigits);
	gtog(origKey->x, scratch);

	#if	SIG_DEBUG
	if(sigDebug) {
		printf("verify origKey:\n");
		printKey(origKey);
		printf("messageGiant: ");
		printGiant(messageGiant);
		printf("curveParams:\n");
		printCurveParams(cp);
	}
	#endif	// SIG_DEBUG

	/* scratch := M 'o' theirPub */
	elliptic_simple(scratch, messageGiant, cp);

	#if	SIG_DEBUG
	if(sigDebug) {
		printf("signature_compare, with\n");
		printf("p0 = Q:\n");
		printGiant(Q);
		printf("p1 = Pm:\n");
		printGiant(sinst->PmX);
		printf("p2 = scratch = R:\n");
		printGiant(scratch);
	}
	#endif	// SIG_DEBUG

	if(signature_compare(Q, sinst->PmX, scratch, cp)) {

		frtn = FR_InvalidSignature;
		#if	LOG_BAD_SIG
		printf("***yup, bad sig***\n");
		#endif	// LOG_BAD_SIG
	}
	else {
		frtn = FR_Success;
	}
out:
	if(messageGiant != NULL) {
	    freeGiant(messageGiant);
	}
	if(Q != NULL) {
	    freeGiant(Q);
	}
	if(scratch != NULL) {
	    freeGiant(scratch);
	}
	return frtn;
}
/*
 * Sign specified block of data (most likely a hash result) using
 * specified feePubKey.
 */
feeReturn feeSigSign(feeSig sig,
	const unsigned char *data,   		// data to be signed
	unsigned dataLen,			// in bytes
	feePubKey pubKey)
{
	sigInst 		*sinst = (sigInst*) sig;
	giant 			messageGiant = NULL;
	unsigned 		maxlen;
	giant 			privGiant;
	unsigned		privGiantBytes;
	feeReturn 		frtn = FR_Success;
	unsigned		randBytesLen;
	unsigned		uDigits;	// alloc'd digits in sinst->u
	curveParams		*cp;

	if(pubKey == NULL) {
		return FR_BadPubKey;
	}
	cp = feePubKeyCurveParams(pubKey);
	if(cp == NULL) {
		return FR_BadPubKey;
	}
	
	privGiant = feePubKeyPrivData(pubKey);
	if(privGiant == NULL) {
		dbgLog(("Attempt to Sign without private data\n"));
		frtn = FR_IllegalArg;
		goto abort;
	}
	privGiantBytes = abs(privGiant->sign) * GIANT_BYTES_PER_DIGIT;

	/*
	 * Note PmX = m 'o' P1.
	 * Get message/digest as giant. May be significantly different
	 * in size from pubKey's basePrime.
	 */
	messageGiant = giant_with_data(data, dataLen);	    // M(text)
	randBytesLen = feePubKeyBitsize(pubKey) / 8;
	maxlen = max(randBytesLen, dataLen);

	/* leave plenty of room.... */
	uDigits = (3 * (privGiantBytes + maxlen)) / GIANT_BYTES_PER_DIGIT;
	sinst->u = newGiant(uDigits);
	gtog(privGiant, sinst->u);			    // u := ourPri
	mulg(messageGiant, sinst->u);			    // u *= M(text)
	addg(sinst->randGiant, sinst->u);		    // u += m

	/*
	 * Paranoia: we're using the curveParams from the caller's pubKey;
	 * this cp will have a valid x1OrderPlusRecip if pubKey is the same
	 * as the one passed to feeSigNewWithKey() (since feeSigNewWithKey
	 * called x1OrderPlusJustify()). But the caller could conceivably be
	 * using a different instance of their pubKey, in which case
	 * the key's cp->x1OrderPlusRecip may not be valid.
	 */
	calcX1OrderPlusRecip(cp);

	/* u := u mod x1OrderPlus */
	#if	SIG_DEBUG
	if(sigDebug) {
		printf("sigSign:\n");
		printf("u pre-modg  : ");
		printGiant(sinst->u);
	}
	#endif
	modg_via_recip(cp->x1OrderPlus, cp->x1OrderPlusRecip, sinst->u);

	#if	SIG_DEBUG
	if(sigDebug) {
		printf("privGiant   : ");
		printGiant(privGiant);
		printf("u           : ");
		printGiant(sinst->u);
		printf("messageGiant: ");
		printGiant(messageGiant);
		printf("curveParams :\n");
		printCurveParams(cp);
	}
	#endif	// SIG_DEBUG
abort:
	if(messageGiant) {
		freeGiant(messageGiant);
	}
	return frtn;
}