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

📄 pgprsakey.c

📁 vc环境下的pgp源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	(void)format;
	return kPGPError_FeatureNotAvailable;

#else

	RSAsecPlus *sec = (RSAsecPlus *)seckey->priv;
	BigNum bn;
	int i;
	unsigned t;
	PGPMemoryMgrRef		mgr	= NULL;
	
	mgr	= PGPGetContextMemoryMgr( seckey->context );

	/* We don't need these arguments, although other algorithms may... */
	(void)rc;
	(void)format;

	ASSERTRSASIG(seckey->pkAlg);
	if (sec->locked)
		return kPGPError_KeyIsLocked;

	bnBegin(&bn, mgr, TRUE);

#if PGP_USECAPIFORRSA
	i = rsaSignHash(&bn, &sec->s, h, hash);
#else
	t = h->DERprefixsize;
	/* IKE does not put in hash OID */
	if (format == kPGPPublicKeyMessageFormat_IKE)
		t = 0;
	if (t+h->hashsize  > rsaSecMaxsig(seckey, format))
		return kPGPError_PublicKeyTooSmall;
	memcpy(sig, h->DERprefix, t);
	memcpy(sig+t, hash, h->hashsize);
	t += h->hashsize;

	i = rsaPrivateEncrypt(&bn, sig, t, &sec->s);
	pgpClearMemory( sig,  t);
#endif
	if (i >= 0) {
		t = 0;
		if (format == kPGPPublicKeyMessageFormat_X509) {
			/* Output unformatted, but with no leading zeros */
			format = kPGPPublicKeyMessageFormat_PKCS1;
			t += pgpBnPutFormatted(&bn, sig+t, bnBytes(&bn), format);
		} else {
			t += pgpBnPutFormatted(&bn, sig+t, bnBytes(&sec->s.n), format);
		}
		if (siglen)
			*siglen = (size_t)t;
		i = 0;
	}
	bnEnd(&bn);
	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 (=1 for RSA)
 * The following:
 *  0                2+u  MPI for modulus
 *  2+u              2+v  MPI for exponent
 *  4+u+v            1    Encryption algorithm (0 for none, 1 for IDEA)
 *  5+u+v            t    Encryption IV: 0 or 8 bytes
 *  5+t+u+v          2+w  MPI for d
 *  7+t+u+v+w        2+x  MPI for p
 *  9+t+u+v+w+x      2+y  MPI for q
 * 11+t+u+v+w+x+y    2+z  MPI for u
 * 13+t+u+v+w+x+y+z  2    Checksum (big-endian sum of all the bytes)
 * 15+t+u+v+w+x+y+z
 *
 * 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
