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

📄 pgpdsakey.c

📁 vc环境下的pgp源码
💻 C
📖 第 1 页 / 共 3 页
字号:
			len_seq = pgpBnX509LenLen(qbytes+1) + 1 + qbytes+1;
		else
			len_seq = pgpBnX509LenLen(qbytes) + 1 + qbytes;
		if (8*qbytes == bnBits(&s))
			len_seq += pgpBnX509LenLen(qbytes+1) + 1 + qbytes+1;
		else
			len_seq += pgpBnX509LenLen(qbytes) + 1 + qbytes;
		lenlen_seq = pgpBnX509LenLen(len_seq);
		sig[t++] = X509_TAG_SEQUENCE | X509_TAG_CONSTRUCTED;
		if (--lenlen_seq == 0) {
			sig[t++] = len_seq;
		} else {
			sig[t++] = 0x80 | lenlen_seq;
			len_seq <<= 8 * (4-lenlen_seq);
			while (lenlen_seq--) {
				sig[t++] = (PGPByte)(len_seq >> 24);
				len_seq <<= 8;
			}
		}
	}
	t += pgpBnPutFormatted(&r, sig+t, qbytes, format);
	t += pgpBnPutFormatted(&s, sig+t, qbytes, format);
	if (siglen)
		*siglen = (size_t)t;

	i = 0;
	goto done;

nomem:
	i = kPGPError_OutOfMemory;
	/* fall through */
done:
	pgpRandomDestroy(rc2);
	bnEnd(&k);
	bnEnd(&bn);
	bnEnd(&s);
	bnEnd(&r);
	return i;

#endif /* PGP_SIGN_DISABLE */ /* ] */
}


/*
 * Re-encrypt a PGPSecKey with a new urn a PGPSecKey into a secret key.
 * A secret key is, after a non-specific prefix:
 *  0       1    Version (= 2 or 3)
 *  1       4    Timestamp
 *  5       2    Validity (=0 at present)
 *  7       1    Algorithm (=kPGPPublicKeyAlgorithm_DSA for DSA)
 * The following:
 *  0                2+u  MPI for prime p
 *  2+u              2+v  MPI for order q
 *  4+u+v            2+w  MPI for generator g
 *  6+u+v+w	     2+x  MPI for public key y
 *  8+u+v+w+x        1    Encryption algorithm (0 for none, 1 for IDEA)
 *  9+u+v+w+x        t    Encryption IV: 0 or 8 bytes
 *  9+t+u+v+w+x      2+y  MPI for x (discrete log of public key)
 * 11+t+u+v+w+x+y    2    Checksum
 * 13+t+u+v+w+x+y
 *
 * The Encryption algorithm is the cipher algorithm for the old-style
 * string-to-key conversion.  For the new type, it's 255, then a cipher
 * algorithm, then a string-to-key algorithm (variable-length),
 * then the encryption IV.  That's 16 bytes plus the string-to-key
 * conversion length.
 */
#if PGP_MACINTOSH
#pragma global_optimizer on
#endif

