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

📄 pgpdecode.c

📁 可以实现对邮件的加密解密以及签名
💻 C
📖 第 1 页 / 共 5 页
字号:
	if( !s->fUsedDetachedSigOp && IsOp( op )  && IsntNull( op.subOptions ) ) {
		/* Only use the detachedsig op once, after that we will ask user */
		s->fUsedDetachedSigOp = TRUE;
		setupOp = op.subOptions;
	} else {
		/* Ask user for detached signature input */

		if( IsNull( s->func ) ) {
			err = kPGPError_DetachedSignatureFound;
			goto error;
		}

		if( IsPGPError (err = pgpEventDetachedSignature( s->context,
								&s->newOptionList, s->func, s->userValue ) ) )
			goto error;
		if( IsPGPError( err = pgpSearchOptionSingle( s->newOptionList,
								kPGPOptionType_DetachedSignature, &op ) ) )
			goto error;
		if( IsOp( op )  && IsntNull( op.subOptions ) ) {
			setupOp = op.subOptions;
		} else {
			err = kPGPError_DetachedSignatureFound;
			goto error;
		}
		freshOpList = s->newOptionList;
	}

	/* Set up input file or buffer */
	err = pgpSetupInput( s->context, setupOp, NULL, NULL, TRUE, TRUE,
						 &detFileRef, &pfrdet, &inFileDataType, &bLargeFile,
						 &detBufPtr,
						 &detBufLength );
	if( IsPGPError( err ) )
		goto error;
	
	/* Now pump the sig-check data through the pipes */
	if( detFileRef ) {
		/* File input */
		pgpFileReadSetCallBack( pfrdet, decodeLocalCallBack, s );
		err = pgpFileReadPump( pfrdet, head );
		pgpFileReadDestroy( pfrdet );
		if( IsPGPError( err ) )
			goto error;
	} else {
		/* Buffer input */
		if( IsPGPError( err = pgpPumpMem( head, detBufPtr,
						detBufLength, NULL, NULL ) ) )
			goto error;
	}
	err = kPGPError_NoErr;
	/* Fall through */
error:
	/* Discard after one usage */
	if( PGPOptionListRefIsValid( freshOpList ) ) {
		pgpFreeOptionList( freshOpList );
	}
	
	s->newOptionList = kInvalidPGPOptionListRef;
	
	return err;
}


/*
 * Given the signature structure, sig, verify it against the hash
 * to see if this signature is valid.  This requires looking up the
 * public key in the keyring and validating the key.
 *
 * Returns 0 on success or an error code.
 */
	static PGPError
pgpDecodeVerifySig(
	void				*arg,
	PGPSigData const	*sig,
	PGPByte const		*hash
	)
{
#if PGP_VERIFY_DISABLE /* [ */

	(void)arg;
	(void)sig;
	(void)hash;
	return kPGPError_FeatureNotAvailable;

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

	PGPDecodeJob		*s;				/* Parameters for callbacks */
	PGPKeyDBObjRef		 signKey;		/* Signing key as PGPKeyDBObj */
	PGPKeyDBRef			 alternateKeyDB; /* Extra keydb to try lookup */
	PGPKeyID			keyid;			/* KeyID from signature */
	PGPTime				 timeStamp;		/* Issuance time of sig */
	PGPUInt32			 timeValidityPeriod; /* signature validity period in seconds */
	PGPValidity			 failValidity,	/* Fail on keys less valid */
						 warnValidity;	/* Warn on keys less valid */
	PGPBoolean			 fRevoked=FALSE,/* Status of signing key */
						 fExpired=FALSE,
						 fDisabled=FALSE,
						 fValidityThreshold=TRUE;
	PGPValidity			 keyValidity=kPGPValidity_Unknown;
	PGPError			 err;			/* Error code */
	
	s = (PGPDecodeJob *) arg;
	alternateKeyDB = NULL;

	if( IsNull( s->func ) ) {
		/* If can't report results, don't bother to do anything */
		err = kPGPError_NoErr;
		goto error;
	}

	/* Get info about sig */
	pgpGetSigDataKeyID ( sig, &keyid );
	
	/* Get time stamp / expiration  */
	pgpSigDataTime (sig, &timeStamp, &timeValidityPeriod);

retrykeydb:

	if( IsNull( s->keyDB ) ) {
		err = kPGPError_MissingKeyDB;
	} else {
		err = PGPFindKeyByKeyID ( s->keyDB, &keyid, &signKey);
	}
	if( IsPGPError( err ) && IsntNull( alternateKeyDB ) ) {
		err = PGPFindKeyByKeyID ( alternateKeyDB, &keyid, &signKey);
	}

	/* Check for sig by subkeys - OK as long as it's a valid subkey */
	if( IsntPGPError( err ) && pgpKeyIsSubkey( signKey ) )
	{
		if( !pgpSubkeyValid( signKey, FALSE, FALSE ) )
		{
			err = kPGPError_MissingKeyDB;  // Actual error code is ignored
			signKey = NULL;
		}
	}

	if( IsPGPError( err ) ) {
		/* Don't have signing key; notify him */
		err = pgpEventSignature( s->context, &s->newOptionList,
							  s->func, s->userValue, &keyid, NULL,
							  FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
							  keyValidity, timeStamp, timeValidityPeriod );
		if( IsntNull( alternateKeyDB ) )
			PGPFreeKeyDB (alternateKeyDB);
		pgpSetupKeyDB (s->newOptionList, &alternateKeyDB);
		if( IsntNull( alternateKeyDB ) ) {
			PGPIncKeyDBRefCount( alternateKeyDB );
			pgpCleanupOptionList( &s->newOptionList );
			goto retrykeydb;
		}
		pgpCleanupOptionList( &s->newOptionList );
		goto error;
	}

	/* Determine validity of signing key */
	if( IsPGPError( err = pgpGetMinValidity( s->optionList,
					&failValidity, &warnValidity ) ) )
		goto error;
	err = pgpCheckKeyValidity( s->context, s->optionList,
					signKey, failValidity, warnValidity, NULL,
					&keyValidity );

	if( err == kPGPError_KeyInvalid ) {
		fValidityThreshold = FALSE;
	} else if( err == kPGPError_KeyRevoked ||
			   err == kPGPError_KeyExpired ||
			   err == kPGPError_KeyDisabled ) {
		fValidityThreshold = FALSE;
		if( IsPGPError( err = pgpGetKeyBoolean( signKey,
												kPGPKeyProperty_IsRevoked,
												&fRevoked ) ) )
			goto error;
		if( IsPGPError( err = pgpGetKeyBoolean( signKey,
												kPGPKeyProperty_IsDisabled,
												&fDisabled ) ) )
			goto error;
		if( IsPGPError( err = pgpGetKeyBoolean( signKey,
												kPGPKeyProperty_IsExpired,
												&fExpired ) ) )
			goto error;
	} else if( err != kPGPError_NoErr ) {
		goto error;
	}

	/* Check signature, returns 1 if OK */
	err = pgpSigDataCheck (sig, signKey, hash);
	if( err != 1 ) {
		if( err == kPGPError_KeyUnusableForSignature )
		{
			/* Can't verify for some reason... notify him */
			err = pgpEventSignature( s->context, &s->newOptionList,
								  s->func, s->userValue, &keyid, signKey,
								  FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
								  keyValidity, timeStamp, timeValidityPeriod );
			if( IsntNull( alternateKeyDB ) )
				PGPFreeKeyDB (alternateKeyDB);
			pgpSetupKeyDB (s->newOptionList, &alternateKeyDB);
			if( IsntNull( alternateKeyDB ) ) {
				PGPIncKeyDBRefCount( alternateKeyDB );
				pgpCleanupOptionList( &s->newOptionList );
				goto retrykeydb;
			}
			pgpCleanupOptionList( &s->newOptionList );
			goto error;
		}
		if( IsPGPError( err ) )
			goto error;
		/* Notify of bad signature and exit */
		err = pgpEventSignature( s->context, &s->newOptionList,
							  s->func, s->userValue, &keyid, signKey,
							  TRUE, FALSE, fDisabled, fRevoked, fExpired,
							  fValidityThreshold, keyValidity, timeStamp, 
							  timeValidityPeriod );
		pgpCleanupOptionList( &s->newOptionList );
		goto error;
	}
		
	/* Good signature, tell him! */
	err = pgpEventSignature( s->context, &s->newOptionList,
						  s->func, s->userValue, &keyid, signKey,
						  TRUE, TRUE, fDisabled, fRevoked, fExpired,
						  fValidityThreshold, keyValidity, timeStamp, 
						  timeValidityPeriod );
	pgpCleanupOptionList( &s->newOptionList );

	/* Fall through */
error:
	if ( IsntNull( alternateKeyDB ) )
		PGPFreeKeyDB( alternateKeyDB );
	return err;

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


/*
 * given a list of Encrypted Session Keys (esklist), try to decrypt
 * them to get the session key.  Fills in keylen with the length of
 * the session key buffer.
 *
 * Returns 0 on success or PGPANN_PARSER_EATIT on failure.
 */
	static PGPError
pgpDecodeDecryptESK(
	void				*arg,
	PGPESK const		*esklist,
	int				   (*tryKey)(void *arg, PGPByte const *key, PGPSize keylen),
	void				*tryarg
	)
{
#if PGP_DECRYPT_DISABLE /* [ */

	(void) arg;
	(void) esklist;
	(void) tryKey;
	(void) tryarg;
	return kPGPError_FeatureNotAvailable;

#else /* PGP_DECRYPT_DISABLE */  /* ]  [ */

	PGPDecodeJob		*s;				/* Parameters for callbacks */
	PGPESK const		*esk;			/* ESK being tested */
	PGPKeyDBObjRef		 decKey;		/* PGPKeyDBObj for decryption key */
	PGPKeySet			*decKeySet;		/* Keyset with all decryption keys */
	PGPBoolean			 success;		/* True if had a successful decrypt */
	PGPError			 err;			/* Error from pgplib */
	PGPUInt32			 passPhraseCount; /* Count of possible pphrases */
	PGPUInt32			 keyIDCount;	/* # deckeys unavail */
	PGPKeyID			*keyIDArray;	/* Array of ptrs to keyids */
	PGPCipherAlgorithm	 cipheralg;		/* Decryption algorithm */
	PGPBoolean			 firstpass;		/* of passphrase checking */
	PGPByte				*key;			/* Buffer holding decrypted key */
	PGPSize				 keylen;		/* Size of key buffer */

	s = (PGPDecodeJob *) arg;
	decKeySet = NULL;
	keyIDArray = NULL;
	key = NULL;
	
	/* First loop over all ESK's to set up recipient list */
	passPhraseCount = 0;
	keyIDCount = 0;
	if( IsntNull( s->keyDB ) ) {
		if( IsPGPError( err = PGPNewEmptyKeySet( s->keyDB, &decKeySet ) ) )
			goto error;
	}
	for( esk = esklist; IsntNull( esk ); esk = pgpEskNext( esk ) ) {
		switch( pgpEskType( esk ) ) {
		case PGP_ESKTYPE_PASSPHRASE:
			passPhraseCount += 1;
			break;
		case PGP_ESKTYPE_PUBKEY:
		{
			PGPKeyID			keyid;			/* Key ID from ESK */
			void *				vKeyIDArray;
	
			err	= pgpGetEskKeyID( esk, &keyid);
			if ( IsPGPError( err ) )
				goto error;

			/* Save keyids in list */
			vKeyIDArray = keyIDArray;
			err = pgpContextMemRealloc( s->context,
				   &vKeyIDArray,
				   (keyIDCount+1) * sizeof(keyIDArray[ 0 ]), 0 );
			if( IsPGPError( err ) )
				goto error;
			keyIDArray = (PGPKeyID *)vKeyIDArray;
			keyIDArray[keyIDCount++] = keyid;
				
			decKey = NULL;
			if( IsntNull( s->keyDB ) ) {
				(void)pgpGetKeyByKeyID ( s->keyDB, &keyid, FALSE, FALSE,
										 &decKey);
			}

			if( IsNull( decKey ) ) {
				/* We don't have the decryption key */
			} else {
				/* Accumulate into recipient key set */
				if( IsPGPError( err = PGPAddKey(decKey, decKeySet ) ) )
					goto error;
			}
			break;
		}
		
		default:
			pgpAssert(0);
			break;
		}
	}

	/* Notify user about decryption keys */
	if( IsPGPError( err = pgpEventRecipients( s->context, &s->newOptionList,
						  s->func, s->userValue, decKeySet, keyIDArray,
						  passPhraseCount, keyIDCount ) ) )
		goto error;
	pgpCleanupOptionList( &s->newOptionList );
	if( IsntNull( decKeySet ) ) {
		PGPFreeKeySet( decKeySet );
		decKeySet = NULL;
	}

	/* Loop over all ESK's trying to find one we can decrypt */
	/* decKeySet will hold decryption keys that we have secrets for */
	success = FALSE;
	if( IsntNull( s->keyDB ) ) {
		if( IsPGPError( err = PGPNewEmptyKeySet( s->keyDB, &decKeySet ) ) )
			goto error;
	}

	firstpass = TRUE;
	while( !success ) {
		for( esk = esklist; IsntNull( esk ) && !success;
			 								esk = pgpEskNext( esk ) ) {
			switch( pgpEskType( esk ) ) {
			case PGP_ESKTYPE_PASSPHRASE:
				/* Try the pass phrase */
				keylen = pgpEskMaxKeySize( esk );
				key = pgpContextMemAlloc( s->context, keylen, 0 );
				if( IsNull( key ) )
				{
					err = kPGPError_OutOfMemory;
					goto error;
				}
				if (s->passPhraseIsSessionKey) {
					keylen = pgpMin( keylen, s->passLength );
					pgpCopyMemory( s->passPhrase, key, keylen );
				} else {
					err = pgpEskConvDecrypt (esk, s->env,
								(char *)s->passPhrase, s->passLength, key);
					if( err < 0 ) {
						err = keylen;
						goto error;
					}
					keylen = err;
				}

				/* Returns 0 on success, nonzero on failure */
				if( tryKey (tryarg, key, keylen) == 0 ) {
					/* Success */
					success = 1;
					/* Report it worked OK */
					cipheralg = (PGPCipherAlgorithm)key[0];
					if( IsPGPError( err = pgpEventDecryption( s->context,
										  &s->newOptionList, s->func,
										  s->userValue, cipheralg,
										  key, keylen) ) )
						goto error;
					pgpCleanupOptionList( &s->newOptionList );
				}
				break;

			case PGP_ESKTYPE_PUBKEY:
			{
				PGPKeyID			keyid;		/* Key ID from ESK */
				PGPBoolean			bOnToken;
			
				if (s->passPhraseIsSessionKey) {
					keylen = s->passLength;
					key = pgpContextMemAlloc( s->context, keylen, 0 );
					if( IsNull( key ) )
					{
						err = kPGPError_OutOfMemory;
						goto error;
					}
					pgpCopyMemory( s->passPhrase, key, keylen );
				} else {
					/* Look up key from ESK */
					err = pgpGetEskKeyID( esk, &keyid );
					if ( IsPGPError( err ) )
						goto error;

					/*
					 * If don't have key, go on to next one.
					 */
					decKey = NULL;
					if( IsntNull( s->keyDB ) ) {
						(void)pgpGetKeyByKeyID( s->keyDB, &keyid, FALSE,
												FALSE, &decKey);
					}

					if( IsNull( decKey ) )
						break;

					if( !pgpKeyIsSec( decKey ) )
						break;

					bOnToken = pgpKeyIsOnToken( decKey );

⌨️ 快捷键说明

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