rsaChangeLock(PGPSecKey *seckey, PGPEnv const *env, 
	PGPRandomContext const *rc, char const *phrase, size_t plen,
	PGPStringToKeyType s2ktype)
{
	RSAsecPlus *sec = (RSAsecPlus *)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;

	ASSERTRSA(seckey->pkAlg);
	if (sec->locked)
		return kPGPError_KeyIsLocked;

	len = bnBytes(&sec->s.n) + bnBytes(&sec->s.e) +
	      bnBytes(&sec->s.d) + bnBytes(&sec->s.p) +
	      bnBytes(&sec->s.q) + bnBytes(&sec->s.u) + 15;
	if (phrase) {
		/* Create old-style s2k unless new features requested */
		if (s2ktype == kPGPStringToKey_Simple)
			s2k = pgpS2KdefaultV3(env, rc);
		else
			s2k = pgpS2Kcreate(env, rc, s2ktype);
		if (!s2k)
			return kPGPError_OutOfMemory;
		cipher = pgpCipherDefaultKeyV3(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.n, p);
	p += pgpBnPutPlain(&sec->s.e, 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 d, p, q and u, encrypted */
	checksum = 0;
	p += pgpBnPut(&sec->s.d, p, cfb, &checksum, sec->v3);
	p += pgpBnPut(&sec->s.p, p, cfb, &checksum, sec->v3);
	p += pgpBnPut(&sec->s.q, p, cfb, &checksum, sec->v3);
	p += pgpBnPut(&sec->s.u, p, cfb, &checksum, sec->v3);
	pgpChecksumPutOld(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
rsaSecBufferLength(PGPSecKey const *seckey)
{
	RSAsecPlus const *sec = (RSAsecPlus *)seckey->priv;

	return sec->cklen;
}

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

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

/* Fill in secret key structure */
static void
rsaFillSecKey(PGPSecKey *seckey, RSAsecPlus *sec)
{
	seckey->pkAlg	            = kPGPPublicKeyAlgorithm_RSA;
	seckey->priv	            = sec;
	seckey->destroy             = rsaSecDestroy;
	seckey->pubkey              = rsaPubkey;
	seckey->islocked            = rsaIslocked;
	seckey->lockingalgorithm    = rsaLockingAlgorithm;
	seckey->s2ktype             = rsaS2KType;
	seckey->convertpassphrase   = rsaConvertPassphrase;
	seckey->unlock              = rsaUnlock;
	seckey->lock                = rsaLock;
	seckey->decrypt             = rsaDecrypt;
	seckey->maxdecrypted        = rsaSecMaxdecrypted;
	seckey->maxsig              = rsaSecMaxsig;
	seckey->maxesk              = rsaSecMaxesk;
	seckey->sign                = rsaSign;
	seckey->changeLock          = rsaChangeLock;
	seckey->bufferLength        = rsaSecBufferLength;
	seckey->toBuffer            = rsaSecToBuffer;
}


PGPSecKey *
rsaSecFromBuf(
	PGPContextRef	context,
	PGPByte const *	buf,
	size_t			size,
	PGPBoolean		v3,
	PGPError *		error)
{
	PGPSecKey *seckey;
	RSAsecPlus *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 = (RSAsecPlus *)PGPNewSecureData( mgr, sizeof(*sec), 0 );
		if (sec) {
			pgpClearMemory( sec, sizeof(*sec) );
			sec->context	= context;
			sec->v3			= v3;
			seckey = (PGPSecKey *)
				pgpContextMemAlloc(context,
					sizeof(*seckey), kPGPMemoryMgrFlags_Clear);
			if (seckey) {
				seckey->context	= context;
				
				memcpy(cryptk, buf, size);
				bnBegin(&sec->s.n, mgr, FALSE);
				bnBegin(&sec->s.e, mgr, FALSE);
				bnBegin(&sec->s.d, mgr, TRUE);
				bnBegin(&sec->s.p, mgr, TRUE);
				bnBegin(&sec->s.q, mgr, TRUE);
				bnBegin(&sec->s.u, mgr, TRUE);
				sec->cryptkey = cryptk;
				sec->cklen = sec->ckalloc = size;
				sec->locked = 1;
				/* We only need this to try unlocking... */
				seckey->pkAlg = kPGPPublicKeyAlgorithm_RSA;
				seckey->priv = sec;
				
				if (rsaUnlock(seckey, pgpEnv, NULL, 0, FALSE) >= 0) {
					if (rsaKeyTooBig (NULL, &sec->s) ||
						bnBits(&sec->s.n) > 2048) {
						bnEnd (&sec->s.n);
						bnEnd (&sec->s.e);
						err = kPGPError_KeyTooLarge;
					} else {
						rsaFillSecKey(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;
}

#if PGP_RSA_KEYGEN

/*
 * PGPRandomContext to use for primeGen callback.  We really should enhance
 * primeGen to pass an arg parameter along with the limit value.
 */
static PGPRandomContext const *staticrc;

/* Random callback for primeGen */
static unsigned randcallback(unsigned limit)
{
	return pgpRandomRange(staticrc, limit);
}

/*
 * Generate an RSA secret key with modulus of the specified number of bits.
 * We choose public exponent from the #define value above.
 * The high two bits of each prime are always
 * set to make the number more difficult to factor by forcing the
 * number into the high end of the range.
 * Make callbacks to progress function periodically.
 * Secret key is returned in the unlocked form, with no passphrase set.
 * fastgen is an unused flag which is used by the discrete log keygens to
 * allow use of canned primes.
 */
PGPSecKey *
rsaSecGenerate(
	PGPContextRef	context,
	unsigned bits, PGPBoolean fastgen,
	PGPRandomContext const *rc,
	int progress(void *arg, int c), void *arg, PGPError *error)
{
	PGPSecKey *seckey;
	RSAsecPlus *sec;
	BigNum t;		/* temporary */
	unsigned ent;			/* Entropy */
	int i;
	int exp = RSA_DEFAULT_EXPONENT;
	PGPMemoryMgrRef		mgr	= PGPGetContextMemoryMgr( context );
	PGPEnv *			pgpEnv = pgpContextGetEnvironment( context );

	(void) fastgen;

	*error = kPGPError_NoErr;

	/* Initialize local pointers (simplify cleanup below) */
	seckey = NULL;
	sec = NULL;
	bnBegin(&t, mgr, TRUE);

	/* Allocate data structures */
	seckey = (PGPSecKey *)pgpContextMemAlloc( context, 
		sizeof(*seckey), kPGPMemoryMgrFlags_Clear );
	if (!seckey)
		goto memerror;
	seckey->context	= context;
	sec = (RSAsecPlus *)PGPNewSecureData( mgr, sizeof(*sec), 0 );
	if (!sec)
		goto memerror;
	sec->context	= context;
	sec->v3			= TRUE;
	
	/* n is not inherently sensitive, but holds sensitive intermediates */
	bnBegin(&sec->s.n, mgr, TRUE);
	bnBegin(&sec->s.e, mgr, FALSE);
	bnBegin(&sec->s.d, mgr, TRUE);
	bnBegin(&sec->s.p, mgr, TRUE);
	bnBegin(&sec->s.q, mgr, TRUE);
	bnBegin(&sec->s.u, mgr, TRUE);
	
	if (bnSetQ(&sec->s.e, exp))
		goto bnerror;

	/* Find p - choose a starting place */
	if (pgpBnGenRand(&sec->s.p, rc, bits/2, 0xC0, 1, bits/2-3) < 0)
		goto bnerror;

	/* And search for a prime */
	staticrc = rc;
	i = bnPrimeGen(&sec->s.p, randcallback, progress, arg, exp, 0);
	if (i < 0)
		goto bnerror;
	pgpAssert(bnModQ(&sec->s.p, exp) != 1);

	/* Make sure p and q aren't too close together */

	/* Bits of entropy needed to generate q. */
	ent = (bits+1)/2 - 3;
	/* Pick random q until we get one not too close to p */
	do {
		/* Visual separator between the two progress indicators */
		if (progress != NULL)
			progress(arg, ' ');
		if (pgpBnGenRand(&sec->s.q, rc, (bits+1)/2, 0xC0, 1, ent) < 0)
			goto bnerror;
		ent = 0;	/* No entropy charge next time around */
		if (bnCopy(&sec->s.n, &sec->s.q) < 0)
			goto bnerror;
		if (bnSub(&sec->s.n, &sec->s.p) < 0)
			goto bnerror;
		/* Note that bnSub(a,b) returns abs(a-b) */
	} while (bnBits(&sec->s.n) < bits/2-5);

	i = bnPrimeGen(&sec->s.q, randcallback, progress, arg, exp, 0);
	if (i < 0)
		goto bnerror;
	pgpAssert(bnModQ(&sec->s.p, exp) != 1);

	/* Wash the random number pool. */
	pgpRandomStir(rc);

	/* Ensure that q is larger */
	if (bnCmp(&sec->s.p, &sec->s.q) > 0)
		bnSwap(&sec->s.p, &sec->s.q);

	/*
	 * Now we compute d,
	 * the decryption exponent, from the encryption exponent.
	 */

	/* Decrement q temporarily */
	(void)bnSubQ(&sec->s.q, 1);
	/* And u = p-1, to be divided by gcd(p-1,q-1) */
	if (bnCopy(&sec->s.u, &sec->s.p) < 0)
		goto bnerror;
	(void)bnSubQ(&sec->s.u, 1);

	/* Use t to store gcd(p-1,q-1) */
	if (bnGcd(&t, &sec->s.q, &sec->s.u) < 0) {
		goto bnerror;
	}

	/* Let d = (p-1) / gcd(p-1,q-1) (n is scratch for the remainder) */
	i = bnDivMod(&sec->s.d, &sec->s.n, &sec->s.u, &t);
	if (i < 0)
		goto bnerror;
	pgpAssert(bnBits(&sec->s.n) == 0);

	/* Now we have q-1 and d = (p-1) / gcd(p-1,q-1) */
	/* Find the product, n = lcm(p-1,q-1) = c * d */
	if (bnMul(&sec->s.n, &sec->s.q, &sec->s.d) < 0)
		goto bnerror;

	/* Find the inverse of the exponent mod n */
	i = bnInv(&sec->s.d, &sec->s.e, &sec->s.n);
	if (i < 0)
		goto bnerror;
	pgpAssert(!i);	/* We should NOT get an error here */

	/*
	 * Now we have the comparatively simple task of computing
	 * u = p^-1 mod q.
	 */

	/* But it *would* be nice to have q back first. */
	(void)bnAddQ(&sec->s.q, 1);

	/* Now compute u = p^-1 mod q */
	i = bnInv(&sec->s.u, &sec->s.p, &sec->s.q);
	if (i < 0)
		goto bnerror;
	pgpAssert(!i);	/* p and q had better be relatively prime! */

	/* And finally,  n = p * q */
	if (bnMul(&sec->s.n, &sec->s.p, &sec->s.q) < 0)
		goto bnerror;

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

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

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

	goto done;

bnerror:
	bnEnd(&sec->s.n);
	bnEnd(&sec->s.e);
	bnEnd(&sec->s.d);
	bnEnd(&sec->s.p);
	bnEnd(&sec->s.q);
	bnEnd(&sec->s.u);
	/* 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(&t);
	return seckey;
}

#endif /* PGP_RSA_KEYGEN */


#endif /* PGP_RSA */

⌨️ 快捷键说明

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