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

📄 pgpkeyobj.c

📁 可以实现对邮件的加密解密以及签名
💻 C
📖 第 1 页 / 共 5 页
字号:

void
pgpSecClearValidated(PGPKeyDBObj *sec)
{
	PGPKeyInfo *kinfo;

	pgpAssert(OBJISKEY(sec));
	pgpAssert(pgpKeyIsSec(sec));
	kinfo = pgpKeyToKeyInfo( sec );
	KEYCLEARVALIDATED( kinfo );
}

	PGPBoolean
pgpSecIsValidated(PGPKeyDBObj *sec)
{
	PGPKeyInfo *kinfo;

	pgpAssert(OBJISKEY(sec));
	pgpAssert(pgpKeyIsSec(sec));
	kinfo = pgpKeyToKeyInfo( sec );
	return KEYISVALIDATED( kinfo );
}

/* 
 * Return true if the specified signature has been revoked, that is,
 * if there is a newer signature by the same key which is of type
 * UID_REVOKE, or if it has been revoked by CRL.
 */
	PGPBoolean
pgpSigRevoked (PGPKeyDBObj *sig)
{
	PGPKeyDBObj		*parent,
					*sibling;
	PGPSigInfo *sinfo;
	PGPSigInfo *sibinfo;

	pgpAssert (OBJISSIG(sig));
	sinfo = pgpSigToSigInfo( sig );

	/* Sigs can be declared irrevocable at creation time */
	if (!SIGISREVOCABLE(sinfo))
		return FALSE;

	/* Check revoked flag */
	if (sinfo->trust & PGP_SIGTRUSTF_REVOKEDBYCRL)
		return TRUE;

	parent = sig->up;
	for (sibling = parent->down; sibling ; sibling = sibling->next) {
		if( !pgpKeyDBObjIsReal(sibling) )
			continue;
		if (!OBJISSIG(sibling) || sibling == sig)
			continue;
		sibinfo = pgpSigToSigInfo( sibling );
		if (sibinfo->by == sinfo->by) {
			if (sibinfo->trust & PGP_SIGTRUSTF_CHECKED) {
				if (sibinfo->tstamp > sinfo->tstamp) {
					if (sibinfo->type == PGP_SIGTYPE_KEY_UID_REVOKE) {
						/* Valid revocation */
						return TRUE;
					}
				}
			}
		}
	}
	return FALSE;
}


	PGPUInt16
pgpKeyConfidence(PGPKeyDBObj *key)
{
	pgpAssert(OBJISKEY(key));

	/*  pgpKeyCalcTrust handles revoked/expired keys */
	return pgpKeyCalcTrust (key);
}

void
pgpKeyID8(
	PGPKeyDBObj const *key,
	PGPByte *pkalg,
	PGPKeyID *keyID)
{
	PGPKeyInfo *kinfo;
	PGPByte keypkalg;

	pgpAssert(OBJISKEY(key));
	kinfo = pgpKeyToKeyInfo( key );
	keypkalg = kinfo->pkalg;
	if ((keypkalg | 1) == 3)		/* ViaCrypt */
		keypkalg = 1;
	if (pkalg)
		*pkalg = keypkalg;
	if (keyID)
	{
		pgpNewKeyIDFromRawData( kinfo->keyID, keypkalg, 8, keyID );
	}
}

void
pgpKeyID4(
	PGPKeyDBObj const *key,
	PGPByte *pkalg,
	PGPKeyID *keyID)
{
	PGPKeyInfo *kinfo;
	PGPByte keypkalg;

	pgpAssert(OBJISKEY(key));
	kinfo = pgpKeyToKeyInfo( key );
	keypkalg = kinfo->pkalg;
	if ((keypkalg | 1) == 3)		/* ViaCrypt */
		keypkalg = 1;
	if (pkalg)
		*pkalg = keypkalg;
	if (keyID)
	{
		pgpNewKeyIDFromRawData( &kinfo->keyID[4], keypkalg, 4, keyID );
	}
}

	PGPBoolean
pgpKeyV3(PGPKeyDBObj const *key)
{
	PGPKeyInfo *kinfo;
	pgpAssert(OBJISKEY(key));
	kinfo = pgpKeyToKeyInfo( key );
	return KEYISV3(kinfo) != 0;
}

	PGPError
pgpKeyFingerprint16(PGPKeyDBObj *key,
	PGPByte *buf)
{
	PGPByte const *p;
	PGPContextRef context;
	PGPSize len;

	pgpAssert(OBJISKEY(key));
	context = PGPPeekKeyDBContext(PGPPeekKeyDBObjKeyDB( key ) );

	p = (PGPByte const *)pgpFetchObject(key, &len);
	if (!p)
		return kPGPError_OutOfMemory;
	return pgpKeyParseFingerprint16(context, p, len, buf);
}

	PGPError
