⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pgpeckey.c

📁 可以实现对邮件的加密解密以及签名
💻 C
📖 第 1 页 / 共 5 页
字号:
	ASSERTEC( pubkey->pkAlg );

	(void) x1;
	(void) x2;
	(void) x3;
	(void) x4;
	(void) x5;
	(void) x6;
	(void) x7;
	(void) x8;
	return kPGPError_PublicKeyUnimplemented;
}

/*
 * Given a buffer of at least "maxesk" bytes, make an PGPESK
 * into it and return the size of the PGPESK, or <0.
 */
static int
ecEncrypt(PGPPubKey const *pubkey, PGPByte const *key,
           PGPSize keylen, PGPByte *esk, PGPSize *esklen,
           PGPRandomContext const *rc, PGPPublicKeyMessageFormat format)
{
#if PGP_ENCRYPT_DISABLE /* [ */

	(void)pubkey;
	(void)key;
	(void)keylen;
	(void)esk;
	(void)esklen;
	(void)rc;
	(void)format;
	return kPGPError_FeatureNotAvailable;

#else /* PGP_ENCRYPT_DISABLE */  /* ]  [ */

	ECpub const *pub = (ECpub *)pubkey->priv;
	ecContextRef ec = pub->ec;
	unsigned t;
	int i;
	PGPUInt32 coordSize, scalarSize, pointSize;
	BigNum bn, bntq, bnorder;
	ecScalarRef td=NULL, td2=NULL;
	ecPointRef tq=NULL, dh=NULL;
	PGPByte *tdbuf=NULL, *maskbuf=NULL, *kbuf=NULL;
	PGPMemoryMgrRef		mgr	= NULL;
	
	mgr	= PGPPeekContextMemoryMgr( pubkey->context );

	ASSERTECENC(pubkey->pkAlg);

	ecGetBufferSize( ec, &coordSize, &scalarSize, NULL, &pointSize );

	if (keylen > MASKBUF_SIZE)
		return kPGPError_PublicKeyTooSmall; /* data too big for pubkey */

	if( format == kPGPPublicKeyMessageFormat_PGP ) {
		if (keylen+2 > MASKBUF_SIZE)
			return kPGPError_PublicKeyTooSmall; /* data too big for pubkey */
		/* Add checksum to key, place temporarily in esk buffer */
		t = 0;
		esk[0] = key[0];
		for (i = 1; i < (int)keylen; i++)
			t += esk[i] = key[i];
		esk[keylen] = (PGPByte)(t >> 8 & 255);
		esk[keylen+1] = (PGPByte)(t & 255);
		keylen += 2;
		key = esk;
	}

	bnBegin(&bn, mgr, SECURE );
	bnBegin(&bntq, mgr, SECURE );
	bnBegin(&bnorder, mgr, INSECURE );

	if( ecScalarCreate( ec, &td, SECURE ) < 0
		|| ecScalarCreate( ec, &td2, SECURE ) < 0
		|| ecPointCreate( ec, &tq ) < 0
		|| ecPointCreate( ec, &dh ) < 0
		|| sScalartoBN( pub->order, &bnorder, mgr, scalarSize ) < 0 )
		goto nomem;

	/* Choose the random td scalar to be used for this encryption */
	tdbuf = PGPNewSecureData( mgr, scalarSize+8, 0 );
	if( IsNull( tdbuf ) )
		goto nomem;
	pgpRandomGetBytes( rc, tdbuf, scalarSize+8 );
	if( bnInsertBigBytes( &bn, tdbuf, 0, scalarSize+8 ) < 0
		|| bnMod( &bn, &bn, &bnorder ) < 0 
		|| sBNtoScalar( &bn, td, mgr, scalarSize ) < 0 )
		goto nomem;

	/* Also calculate td*cofactor % order */
	if( bnMulQ( &bn, &bn, pub->cofactor ) < 0
		|| bnMod( &bn, &bn, &bnorder ) < 0
		|| sBNtoScalar( &bn, td2, mgr, scalarSize ) < 0 )
		goto nomem;

	/* Do EC multiplication to get tq value */
	if( ecPointMul( pub->g, td, FALSE, tq ) < 0 )
		goto nomem;

	/* Calculate shared secret curve point dh */
	if( ecPointMul( pub->y, td2, FALSE, dh ) < 0 )
		goto nomem;

	/* Create maskbuf from shared secret */
	maskbuf = PGPNewSecureData( mgr, MASKBUF_SIZE, 0 );
	if( IsNull( maskbuf ) )
		goto nomem;
	i = sFillEncryptMaskBuf( pubkey->context, dh, coordSize,
							 kPGPHashAlgorithm_SHA, maskbuf, MASKBUF_SIZE );
	if( i < 0 )
		goto done;

	/* PKCS-1 pad the key to encode its length */
	if (pgpPKCSPack(&bn, key, keylen, PKCS_PAD_ENCRYPTED, MASKBUF_SIZE, rc)<0)
		goto nomem;
	kbuf = PGPNewSecureData( mgr, MASKBUF_SIZE, 0 );
	if( IsNull( kbuf ) )
		goto nomem;
	bnExtractBigBytes( &bn, kbuf, 0, MASKBUF_SIZE );

	/* XOR the key with the shared secret */
	for( i=0; i<MASKBUF_SIZE; ++i )
		kbuf[i] ^= maskbuf[i];
	
	/* Prepare to output results */
	t = 0;
	esk[t++] = kPGPHashAlgorithm_SHA;
	if( sPointtoBN( tq, &bntq, mgr, pointSize ) < 0
		|| bnInsertBigBytes( &bn, kbuf, 0, MASKBUF_SIZE ) < 0 )
		goto nomem;

	if (format == kPGPPublicKeyMessageFormat_X509) {
		/* Put in SEQUENCE header for 509 encrypted data */
		PGPUInt32 len_seq, lenlen_seq;
		/* Count size of sequence, counting a 0 byte if hi bit is set */
		if (8*pointSize == bnBits(&bntq))
			len_seq = pgpBnX509LenLen(pointSize+1) + 1 + pointSize+1;
		else
			len_seq = pgpBnX509LenLen(pointSize) + 1 + pointSize;
		if (8*MASKBUF_SIZE == bnBits(&bn))
			len_seq += pgpBnX509LenLen(MASKBUF_SIZE+1) + 1 + MASKBUF_SIZE+1;
		else
			len_seq += pgpBnX509LenLen(MASKBUF_SIZE) + 1 + MASKBUF_SIZE;
		lenlen_seq = pgpBnX509LenLen(len_seq);
		esk[t++] = X509_TAG_SEQUENCE | X509_TAG_CONSTRUCTED;
		if (--lenlen_seq == 0) {
			esk[t++] = len_seq;
		} else {
			esk[t++] = 0x80 | lenlen_seq;
			len_seq <<= 8 * (4-lenlen_seq);
			while (lenlen_seq--) {
				esk[t++] = (PGPByte)(len_seq >> 24);
				len_seq <<= 8;
			}
		}
	}

	/* Pack the two values into the esk, first tq and then xbuf^key */
	t += pgpBnPutFormatted(&bntq, esk+t, pointSize, format);
	t += pgpBnPutFormatted(&bn, esk+t, MASKBUF_SIZE, format);

	if (esklen)
		*esklen = (PGPSize)t;
	
	i = 0;
	goto done;
nomem:
	i = kPGPError_OutOfMemory;
done:
	bnEnd(&bn);
	bnEnd(&bntq);
	bnEnd(&bnorder);
	if( IsntNull( tq ) )
		ecPointFree(tq);
	if( IsntNull( dh ) )
		ecPointFree(dh);
	if( IsntNull( td ) )
		ecScalarFree(td);
	if( IsntNull( td2 ) )
		ecScalarFree(td2);
	if( IsntNull( maskbuf ) )
		PGPFreeData( maskbuf );
	if( IsntNull( tdbuf ) )
		PGPFreeData( tdbuf );
	if( IsntNull( kbuf ) )
		PGPFreeData( kbuf );
	return i;


#endif /* PGP_ENCRYPT_DISABLE */ /* ] */
}


