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

📄 pgpkeyadd.c

📁 可以实现对邮件的加密解密以及签名
💻 C
📖 第 1 页 / 共 5 页
字号:
 * set of keydb objects.  Then self-sign the pubkey.  Return the
 * key object.
 */
	PGPKeyDBObj *
pgpCreateKeypair (PGPEnv const *env, PGPKeyDB *db, PGPSecKey *seckey,
		   PGPKeySpec *keyspec, char const *name, size_t namelen,
		   PGPKeySet const *adkset, PGPByte adkclass,
		   PGPKeySet const *rakset, PGPByte rakclass,
		   PGPByte const *passphrase, PGPSize pplen, PGPBoolean hashedPhrase,
		   PGPError *error)
{
	PGPKeyDBObj *keyobj=NULL, *nameobj;
	PGPKeyDBObj *tmpkey;
	PGPKeyInfo *kinfo;
	PGPSigSpec *sigspec = NULL;
	PGPKeyIter *rakIter = NULL;
	PGPKeyIter *adkIter = NULL;
	PGPByte const *prefAlg;
	PGPSize prefAlgLength;
	PGPByte const *prefKeyServ;
	PGPSize prefKeyServLength;
	PGPUInt32 keyFlags, keyServPrefs;
	PGPBoolean fKeyFlags, fKeyServPrefs;
	PGPUInt16 validity;
	PGPUInt32 nkeys;
	PGPError err;
	PGPUInt32 i;
	PGPBoolean keyv4;
	PGPBoolean secret = TRUE;
	PGPPubKey *pubkey = NULL;
	PGPByte pkalg;

	pgpAssert( error );
	*error = kPGPError_NoErr;

#define CHECKRETVAL(val, err) if (val) { *error = err; goto cleanup; }

	/* SECRET KEY stuff */

	keyv4 = pgpKeySpecVersion (keyspec) > PGPVERSION_3;
	pkalg = seckey->pkAlg;
	if( pgpSecKeyOnToken(seckey) )
	{
		secret = FALSE;
		pubkey = pgpSecKeyPubkey(seckey);
	}
	keyobj = pgpCreateKey (db, NULL, secret, pubkey, (secret?seckey:NULL),
						   keyspec, pkalg);
	CHECKRETVAL (!keyobj, kPGPError_OutOfMemory);
	pgpAssert(OBJISKEY(keyobj));
	kinfo = pgpKeyToKeyInfo( keyobj );
	pgpSecKeySetKeyID( seckey, kinfo->keyID );
	if( !secret )
	{
		pgpPubKeySetKeyID( pubkey, kinfo->keyID );
		pgpKeyOnToken( keyobj, NULL );
	}

	nameobj = pgpCreateUserID (db, keyobj, (PGPByte *) name, namelen);
	CHECKRETVAL (!nameobj, kPGPError_OutOfMemory);

	/* Self-Sign the new pubkey */
	if (pgpKeyAlgUse(pgpPkalgByNumber(pkalg)) & PGP_PKUSE_SIGN)
	{
		sigspec = pgpSigSpecCreate (env, keyobj, PGP_SIGTYPE_KEY_GENERIC);
		CHECKRETVAL (!sigspec, kPGPError_OutOfMemory);
		pgpSigSpecSetPassphrase( sigspec, passphrase, pplen, hashedPhrase );
		if (keyv4)
		{
			/* New keys self-sign with special info! */
			static PGPByte defaultPrefAlg[] = {kPGPCipherAlgorithm_CAST5,
											   kPGPCipherAlgorithm_IDEA,
											   kPGPCipherAlgorithm_3DES};
			PGPByte flagbuf[4];

			prefAlg = pgpKeySpecPrefAlgs (keyspec, &prefAlgLength);
			if( IsntNull( prefAlg ) )
			{
				pgpSigSpecSetPrefAlgs (sigspec, 0, prefAlg, prefAlgLength);
			} else {
				pgpSigSpecSetPrefAlgs (sigspec, 0, defaultPrefAlg,
									   sizeof(defaultPrefAlg));
			}
			prefKeyServ = pgpKeySpecPrefKeyserv (keyspec, &prefKeyServLength);
			if( IsntNull( prefKeyServ ) )
			{
				pgpSigSpecSetPrefKeyServ (sigspec, 0, prefKeyServ,
										  prefKeyServLength);
			}
			keyFlags = pgpKeySpecKeyflags (keyspec, &fKeyFlags);
			if( fKeyFlags )
			{
				for( i=0; i<sizeof(flagbuf); ++i )
					flagbuf[i] = (PGPByte)(keyFlags >> (i*8));
				pgpSigSpecSetKeyFlags( sigspec, 0, flagbuf, sizeof(flagbuf) );
			}
			keyServPrefs = pgpKeySpecKeyservPrefs (keyspec, &fKeyServPrefs);
			if( fKeyServPrefs )
			{
				for( i=0; i<sizeof(flagbuf); ++i )
					flagbuf[i] = (PGPByte)(keyServPrefs >> (i*8));
				pgpSigSpecSetKeyServPrefs( sigspec, 0, flagbuf,
										   sizeof(flagbuf) );
			}

			pgpSigSpecSetVersion (sigspec, PGPVERSION_4);
			pgpSigSpecSetPrimaryUserID (sigspec, 0, TRUE);
			if ((validity=pgpKeySpecValidity (keyspec)) != 0)
			{
				pgpSigSpecSetKeyExpiration (sigspec, 0,
					(PGPUInt32)validity*24*60*60);
				kinfo->validityperiod = validity;
			}
			/* Add any additional decryption packets requested */
			if (IsntNull (adkset) &&
					((void)PGPCountKeys((PGPKeySet *)adkset,&nkeys), nkeys>0))
			{
				if( IsPGPError( err = PGPNewKeyIterFromKeySet (
											(PGPKeySet *)adkset, &adkIter ) ) )
				{
					*error = err;
					goto cleanup;
				}
				while( IsntPGPError( PGPKeyIterNextKeyDBObj( adkIter,
							kPGPKeyDBObjType_Key, &tmpkey ) ) )
				{
					PGPByte adinfo[22];
					kinfo = pgpKeyToKeyInfo( tmpkey );
					adinfo[0] = adkclass;
					adinfo[1] = kinfo->pkalg;
					pgpKeyFingerprint20( tmpkey, adinfo+2 );
					*error = pgpSigSpecSetAdditionalRecipientRequest (sigspec,
									0, adinfo, sizeof(adinfo) );
					CHECKRETVAL (*error, *error);
				}
				PGPFreeKeyIter (adkIter);
				adkIter = NULL;
			}
		}
		*error = pgpSignObject( nameobj, sigspec );
		if (IsntPGPError(*error) && keyv4 && IsntNull (rakset) &&
					((void)PGPCountKeys((PGPKeySet *)rakset,&nkeys), nkeys>0))
		{
			/* Add any Revocation Authorization Keys requested */
			/* These go in a separate, irrevocable signature on the key */
			pgpSigSpecDestroy (sigspec);
			sigspec = pgpSigSpecCreate (env, keyobj, PGP_SIGTYPE_KEY_PROPERTY);
			CHECKRETVAL (!sigspec, kPGPError_OutOfMemory);
			pgpSigSpecSetPassphrase( sigspec, passphrase, pplen, hashedPhrase);
			if( IsPGPError( err = PGPNewKeyIterFromKeySet (
											(PGPKeySet *)rakset, &rakIter ) ) )
			{
				*error = err;
				goto cleanup;
			}
			while( IsntPGPError( PGPKeyIterNextKeyDBObj( rakIter,
						kPGPKeyDBObjType_Key, &tmpkey ) ) )
			{
				PGPByte krinfo[22];
				kinfo = pgpKeyToKeyInfo( tmpkey );
				/* Note that rakclass must have 0x80 set to be effective */
				krinfo[0] = rakclass;
				krinfo[1] = kinfo->pkalg;
				pgpKeyFingerprint20 ( tmpkey, krinfo+2 );
				*error = pgpSigSpecSetRevocationKey (sigspec, 0, krinfo,
													 sizeof(krinfo) );
				CHECKRETVAL (*error, *error);
			}
			PGPFreeKeyIter (rakIter);
			rakIter = NULL;
			/* Make this signature non-revocable */
			pgpSigSpecSetRevocable (sigspec, 0, FALSE);
			*error = pgpSignObject (keyobj, sigspec);
		}
	}

	/* This sets both key and name trust */
	pgpKeySetAxiomatic(keyobj);
	pgpKeyDBChanged( db, TRUE );

 cleanup:
	if (pubkey)
		pgpPubKeyDestroy (pubkey);
	if (sigspec)
		pgpSigSpecDestroy (sigspec);
	if (rakIter)
		PGPFreeKeyIter( rakIter );
	if (adkIter)
		PGPFreeKeyIter( adkIter );
	return keyobj;
}