static int
dsaChangeLock(PGPSecKey *seckey, PGPEnv const *env, 
	PGPRandomContext const *rc, char const *phrase, size_t plen,
	PGPStringToKeyType s2ktype)
{
	DSAsecPlus *sec = (DSAsecPlus *)seckey->priv;
	PGPStringToKey *s2k = NULL;	/* Shut up warnings */
	PGPCipherVTBL const *cipher = NULL;	/* Shut up warnings */
	PGPCFBContext *cfb = NULL;	/* This is realy needed */
	PGPByte *p;
	PGPByte key[PGP_CIPHER_MAXKEYSIZE];
	int oldf = 0;				/* Shut up warnings */
	unsigned len;
	unsigned checksum;

	ASSERTDSA(seckey->pkAlg);
	if (sec->locked)
		return kPGPError_KeyIsLocked;
	len = bnBytes(&sec->s.p) + bnBytes(&sec->s.q) + bnBytes(&sec->s.g) +
	      bnBytes(&sec->s.y) + bnBytes(&sec->s.x) + 13;
	if (phrase) {
		s2k = pgpS2Kcreate(env, rc, s2ktype);
		if (!s2k)
			return kPGPError_OutOfMemory;
		cipher = pgpCipherDefaultKey(env);
		pgpAssert(cipher);
		if (!cipher) {
			pgpS2Kdestroy(s2k);
			return kPGPError_OutOfMemory;
		}
		len += cipher->blocksize;
		cfb = pgpCFBCreate(
				PGPGetContextMemoryMgr( pgpenvGetContext( env ) ), cipher);
		if (!cfb) {
			pgpS2Kdestroy(s2k);
			return kPGPError_OutOfMemory;
		}
		oldf = pgpS2KisOldVers(s2k);
		if (!oldf)
			len += 1 + s2k->encodelen;
	}
	if (len > sec->ckalloc) {
		PGPError err = kPGPError_NoErr;
		if( IsNull( sec->cryptkey ) ) {
			sec->cryptkey = (PGPByte *)
				pgpContextMemAlloc( sec->context, len, 0 );
			if( IsNull( sec->cryptkey ) ) {
				err = kPGPError_OutOfMemory;
			}
		} else {
			err = pgpContextMemRealloc( sec->context,
				(void **)&sec->cryptkey, len, 0 );
		}
		if( IsPGPError( err ) ) {
			PGPFreeCFBContext(cfb);
			pgpS2Kdestroy(s2k);
			return err;
		}
		sec->ckalloc = (size_t)len;
	}
	sec->cklen = len;
	p = sec->cryptkey;

	/* Okay, no more errors possible!   Start installing data */
	p += pgpBnPutPlain(&sec->s.p, p);
	p += pgpBnPutPlain(&sec->s.q, p);
	p += pgpBnPutPlain(&sec->s.g, p);
	p += pgpBnPutPlain(&sec->s.y, p);

	/* Encryption parameters */
	if (!phrase) {
		*p++ = 0;	/* Unencrypted */
	} else {
		if (oldf) {
			*p++ = cipher->algorithm;
		} else {
			*p++ = 255;
			*p++ = cipher->algorithm;
			memcpy(p, s2k->encoding, s2k->encodelen);
			p += s2k->encodelen;
		}
		/* Create IV */
		pgpRandomGetBytes(rc, p, cipher->blocksize);
		pgpStringToKey(s2k, phrase, plen, key, cipher->keysize);
		PGPInitCFB(cfb, key, p);
		pgpS2Kdestroy(s2k);
		p += cipher->blocksize;
		/* Wipe key *immediately* */
		pgpClearMemory( key,  cipher->keysize);
	}

	/* Now install x, encrypted */
	checksum = 0;
	p += pgpBnPutNew(&sec->s.x, p, cfb, &checksum);
	pgpChecksumPutNew(checksum, p, cfb);
	p += 2;
	pgpAssert((ptrdiff_t)len == p - sec->cryptkey);

	if (cfb)
		PGPFreeCFBContext(cfb);
	return 0;	/* Success */
}
#if PGP_MACINTOSH
#pragma global_optimizer reset
#endif

static size_t
dsaSecBufferLength(PGPSecKey const *seckey)
{
	DSAsecPlus const *sec = (DSAsecPlus *)seckey->priv;

	return sec->cklen;
}

static void
dsaSecToBuffer(PGPSecKey const *seckey, PGPByte *buf)
{
	DSAsecPlus const *sec = (DSAsecPlus *)seckey->priv;

	memcpy(buf, sec->cryptkey, sec->cklen);

	/* Return only algorithm-dependent portion */
}


/* Fill in secret key structure */
static void
dsaFillSecKey(PGPSecKey *seckey, DSAsecPlus *sec)
{
	seckey->pkAlg	            = kPGPPublicKeyAlgorithm_DSA;
	seckey->priv	            = sec;
	seckey->destroy             = dsaSecDestroy;
	seckey->pubkey              = dsaPubkey;
	seckey->islocked            = dsaIslocked;
	seckey->lockingalgorithm    = dsaLockingAlgorithm;
	seckey->s2ktype             = dsaS2KType;
	seckey->convertpassphrase   = dsaConvertPassphrase;
	seckey->unlock              = dsaUnlock;
	seckey->lock                = dsaLock;
	seckey->decrypt             = dsaDecrypt;
	seckey->maxdecrypted        = dsaSecMaxdecrypted;
	seckey->maxesk              = dsaSecMaxesk;
	seckey->maxsig              = dsaSecMaxsig;
	seckey->sign                = dsaSign;
	seckey->changeLock          = dsaChangeLock;
	seckey->bufferLength        = dsaSecBufferLength;
	seckey->toBuffer            = dsaSecToBuffer;
}


PGPSecKey *
dsaSecFromBuf(
	PGPContextRef	context,
	PGPByte const *	buf,
	size_t			size,
	PGPError *		error)
{
	PGPSecKey *seckey;
	DSAsecPlus *sec;
	PGPByte *cryptk;
	PGPError	err	= kPGPError_OutOfMemory;
	PGPMemoryMgrRef		mgr	= PGPGetContextMemoryMgr( context );
	PGPEnv *			pgpEnv = pgpContextGetEnvironment( context );

	bnInit();
	cryptk = (PGPByte *)pgpContextMemAlloc( context,
		size, kPGPMemoryMgrFlags_Clear);
	if (cryptk) {
		sec = (DSAsecPlus *)PGPNewSecureData( mgr, sizeof(*sec), 0 );
		if (sec) {
			pgpClearMemory( sec, sizeof(*sec) );
			sec->context	= context;
			
			seckey = (PGPSecKey *) pgpContextMemAlloc( context,
					sizeof(*seckey), kPGPMemoryMgrFlags_Clear);
			if (seckey) {
				seckey->context	= context;
			
				memcpy(cryptk, buf, size);
				bnBegin(&sec->s.p, mgr, FALSE );
				bnBegin(&sec->s.q, mgr, FALSE );
				bnBegin(&sec->s.g, mgr, FALSE );
				bnBegin(&sec->s.y, mgr, FALSE );
				bnBegin(&sec->s.x, mgr, TRUE );
				sec->cryptkey = cryptk;
				sec->cklen = sec->ckalloc = size;
				sec->locked = 1;
				/* We only need this to try unlocking... */
				seckey->pkAlg = kPGPPublicKeyAlgorithm_DSA;
				seckey->priv = sec;
				
				if (dsaUnlock(seckey, pgpEnv, NULL, 0, FALSE) >= 0) {
					if (dsaKeyTooBig (NULL, &sec->s)) {
						bnEnd(&sec->s.p);
						bnEnd(&sec->s.q);
						bnEnd(&sec->s.g);
						bnEnd(&sec->s.y);
						err = kPGPError_KeyTooLarge;
					} else {
						dsaFillSecKey(seckey, sec);
						*error = 0;
						return seckey;	/* Success! */
					}
				}

				/* Ka-boom.  Delete and free everything. */
				pgpClearMemory( cryptk,  size);
				pgpContextMemFree( context, seckey);
			}
			PGPFreeData( sec );			/* Wipes as it frees */
		}
		pgpContextMemFree( context, cryptk);
	}
	*error = err;
	return NULL;
}


/*
 * Generate an DSA secret key with prime of the specified number of bits.
 * Make callbacks to progress function periodically.
 * Secret key is returned in the unlocked form, with no passphrase set.
 * fastgen tells us to use canned primes if available.
 *
 * PGP attempts to acquire enough true random entropy in the randpool to
 * make the keys it generates fully random and unpredictable, even if the
 * RNG used to generate them were later found to have some weaknesses.  With
 * RSA keys it gets as many bits as the size of the modulus since the sizes
 * of the secret primes p and q will add up to the size of the modulus.
 * (This is slight overkill since the entropy in a random prime is less
 * than the entropy of a random number because not all numbers are prime.)
 *
 * With discrete log based keys, DSA and ElGamal, only the private exponent
 * x needs to be kept secret.  However, the public values are generated at
 * the same time as x, and are seeded ultimately from the same randpool.
 * These values could theoretically leak information about the state of the
 * randpool when they were generated, and therefore about x.  This would
 * require a very powerful attack which will probably never be possible,
 * but we want to defend against it.  One approach would simply be to acquire
 * as much additional entropy as is needed for the public values, but that
 * is wasteful.  The public values don't need to be random, we just want them
 * to be different among users.
 *
 * Instead, we create a "firewall" between the randpool and the public
 * key values.  We instantiate a second PGPRandomContext which is not
 * based on the randpool but is a simple pseudo RNG, and seed it with
 * a fixed number of bits from the true RNG.  We choose enough bits
 * for the seeding that different keys will not share the same public
 * values.  Only this fixed number of bits reflects the state of the
 * randpool, so we acquire that many bits of additional entropy before
 * beginning the keygen.  This second RNG, rcdummy below and in the
 * ElGamal keygen, is used to generate the public values for the discrete
 * log key.
 */
PGPSecKey *
dsaSecGenerate(
	PGPContextRef	context,
	unsigned bits, PGPBoolean fastgen,
	PGPRandomContext const *rc,
	int progress(void *arg, int c), void *arg, PGPError *error)
{
	PGPSecKey *seckey	= NULL;
	DSAsecPlus *sec;
	PGPRandomContext *rcdummy = NULL;
	BigNum h;
	BigNum e;
	unsigned qbits;
	int i;
	PGPByte dummyseed[DSADUMMYBITS/8];
	PGPMemoryMgrRef		mgr	= PGPGetContextMemoryMgr( context );
	PGPEnv *			pgpEnv = pgpContextGetEnvironment( context );

	*error = kPGPError_NoErr;

	/*
	 * Make bits a multiple of 64.  This is required by the standard,
	 * and also makes it likely that all the various crypto libraries,
	 * smart cards, etc. will be able to work with the keys.
	 */
	bits = 64 * ((bits + 63) / 64);

	/* Initialize local pointers (simplify cleanup below) */
	seckey = NULL;
	sec = NULL;
	bnBegin(&h, mgr, FALSE );
	bnBegin(&e, mgr, FALSE );
	
	/* Limit the size we will generate at this time */
	if (bits > MAX_DSA_PRIME_BITS) {
		*error = kPGPError_PublicKeyTooLarge;
		goto done;
	}



	/* Allocate data structures */
	seckey = (PGPSecKey *)pgpContextMemAlloc( context,
		sizeof(*seckey), kPGPMemoryMgrFlags_Clear);
	if (!seckey)
		goto memerror;
	seckey->context	= context;
	sec = (DSAsecPlus *)PGPNewSecureData( mgr, sizeof(*sec), 0 );
	if (!sec)
		goto memerror;
	pgpClearMemory( sec, sizeof(*sec) );
	sec->context	= context;
	
	bnBegin(&sec->s.p, mgr, FALSE );
	bnBegin(&sec->s.q, mgr, FALSE );
	bnBegin(&sec->s.g, mgr, FALSE );
	bnBegin(&sec->s.y, mgr, FALSE );
	bnBegin(&sec->s.x, mgr, TRUE );

	/* Use fixed primes and generator if in our table */
	if (fastgen) {
		PGPByte const *fixedp, *fixedq;
		size_t fixedplen, fixedqlen;
		if (pgpDSAfixed (bits, &fixedp, &fixedplen, &fixedq, &fixedqlen) > 0) {
			bnInsertBigBytes (&sec->s.q, fixedq, 0, fixedqlen);
			if (progress != NULL)
				progress(arg, ' ');
			bnInsertBigBytes (&sec->s.p, fixedp, 0, fixedplen);
			if (progress != NULL)
				progress(arg, ' ');
			qbits = bnBits (&sec->s.q);
			goto choose_g;
		}
	}

	/* Set up and seed local random number generator for p and q */
	rcdummy = pgpPseudoRandomCreate ( rc->context );
	if (!rcdummy)
		goto memerror;
	pgpRandomGetBytes (rc, dummyseed, sizeof(dummyseed));
	pgpRandomAddBytes (rcdummy, dummyseed, sizeof(dummyseed));

	/*
	 * Choose a random starting place for q, in the high end of the range
	 */
	if (bits <= 1024)
		qbits = 160;	/* Follow the published standard */
	else
		qbits = pgpDiscreteLogQBits(bits);
	if (pgpBnGenRand(&sec->s.q, rcdummy, qbits, 0xFF, 1, qbits-9) < 0)
		goto nomem;
	/* And search for a prime */
	i = bnPrimeGen(&sec->s.q, NULL, progress, arg, 0);
	if (i < 0)
		goto nomem;
	if (progress != NULL)
		progress(arg, ' ');

	/* ...and now a random start for p (we discard qbits bits of it) */
	(void)bnSetQ(&sec->s.p, 0);
	if (pgpBnGenRand(&sec->s.p, rcdummy, bits, 0xC0, 1, bits-qbits) < 0)
		goto nomem;

	/* Temporarily double q */
	if (bnLShift(&sec->s.q, 1) < 0)
		goto nomem;

	/* Set p = p - (p mod q) + 1, i.e. congruent to 1 mod 2*q */
	if (bnMod(&e, &sec->s.p, &sec->s.q) < 0)
		goto nomem;
	if (bnSub(&sec->s.p, &e) < 0 || bnAddQ(&sec->s.p, 1) < 0)
		goto nomem;

	/* And search for a prime, 1+2kq for some k */
	i = bnPrimeGenStrong(&sec->s.p, &sec->s.q, progress, arg);
	if (i < 0)
		goto nomem;
	if (progress != NULL)
		progress(arg, ' ');

	/* Reduce q again */
	bnRShift(&sec->s.q, 1);

	/* May get here directly from above if fixed primes are used */
choose_g:

	/* Now hunt for a suitable g - first, find (p-1)/q */
	if (bnDivMod(&e, &h, &sec->s.p, &sec->s.q) < 0)
		goto nomem;
	/* e is now the exponent (p-1)/q, and h is the remainder (one!) */
	pgpAssert(bnBits(&h)==1);

	if (progress != NULL)
		progress(arg, '.');

	/* Search for a suitable h */
	if (bnSetQ(&h, 2) < 0 ||
	    bnTwoExpMod(&sec->s.g, &e, &sec->s.p) < 0)
		goto nomem;
	while (bnBits(&sec->s.g) < 2) {
		if (progress != NULL)
			progress(arg, '.');
		if (bnAddQ(&h, 1) < 0 ||
		    bnExpMod(&sec->s.g, &h, &e, &sec->s.p) < 0)
			goto nomem;
	}
	if (progress != NULL)
		progress(arg, ' ');

	/* Choose a random 0 < x < q of reasonable size as secret key */
	if (pgpBnGenRand(&sec->s.x, rc, qbits + 8, 0, 0, qbits) < 0 ||
	    bnMod(&sec->s.x, &sec->s.x, &sec->s.q) < 0)
		goto nomem;
	/* prob. failure < 2^-140 is awful unlikely... */
	pgpAssert(bnBits(&sec->s.x) > 20);

	/* And calculate g**x as public key */
	if (bnExpMod(&sec->s.y, &sec->s.g, &sec->s.x, &sec->s.p) < 0)
		goto nomem;

	/* And that's it... success! */

	/* Fill in structs */
	sec->cryptkey = NULL;
	sec->ckalloc = sec->cklen = 0;
	sec->locked = 0;
	dsaFillSecKey(seckey, sec);

	/* Fill in cryptkey structure, unencrypted */
	dsaChangeLock (seckey, pgpEnv, NULL, NULL, 0, kPGPStringToKey_Simple);

	goto done;

nomem:
	bnEnd(&sec->s.p);
	bnEnd(&sec->s.q);
	bnEnd(&sec->s.g);
	bnEnd(&sec->s.y);
	bnEnd(&sec->s.x);
	/* Fall through */
memerror:
	if ( IsntNull( seckey ) )
		pgpContextMemFree( context, seckey);
	if ( IsntNull( sec ) )
		PGPFreeData( sec );			/* Wipes as it frees */
	seckey = NULL;
	*error = kPGPError_OutOfMemory;
	/* Fall through */
done:
	bnEnd(&h);
	bnEnd(&e);

	if (rcdummy)
	{
		pgpRandomDestroy (rcdummy);
	}
	
	return seckey;
}

⌨️ 快捷键说明

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