/*
 * Return 1 if (sig,siglen) is a valid MPI which signs
 * hash, of type h.  Check the DER-encoded prefix and the
 * hash itself.
 */
static int
ecVerify(PGPPubKey const *pubkey, PGPByte const *sig,
	PGPSize siglen, PGPHashVTBL const *h, PGPByte const *hash,
	PGPPublicKeyMessageFormat format)
{
#if PGP_VERIFY_DISABLE /* [ */

	(void)pubkey;
	(void)sig;
	(void)siglen;
	(void)h;
	(void)hash;
	(void)format;
	return kPGPError_FeatureNotAvailable;

#else /* PGP_VERIFY_DISABLE */  /* ]  [ */

	ECpub const *pub = (ECpub *)pubkey->priv;
	ecContextRef ec = pub->ec;
	PGPUInt32 coordSize, scalarSize, pointSize;
	BigNum r, s, w, u2, bnorder;
	ecPointRef gu1=NULL, yu2=NULL, ecv=NULL;
	ecScalarRef ecu1=NULL, ecu2=NULL;
	int i;
	PGPSize off;
	PGPMemoryMgrRef	mgr	= PGPPeekContextMemoryMgr( pubkey->context );

	ASSERTECSIG(pubkey->pkAlg);

	ecGetBufferSize( ec, &coordSize, &scalarSize, NULL, &pointSize );

#if 0
	/* Hashsize must be at least as big as size of field for legal sig */
	if (h->hashsize < scalarSize) {
		return 0;
	}
#endif

#if 0
	/* Allow generalizations of SHA, as long as they are big enough */
	if (h->algorithm != kPGPHashAlgorithm_SHA)
		return 0;	/* No match for sure! */
#endif

	bnBegin(&r, mgr, INSECURE );
	bnBegin(&s, mgr, INSECURE );
	bnBegin(&w, mgr, INSECURE );
	bnBegin(&u2, mgr, INSECURE );
	bnBegin(&bnorder, mgr, INSECURE );

	if( ecPointCreate( ec, &gu1 ) < 0
		|| ecPointCreate( ec, &yu2 ) < 0
		|| ecPointCreate( ec, &ecv ) < 0
		|| ecScalarCreate( ec, &ecu1, INSECURE ) < 0
		|| ecScalarCreate( ec, &ecu2, INSECURE ) < 0
		|| sScalartoBN( pub->order, &bnorder, mgr, scalarSize ) < 0 )
		goto nomem;

	/* sig holds two values.  Get first, r, from sig. */
	off = 0;
	if (format == kPGPPublicKeyMessageFormat_X509) {
		/* Parse SEQUENCE header for 509 sig data */
		PGPByte const *sigp = sig + off;
		PGPUInt32 len;
		if (pgpBnX509TagLen(&sigp, &len) != X509_TAG_SEQUENCE) {
			i = kPGPError_MalformedKeyComponent;
			goto done;
		}
		off += sigp - sig;
		if (len != siglen - off) {
			i = kPGPError_MalformedKeyComponent;
			goto done;
		}
	}
	i = pgpBnGetFormatted(&r, sig+off, siglen-off, scalarSize, format);
	if (i <= 0)
		goto fail;
	/* Get 2nd value, s, from SIG */
	off += i;
	i = pgpBnGetFormatted(&s, sig+off, siglen-off, scalarSize, format);
	if (i <= 0)
		goto fail;
	off += i;
	if (off != siglen) {
		i = kPGPError_BadSignatureSize;
		goto done;
	}

	/*
	 * Sanity-check r and s against the group order.  Both should
	 * be less than that.  If not, the signature is clearly bad.
	 */
	if (bnCmp(&r, &bnorder) >= 0 || bnCmp(&s, &bnorder) >= 0) {
		i = 0;	/* FAIL */
		goto done;
	}
	
	/* Reconstruct hash as u2 */
	if (bnInsertBigBytes(&u2, hash, 0, h->hashsize) < 0)
		goto nomem;

	/*
	 * Calculate DSS check function....
	 * Given signature (r,s) and hash H (in bn), compute:
	 * w = s^-1 mod q
	 * u1 = H * w mod q
	 * u2 = r * w mod q
	 * v = X coord of (u1*G + u2*Y)
	 * if v == r the signature checks.
	 *
	 * To save space, we put u1 into s, H into u2, and v into w.
	 */
	if (bnInv(&w, &s, &bnorder) < 0)
		goto nomem;
	if (bnMul(&s, &u2, &w) < 0 || bnMod(&s, &s, &bnorder) < 0)
		goto nomem;
	if (bnMul(&u2, &r, &w) < 0 || bnMod(&u2, &u2, &bnorder) < 0)
		goto nomem;
	if( sBNtoScalar( &s, ecu1, mgr, scalarSize ) < 0 )
		goto nomem;
	if( sBNtoScalar( &u2, ecu2, mgr, scalarSize ) < 0 )
		goto nomem;

	/* Now for the expensive part... */

	if( ecPointMul( pub->g, ecu1, FALSE, gu1 ) < 0
		|| ecPointMul( pub->y, ecu2, FALSE, yu2 ) < 0
		|| ecPointAdd( gu1, yu2, ecv ) < 0 )
		goto nomem;

	if( sPointXtoBN( ecv, &w, mgr, coordSize ) < 0
		|| bnMod( &w, &w, &bnorder ) < 0 )
		goto nomem;

	/* Compare result with r, should be equal */
	i = bnCmp(&w, &r) == 0;

	goto done;

fail:
	if (!i)
		i = kPGPError_BadSignatureSize;
	goto done;
nomem:
	i = kPGPError_OutOfMemory;
	goto done;
done:
	bnEnd(&bnorder);
	bnEnd(&u2);
	bnEnd(&w);
	bnEnd(&s);
	bnEnd(&r);
	if( IsntNull( gu1 ) )
		ecPointFree( gu1 );
	if( IsntNull( yu2 ) )
		ecPointFree( yu2 );
	if( IsntNull( ecv ) )
		ecPointFree( ecv );
	if( IsntNull( ecu1 ) )
		ecScalarFree( ecu1 );
	if( IsntNull( ecu2 ) )
		ecScalarFree( ecu2 );

	return i;

#endif /* PGP_VERIFY_DISABLE */ /* ] */
}