pgpKeyFingerprint20(PGPKeyDBObj *key,
	PGPByte *buf)
{
	PGPContextRef context;
	PGPSize objlen;
	PGPSize hlen;
	PGPByte const *objbuf;
	PGPBoolean mustFree = FALSE;
	PGPError err;

	pgpAssert(OBJISKEY(key));
	context = PGPPeekKeyDBContext(PGPPeekKeyDBObjKeyDB( key ) );

	if( pgpKeyIsSec( key ) )
	{
		objbuf = pgpKeyDBObjToPubData( key, &objlen );
		mustFree = TRUE;
	} else {
		objbuf = (PGPByte const *)pgpFetchObject(key, &objlen);
	}
	hlen = pgpPktBufferHeaderLen( objbuf );
	err = pgpFingerprint20HashBuf(context, objbuf+hlen, objlen-hlen, buf);
	if( mustFree )
		PGPFreeData( (PGPByte *)objbuf );
	return err;
}

/* This does a 20 byte fingerprint based solely on the numeric material */
	PGPError
pgpKeyFingerprint20n(PGPKeyDBObj *key,
	PGPByte *buf)
{
	PGPContextRef context;
	PGPSize objlen;
	PGPSize numlen;
	PGPByte const *objbuf, *numbuf;
	PGPBoolean mustfree = FALSE;
	PGPError err;

	pgpAssert(OBJISKEY(key));
	context = PGPPeekKeyDBContext(PGPPeekKeyDBObjKeyDB( key ) );

	if( pgpKeyIsSec (key) ) {
		objbuf = pgpKeyDBObjToPubData( key, &objlen );
		mustfree = TRUE;
	} else {
		objbuf = (PGPByte const *)pgpFetchObject(key, &objlen);
	}
	numbuf = pgpKeyParseNumericData(objbuf, objlen, &numlen);
	err = pgpFingerprint20HashBuf(context, numbuf, numlen, buf);
	if( mustfree )
		PGPFreeData( (PGPByte *)objbuf );
	return err;
}

/* Return TRUE if the key is a secret key */
	PGPBoolean
pgpKeyIsSec(PGPKeyDBObj *key)
{
	PGPKeyInfo *kinfo;

	pgpAssert(OBJISKEY(key));
	kinfo = pgpKeyToKeyInfo( key );
	return KEYISSEC(kinfo)  ||  KEYISTOKEN(kinfo);
}


/*
 * Return the most recent subkey associated with the key, if there is one.
 * The subkey must be in the specified keyset.
 */
	PGPKeyDBObj *
pgpKeySubkey(PGPKeyDBObj const *key, PGPKeySet *set)
{
	PGPKeyDBObj *obj, *best = NULL;
	PGPUInt32 objtime, besttime = 0;

	pgpAssert(OBJISKEY(key));
	for (obj = key->down; IsntNull(obj); obj = obj->next) {
		if( !pgpKeyDBObjIsReal(obj) )
			continue;
		if( !OBJISSUBKEY(obj) )
			continue;
		if( IsntNull(set) && !pgpKeySetIsMember(obj, set ) )
			continue;
		if (pgpSubkeyValid(obj, TRUE, FALSE)) {
			objtime = pgpKeyCreation(obj);
			if (besttime <= objtime) {
				best = obj;
				besttime = objtime;
			}
		}
	}
	return best;
}

/* Given a subkey, return its master key */
	PGPKeyDBObj *
pgpKeyMasterkey (PGPKeyDBObj const *subkey)
{
	pgpAssert (OBJISSUBKEY(subkey));
	pgpAssert (OBJISTOPKEY(subkey->up));
	return subkey->up;
}

/* Return MPI data of key */
	PGPByte const *
pgpKeyMPIData( PGPKeyDBObj const *key, PGPSize *plen )
{
	PGPSize len;
	PGPSize hlen;
	PGPSize offset;
	PGPByte const *buf;

	pgpAssert (OBJISKEY(key));
	pgpAssert( IsntNull( plen ) );
	*plen = 0;

	buf = pgpFetchObject( key, &len );
	if( IsNull( buf ) )
		return buf;
	hlen = pgpPktBufferHeaderLen( buf );
	buf += hlen;
	len -= hlen;
	/* V4 keys are two bytes shorter than V3 */
	offset = 6;
	if (buf[0] <= PGPVERSION_3)
		offset += 2;
	len -= offset;

	*plen = len;
	return buf + offset;
}
	