/*
 * Given a (top level) key, a keyspec, and some other information,
 * create a subkey keydb object and put it under the keydb.
 * Then sign the pubkey using the master signature key.
 * seckey is the secret key coresponding to the master signature key,
 * subseckey is the secret key to be used for creating the new subkey.
 */
	PGPKeyDBObj *
pgpCreateSubkeypair (PGPKeyDBObj *keyobj, PGPEnv const *env,
	PGPSecKey *subseckey, PGPKeySpec *keyspec,
	PGPByte const *passphrase, PGPSize pplen, PGPBoolean hashedPhrase,
	PGPError *error)
{
	PGPKeyDB *db = PGPPeekKeyDBObjKeyDB( keyobj );
	PGPKeyDBObj *subkeyobj = NULL;
	PGPSigSpec *sigspec = NULL;
	PGPKeyInfo *kinfo;
	PGPUInt16 validity;
	PGPUInt32 keyFlags;
	PGPBoolean fKeyFlags;
	PGPUInt32 i;
	PGPBoolean secret = TRUE;
	PGPPubKey *subpubkey = NULL;
	PGPByte pkalg;

	pgpAssert( error );
	*error = kPGPError_NoErr;

	/*
	 * All subkeys are V4.
	 */
	pgpKeySpecSetVersion (keyspec, PGPVERSION_4);

	pkalg = subseckey->pkAlg;
	if( pgpSecKeyOnToken(subseckey) )
	{
		secret = FALSE;
		subpubkey = pgpSecKeyPubkey(subseckey);
	}

	/* Create the subkey object on the secret keyring */
	subkeyobj = pgpCreateKey (db, keyobj, secret, subpubkey,
							  (secret?subseckey:NULL), keyspec, pkalg);
	if (!subkeyobj)
	{
		*error = kPGPError_OutOfMemory;
		return NULL;
	}
	kinfo = pgpKeyToKeyInfo( subkeyobj );
	if( !secret )
	{
		pgpPubKeySetKeyID( subpubkey, kinfo->keyID );
		pgpKeyOnToken( subkeyobj, NULL );
	}
	pgpSecKeySetKeyID( subseckey, kinfo->keyID );

	/* Sign the encryption key with the master signature key */
	sigspec = pgpSigSpecCreate (env, keyobj, PGP_SIGTYPE_KEY_SUBKEY);
	if (!sigspec)
	{
		*error = kPGPError_OutOfMemory;
		return NULL;
	}
	pgpSigSpecSetPassphrase( sigspec, passphrase, pplen, hashedPhrase );

	/* New keys self-sign with special info */
	if ((validity=pgpKeySpecValidity (keyspec)) != 0)
	{
		pgpSigSpecSetKeyExpiration (sigspec, 0,
									(PGPUInt32)validity*24*3600);
		kinfo->validityperiod = validity;
	}
	keyFlags = pgpKeySpecKeyflags( keyspec, &fKeyFlags );
	if( fKeyFlags )
	{
		PGPByte flagbuf[4];
		for( i=0; i<sizeof(flagbuf); ++i )
			flagbuf[i] = (PGPByte)(keyFlags >> (i*8));
		pgpSigSpecSetKeyFlags( sigspec, 0, flagbuf, sizeof(flagbuf) );
	}

	*error = pgpSignObject ( subkeyobj, sigspec );
	if (*error)
		goto cleanup;

	pgpKeySetAxiomatic(subkeyobj);
	pgpKeyDBChanged( db, TRUE );

cleanup:

	if (subpubkey)
		pgpPubKeyDestroy (subpubkey);
	if (sigspec)
		pgpSigSpecDestroy (sigspec);

	return subkeyobj;		/* success */
}


/*
 * Signs an object (and its parents); then deposits the new signature
 * object in place on the set.
 */
	PGPError
pgpSignObject(PGPKeyDBObj *obj, PGPSigSpec *spec)
{
	PGPKeyDB *		kdb;
	PGPByte *		sig;
	PGPInt32		siglen;
	PGPKeyDBObj *	sigobj	= NULL;
	PGPContextRef	cdkContext;
	PGPSigInfo *	sinfo;

	kdb = PGPPeekKeyDBObjKeyDB( obj );
	cdkContext = PGPPeekKeyDBContext( kdb );

	/*
	 * Force signatures with newer-than-RSA keys to use version 4,
	 * and also if the hash is newer than those supported by PGP 5.0.
	 * A bug in PGP 5.0 won't let it load keyrings using version 2.6 sigs
	 * which have a hash not recognized by it.  
	 * The exception is revocation sigs on top-level keys.  A different
	 * bug in PGP 5.0 won't let it validate V4 sigs on top-level keys.
	 * The only sigs it tries to recognize on top-level keys are revocation
	 * sigs.  So those we leave as V3.
	 *
	 * Now we are also using V4 signatures when signing with an RSA key on
	 * a non-RSA key.  There is no backwards compatibility issue there
	 * so we'd rather move forward with the V4 signatures consistently.
	 */
	if( pgpSigSpecVersion (spec) == PGPVERSION_3 ) {
		PGPKeyDBObj *signkey = pgpSigSpecSeckey (spec);
		PGPByte hashtype = pgpSigSpecHashtype (spec);
		PGPByte sigtype = pgpSigSpecSigType (spec);
		PGPKeyInfo *kinfo;
		PGPKeyDBObj *topobj = obj;
		while (!OBJISTOPKEY (topobj))
			topobj = topobj->up;
		pgpAssert (OBJISTOPKEY(topobj));
		kinfo = pgpKeyToKeyInfo( topobj );
		if( ! (sigtype == PGP_SIGTYPE_KEY_REVOKE && OBJISTOPKEY(obj)) ) {
			PGPInt32 pkalg;
			pgpGetKeyNumber( signkey, kPGPKeyProperty_AlgorithmID, &pkalg );
			if( pkalg > kPGPPublicKeyAlgorithm_RSA
					|| kinfo->pkalg > kPGPPublicKeyAlgorithm_RSA
					|| hashtype > kPGPHashAlgorithm_RIPEMD160) {
				pgpSigSpecSetVersion( spec, PGPVERSION_4 );
			}
		}
	}

	siglen = pgpSignObj (obj, spec, &sig);
	if (siglen < 0)
		return (PGPError)siglen;
	if (siglen == 0)
	{
		pgpContextMemFree( cdkContext, sig);
		return kPGPError_OutOfMemory;
	}
	sigobj = pgpCreateSig (kdb, obj, sig, siglen);
	pgpContextMemFree( cdkContext, sig);
	if( IsNull( sigobj ) )
		return pgpKeyDBError( kdb );
	sinfo = pgpSigToSigInfo( sigobj );
	sinfo->trust = PGP_SIGTRUSTF_CHECKED_TRIED | kPGPKeyTrust_Complete;

	return sigobj ? kPGPError_NoErr : kPGPError_OutOfMemory;
}



/*
 * Create a new public key in a keydb.  secret is true for pub/sec key
 * pairs.  If parent is non-null, this is a subkey of that parent.
 * If secret is set, skey is used, else pkey is used.
 */
	PGPKeyDBObj *
pgpCreateKey(PGPKeyDB *db, PGPKeyDBObj *parent, PGPBoolean secret,
	PGPPubKey const *pkey, PGPSecKey const *skey, PGPKeySpec const *ks,
	PGPByte pkalg)
{
	PGPContextRef context;
	PGPKeyDBObj *obj;
	PGPByte *pktbuf;
	PGPSize len, prefixlen, headerlen;
	PGPError err;
	PGPByte pkttype;

	if( secret )
		pkttype = parent ? PKTBYTE_SECSUBKEY : PKTBYTE_SECKEY;
	else
		pkttype = parent ? PKTBYTE_PUBSUBKEY : PKTBYTE_PUBKEY;
	pgpAssert( secret ? IsNull(pkey) : IsNull(skey) );
	pgpAssert( secret ? IsntNull(skey) : IsntNull(pkey) );

	pkttype = PKTBYTE_BUILD( pkttype, 1 );

	/* Calculate packet size */
	prefixlen = pgpKeyBufferLength(ks, pkalg);
	len = prefixlen + (secret ? pgpSecKeyBufferLength(skey)
					   : pgpPubKeyBufferLength(pkey) );
	headerlen = pgpPktHeaderLen( pkttype, len );
	len += headerlen;
	if (len >= PGPOBJ_MAXSIZE) {
		pgpKeyDBSetError( db, kPGPError_TroubleKeyTooBig);
		return NULL;
	}

	/* Allocate space */
	context = PGPPeekKeyDBContext( db );
	pktbuf = pgpContextMemAlloc( context, len, 0 );
	if( IsNull(pktbuf) )
	{
		pgpKeyDBSetError( db, kPGPError_OutOfMemory );
		return NULL;
	}

	/* Fill buffer */
	pgpPktHeaderPut( pktbuf, pkttype, len-headerlen );
	pgpKeyToBuffer(pktbuf+headerlen, ks, pkalg);
	if( secret )
		pgpSecKeyToBuffer(skey, pktbuf+headerlen+prefixlen);
	else
		pgpPubKeyToBuffer(pkey, pktbuf+headerlen+prefixlen);

	/* Add to keyring (makes a copy of the data buffer) */
	obj = pgpAddObject( pktbuf, len, db, parent, TRUE, &err );
	PGPFreeData( pktbuf );

	return obj;
}