/*
 * Turn a PGPPubKey into the algorithm-specific parts of a public key.
 * A public key's EC-specific part is:
 *
 *  0      2    Curve type (=0)
 *  2      2+s  Curve name (s=strlen(name))
 * 4+s     2+p  Public curve point (p=pointSize)
 * 6+s+p
 */
static PGPSize
ecPubBufferLength(PGPPubKey const *pubkey)
{
	ECpub const *pub = (ECpub *)pubkey->priv;
	PGPUInt32 pointSize;
	PGPUInt32 scalarSize;
	PGPInt32 curve;

	ASSERTEC(pubkey->pkAlg);

	ecGetBufferSize( pub->ec, NULL, &scalarSize, NULL, &pointSize );

	curve = sCurveIndexFromScalarsize( scalarSize );
	pgpAssert( curve >= 0 );
	return 6 + pointSize + strlen( sCurves[curve].name );
}

static void
ecPubToBuffer(PGPPubKey const *pubkey, PGPByte *buf)
{
	ECpub const *pub = (ECpub *)pubkey->priv;
	PGPUInt32 pointSize;
	PGPUInt32 scalarSize;
	PGPInt32 curve;
	PGPSize namelen;
	PGPUInt32 i;
	BigNum bny;
	PGPMemoryMgrRef mgr = PGPPeekContextMemoryMgr( pubkey->context );

	ASSERTEC(pubkey->pkAlg);

	ecGetBufferSize( pub->ec, NULL, &scalarSize, NULL, &pointSize );

	i = 0;
	buf[i++] = 0;
	buf[i++] = 0;

	curve = sCurveIndexFromScalarsize( scalarSize );
	pgpAssert( curve >= 0 );

	namelen = strlen( sCurves[curve].name );
	buf[i++] = ((8*namelen-1) >> 8) & 0xff;
	buf[i++] = ((8*namelen-1) >> 0) & 0xff;
	pgpCopyMemory( sCurves[curve].name, buf+1, namelen );
	i += namelen;

	bnBegin( &bny, mgr, INSECURE );
	(void)sPointtoBN( pub->y, &bny, mgr, pointSize );
	i += pgpBnPutPlain( &bny, buf+i );
	bnEnd( &bny );
}