/*
 * Given a public key on the keyring, get the corresponding PGPPubKey.
 * Use is a usage code which limits the kinds of keys we will accept.
 * For keys which have subkeys this chooses which one to use.  If use is
 * 0 we do a straight conversion of the key or subkey; if nonzero we
 * verify that the key has the required use.  Return NULL if we can't
 * get a key with the required use.
 */
	PGPPubKey *
pgpKeyPubKey(PGPKeyDBObj *key, int use)
{
	PGPKeyInfo *kinfo;
	PGPByte const *p;
	PGPSize len;
	PGPSize hlen;
	PGPPubKey *pub;
	PGPKeyDBObj *subkey = NULL;
	unsigned vsize;
	PGPError i;
	PGPContextRef	context;

	context = PGPPeekKeyDBContext(PGPPeekKeyDBObjKeyDB( key ) );

	pgpAssert(OBJISKEY(key));
	kinfo = pgpKeyToKeyInfo( key );

	/* Select between subkey and key if necessary */
	if (use &&  (OBJISSUBKEY(key)
			|| ((subkey=pgpKeySubkey(key, NULL)) != NULL))) {
		if (use == PGP_PKUSE_SIGN_ENCRYPT) {
			pgpKeyDBSetError(PGPPeekKeyDBObjKeyDB(key),
							 kPGPError_PublicKeyUnimplemented);
			return NULL;
		}
		if (use == PGP_PKUSE_ENCRYPT) {
			/* Always encrypt to subkey if there is one */
			/* Eventually need to make this skip signature subkeys */
			if (OBJISTOPKEY(key)) {
				pgpAssert(subkey);
				key = subkey;
				pgpAssert (OBJISSUBKEY(key));
				kinfo = pgpKeyToKeyInfo( key );
			}
		} else if (use == PGP_PKUSE_SIGN) {
			/* Allow verification with subkey if explicit, else go up */
			if (use && ((pgpKeyAlgUse(pgpPkalgByNumber(kinfo->pkalg)) & use) !=
							(unsigned)use)){
				if (OBJISSUBKEY(key)) {
					key = key->up;
					pgpAssert (OBJISTOPKEY(key));
					kinfo = pgpKeyToKeyInfo( key );
				}
			}
		}
	}

	/* Verify key satisfies required usage */
	if (use && ((pgpKeyAlgUse(pgpPkalgByNumber(kinfo->pkalg)) & use) !=
			 		(unsigned)use)){
		pgpKeyDBSetError(PGPPeekKeyDBObjKeyDB(key),
						 kPGPError_PublicKeyUnimplemented);
		return NULL;
	}

	p = (PGPByte const *)pgpFetchObject(key, &len);
	if (!p)
		return NULL;
	hlen = pgpPktBufferHeaderLen( p );
	p += hlen;
	len -= hlen;

	/*
	 * A key starts with 5 or 7 bytes of data, an algorithm byte, and
	 * the public components.
	 */
	if (p[0] == PGPVERSION_4) {
		vsize = 0;
	} else {
		vsize = 2;
	}
	pgpAssert(p[5+vsize] == kinfo->pkalg);	/* Checked by pgpKeyVerify */
	pub = pgpPubKeyFromBuf( context, p[5+vsize], p+6+vsize, len-6-vsize, &i);
	if (!pub) {
		pgpKeyDBSetError(PGPPeekKeyDBObjKeyDB(key), i);
		return NULL;
	}
	memcpy(pub->keyID, kinfo->keyID, sizeof(kinfo->keyID));
	pub->keyDBObj = key;
	return pub;
}

/*
 * Return the version for a key.
 */
PgpVersion
pgpKeyVersion (PGPKeyDBObj *key)
{
	PGPByte *kdata;
	PGPSize kdatalen;
	PGPSize hlen;

	pgpAssert(OBJISKEY( key ) );

	kdata = (PGPByte *)pgpFetchObject (key, &kdatalen);
	pgpAssert( IsntNull( kdata ) );
	hlen = pgpPktBufferHeaderLen( kdata );
	kdata += hlen;
	kdatalen -= hlen;
	return (PgpVersion)kdata[0];
}


/*
 * Given a secret on a keyring, get a PGPSecKey (possibly locked).
 * As a hack to help the lazy programmer, you can also pass a key.
 * Use is a usage code which limits the kinds of keys we will accept.
 * For keys which have subkeys this chooses which one to use.
 */
	PGPSecKey *
pgpSecSecKey(PGPKeyDBObj *sec, int use)
{
	PGPKeyInfo *kinfo;
	PGPByte const *p;
	PGPSize len;
	PGPSize hlen;
	PGPSecKey *seckey;
	PGPKeyDBObj *subkey = NULL;
	unsigned vsize;
	PGPError i;
	PGPContextRef	context;
	PGPToken *tok = NULL;

	context = PGPPeekKeyDBContext(PGPPeekKeyDBObjKeyDB( sec ) );

	pgpAssert(OBJISKEY(sec));
	pgpAssert(pgpKeyIsSec(sec));
	kinfo = pgpKeyToKeyInfo( sec );

	/* Select between subkey and sec if necessary */
	if (use	 &&  (OBJISSUBKEY(sec)
			|| ((subkey=pgpKeySubkey(sec, NULL)) != NULL))) {
		if (use == PGP_PKUSE_SIGN_ENCRYPT) {
			pgpKeyDBSetError(PGPPeekKeyDBObjKeyDB(sec),
							 kPGPError_PublicKeyUnimplemented);
			return NULL;
		}
		/* For decrypt/sign, we will use the specified key if legal */
		/* This will allow us to decrypt with top level RSA key */
		/* Could also sign with subkeys eventually */
		if (use && ((pgpKeyAlgUse(pgpPkalgByNumber(kinfo->pkalg)) & use) !=
								(unsigned)use)){
			if (use == PGP_PKUSE_ENCRYPT) {
				if (OBJISTOPKEY(sec)) {
					pgpAssert(subkey);
					sec = subkey;
					pgpAssert (OBJISSUBKEY(sec));
					kinfo = pgpKeyToKeyInfo( sec );
				}
			} else if (use == PGP_PKUSE_SIGN) {
				if (OBJISSUBKEY(sec)) {
					sec = sec->up;
					pgpAssert (OBJISTOPKEY(sec));
					kinfo = pgpKeyToKeyInfo( sec );
				}
			}
		}
	}


	/* Verify sec satisfies required usage */
	if (use && ((pgpKeyAlgUse(pgpPkalgByNumber(kinfo->pkalg)) & use) !=
									(unsigned)use)){
		pgpKeyDBSetError(PGPPeekKeyDBObjKeyDB(sec),
						 kPGPError_PublicKeyUnimplemented);
		return NULL;
	}


	/* See if key is on a hardware token */
	if( !KEYISSEC(kinfo) && KEYISTOKEN(kinfo) )
		tok = pgpTokenFromKeyID( kinfo->keyID );

	p = (PGPByte const *)pgpFetchObject(sec, &len);
	if (!p)
		return NULL;
	hlen = pgpPktBufferHeaderLen( p );
	p += hlen;
	len -= hlen;

	if (p[0] == PGPVERSION_4) {
		vsize = 0;
	} else {
		vsize = 2;
	}
	pgpAssert(p[5+vsize] == kinfo->pkalg);
	seckey = pgpSecKeyFromBuf( context, p[5+vsize], p+6+vsize, len-6-vsize,
							   (PGPBoolean)!!KEYISV3(kinfo), tok, &i);
	if (!seckey) {
		pgpKeyDBSetError(PGPPeekKeyDBObjKeyDB(sec), i);
		return NULL;
	}
	memcpy(seckey->keyID, kinfo->keyID, sizeof(kinfo->keyID));
	seckey->keyDBObj = sec;
	return seckey;
}


/* Return the latest valid sig on the object by the specified key */
	PGPKeyDBObj *
pgpLatestSigByKey (PGPKeyDBObj const *obj, PGPKeyDBObj const *key)
{
	PGPKeyDBObj *sig;
	PGPKeyDBObj *latestsig;

	pgpAssert (!OBJISSIG(obj));

	latestsig = NULL;
	for (sig=obj->down; IsntNull(sig); sig=sig->next) {
		if( !pgpKeyDBObjIsReal(sig) )
			continue;
		if (!OBJISSIG(sig))
			continue;
		if (pgpSigMaker (sig) != key)
			continue;
		if ((pgpSigType (sig) & 0xf0) != PGP_SIGTYPE_KEY_GENERIC)
			continue;
		if (!pgpSigChecked (sig) || pgpSigRevoked (sig))
			continue;
		/* Save the newest such signature on the name */
		if (!latestsig) {
			latestsig = sig;
		} else {
			if (pgpSigTimestamp(sig) > pgpSigTimestamp(latestsig))
				latestsig = sig;
		}
	}		
	return latestsig;
}

/* True if there is a newer sig of the same type by the same key */
	PGPBoolean
pgpSigIsSuperceded( PGPKeyDBObj const *sig )
{
	PGPKeyDBObj *obj;
	PGPKeyDBObj *signer;
	PGPUInt32 type;
	PGPSigInfo *sinfo;

	pgpAssert( OBJISSIG(sig) );

	sinfo = pgpSigToSigInfo( sig );
	if( !SIGISREVOCABLE(sinfo) )
		return FALSE;

	signer = pgpSigMaker( sig );
	type = pgpSigType( sig ) & 0xf0;

⌨️ 快捷键说明

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