/*
 * Change the data associated with a secret key.
 */
	PGPError
pgpUpdateSecKeyData( PGPKeyDBObj *key, PGPSecKey const *skey )
{
	PGPContextRef context;
	PGPKeyDB *db;
	PGPByte *newpktbuf;
	PGPSize len, prefixlen, headerlen, newlen, newheaderlen;
	PGPByte const *kdata;
	PGPByte version;
	PGPError err = kPGPError_NoErr;

	pgpAssert( OBJISKEY( key ) );
	pgpAssert( pgpKeyIsSec( key ) );

	/* Token keys don't need updates */
	if( pgpKeyIsOnToken( key ) )
		return kPGPError_NoErr;

	db = PGPPeekKeyDBObjKeyDB( key );
	context = PGPPeekKeyDBContext( db );
	kdata = pgpFetchObject( key, &len );

	/* Calculate packet size */
	headerlen = pgpPktBufferHeaderLen( kdata );
	version = kdata[headerlen];
	prefixlen = (version == PGPVERSION_4) ? 6 : 8;
	newlen = prefixlen + pgpSecKeyBufferLength(skey);
	newheaderlen = pgpPktHeaderLen( kdata[0], newlen );

	newlen += newheaderlen;
	if (newlen >=

⌨️ 快捷键说明

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