/* A little helper function that's used twice */
static void
ecFillPubkey(PGPPubKey *pubkey, ECpub *pub)
{
	pubkey->next	 = NULL;
	pubkey->pkAlg	 = kPGPPublicKeyAlgorithm_ECSign;
	pubkey->priv	 = pub;
	pubkey->destroy  = ecPubDestroy;
	pubkey->maxesk   = ecPubMaxesk;
	pubkey->maxdecrypted   = ecPubMaxdecrypted;
	pubkey->maxsig   = ecPubMaxsig;
	pubkey->encrypt  = ecEncrypt;
	pubkey->verify   = ecVerify;
	pubkey->bufferLength  = ecPubBufferLength;
	pubkey->toBuffer = ecPubToBuffer;
	pubkey->pubparams= ecPubParams;
	pubkey->setkeyid= ecPubSetKeyID;
}


/*
 * Turn the algorithm-specific parts of a public key into a PGPPubKey
 * structure.  A public key's EC-specific part is:
 *
 *  0      2    Curve type (=0)
 *  2      2+s  Curve name (s=strlen(name))
 * 4+s     2+p  Public curve point (p=pointSize)
 * 6+s+p
 */
PGPPubKey *
ecPubFromBuf(
	PGPContextRef	context,
	PGPByte const *	buf,
	PGPSize			size,
	PGPError *		error)
{
	PGPPubKey *pubkey;
	ECpub *pub;
	unsigned i, t;
	PGPInt32 curve;
	PGPError	err	= kPGPError_OutOfMemory;
	PGPMemoryMgrRef	mgr	= PGPPeekContextMemoryMgr( context );

	bnInit();

	if (size < 6)
		return NULL;

	if( buf[0] != 0 || buf[1] != 0 )
	{
		*error = kPGPError_MalformedKeyComponent;
		return NULL;
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -