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

📄 pgpeckey.c

📁 可以实现对邮件的加密解密以及签名
💻 C
📖 第 1 页 / 共 5 页
字号:
		if (8*scalarSize == bnBits(&r))
			len_seq = pgpBnX509LenLen(scalarSize+1) + 1 + scalarSize+1;
		else
			len_seq = pgpBnX509LenLen(scalarSize) + 1 + scalarSize;
		if (8*scalarSize == bnBits(&s))
			len_seq += pgpBnX509LenLen(scalarSize+1) + 1 + scalarSize+1;
		else
			len_seq += pgpBnX509LenLen(scalarSize) + 1 + scalarSize;
		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, scalarSize, format);
	t += pgpBnPutFormatted(&s, sig+t, scalarSize, format);
	if (siglen)
		*siglen = (PGPSize)t;

	i = 0;
	goto done;

nomem:
	i = kPGPError_OutOfMemory;
	/* fall through */
done:
	bnEnd(&k);
	bnEnd(&bn);
	bnEnd(&s);
	bnEnd(&r);
	bnEnd(&bnx);
	bnEnd(&bnorder);
	if( IsntNull( eck ) )
		ecScalarFree( eck );
	if( IsntNull( kg ) )
		ecPointFree( kg );
	if( IsntNull( rc2 ) ) {
		pgpRandomDestroy(rc2);
	}
	return i;

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


/*
 * Re-encrypt a PGPSecKey to turn 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 EC)
 * The following:
 *  0      2    Curve type (=0)
 *  2      2+s  Curve name (s=strlen(name))
 * 4+s     2+p  Public curve point (p=pointSize)
 * 6+s+p   e    Encryption algorithm data, S2K info
 * 6+s+p+e 2+w  MPI for x, secret part (w=scalarSize)
 * 8+s+p+e+w
 *
 */

#if PGP_MACINTOSH
#pragma global_optimizer on
#endif
static int
ecChangeLock(PGPSecKey *seckey, PGPEnv const *env, 
	PGPRandomContext const *rc, char const *ophrase, PGPSize oplen,
	PGPBoolean oHashedPhrase, char const *phrase, PGPSize plen,
	PGPStringToKeyType s2ktype)
{
	ECsecPlus *sec = (ECsecPlus *)seckey->priv;
	ecContextRef ec = sec->s.ec;
	PGPUInt32 coordSize, scalarSize, pointSize;
	PGPStringToKey *s2k = NULL;	/* Shut up warnings */
	PGPCipherVTBL const *cipher = NULL;	/* Shut up warnings */
	PGPCFBContext *cfb = NULL;	/* This is realy needed */
	BigNum bnx, bny;
	PGPByte *p;
	PGPByte key[PGP_CIPHER_MAXKEYSIZE];
	PGPBoolean oldf = 0;				/* Shut up warnings */
	PGPInt32 curve;
	PGPSize len;
	PGPSize namelen;
	PGPUInt32 checksum;
	PGPContextRef context = pgpenvGetContext( env );
	PGPMemoryMgrRef	mgr	= PGPPeekContextMemoryMgr( seckey->context );
	
	ASSERTEC(seckey->pkAlg);
	if (sec->locked)
		if( IsPGPError(ecUnlock( seckey, ophrase, oplen, oHashedPhrase )) )
			return kPGPError_KeyIsLocked;

	ecGetBufferSize( ec, &coordSize, &scalarSize, NULL, &pointSize );

	curve = sCurveIndexFromScalarsize( scalarSize );
	pgpAssert( curve >= 0 );
	namelen = strlen(sCurves[curve].name);

	bnBegin( &bny, mgr, INSECURE );
	bnBegin( &bnx, mgr, INSECURE );

	sPointtoBN( sec->s.y, &bny, mgr, pointSize );
	sScalartoBN( sec->s.x, &bnx, mgr, scalarSize );

	len = 11 + namelen + bnBytes(&bny) + bnBytes(&bnx);

	if (phrase) {
		s2k = pgpS2Kcreate(context, rc, s2ktype);
		if (!s2k) {
			bnEnd( &bnx );
			bnEnd( &bny );
			return kPGPError_OutOfMemory;
		}
		cipher = pgpCipherDefaultKey(env);
		pgpAssert(cipher);
		if (!cipher) {
			bnEnd( &bnx );
			bnEnd( &bny );
			pgpS2Kdestroy(s2k);
			return kPGPError_OutOfMemory;
		}
		len += cipher->blocksize;
		cfb = pgpCFBCreate( mgr, cipher);
		if (!cfb) {
			bnEnd( &bnx );
			bnEnd( &bny );
			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 ) ) {
			bnEnd( &bnx );
			bnEnd( &bny );
			PGPFreeCFBContext(cfb);
			pgpS2Kdestroy(s2k);
			return err;
		}
		sec->ckalloc = (PGPSize)len;
	}
	sec->cklen = len;
	p = sec->cryptkey;

	/* Okay, no more errors possible!   Start installing data */
	
	*p++ = 0;
	*p++ = 0;

	/* Assume namelen has 2nd to highest bit set, typical of ascii */
	*p++ = ((8*namelen-1) >> 8) & 0xff;
	*p++ = ((8*namelen-1) >> 0) & 0xff;
	pgpCopyMemory( sCurves[curve].name, p, namelen );
	p += namelen;

	p += pgpBnPutPlain(&bny, p);

	/* Encryption parameters */
	if (!phrase) {
		*p++ = 0;	/* Unencrypted */
	} else {
		if (oldf) {
			*p++ = cipher->algorithm;
		} else {
			*p++ = 0xff;
			*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 += pgpBnPut(&bnx, p, cfb, &checksum, FALSE);
	pgpChecksumPut(checksum, p, cfb, FALSE);
	p += 2;
	pgpAssert((ptrdiff_t)len == p - sec->cryptkey);

	if (cfb)
		PGPFreeCFBContext(cfb);
	bnEnd(&bnx);
	bnEnd(&bny);

	return 0;	/* Success */
}
#if PGP_MACINTOSH
#pragma global_optimizer reset
#endif

static PGPSize
ecSecBufferLength(PGPSecKey const *seckey)
{
	ECsecPlus const *sec = (ECsecPlus *)seckey->priv;

	return sec->cklen;
}

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

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


static int
ecSecParams(PGPSecKey const *seckey,
	BigNum *x1, BigNum *x2, BigNum *x3, BigNum *x4, BigNum *x5, BigNum *x6,
	BigNum *x7, BigNum *x8)
{
	ECsecPlus const *sec = (ECsecPlus *)seckey->priv;

	ASSERTEC( seckey->pkAlg );
	pgpAssert( !sec->locked );
	(void) sec;
	(void) x1;
	(void) x2;
	(void) x3;
	(void) x4;
	(void) x5;
	(void) x6;
	(void) x7;
	(void) x8;
	return kPGPError_PublicKeyUnimplemented;
}


/* Fill in secret key structure */
static void
ecFillSecKey(PGPSecKey *seckey, ECsecPlus *sec)
{
	seckey->pkAlg	            = kPGPPublicKeyAlgorithm_ECSign;
	seckey->priv	            = sec;
	seckey->destroy             = ecSecDestroy;
	seckey->pubkey              = ecPubkey;
	seckey->islocked            = ecIslocked;
	seckey->lockingalgorithm    = ecLockingAlgorithm;
	seckey->s2ktype             = ecS2KType;
	seckey->convertpassphrase   = ecConvertPassphrase;
	seckey->unlock              = ecUnlock;
	seckey->lock                = ecLock;
	seckey->decrypt             = ecDecrypt;
	seckey->maxdecrypted        = ecSecMaxdecrypted;
	seckey->maxsig              = ecSecMaxsig;
	seckey->maxesk              = ecSecMaxesk;
	seckey->sign                = ecSign;
	seckey->changeLock          = ecChangeLock;
	seckey->bufferLength        = ecSecBufferLength;
	seckey->toBuffer            = ecSecToBuffer;
	seckey->secparams			= ecSecParams;
	seckey->setkeyid			= ecSecSetKeyID;
}


PGPSecKey *
ecSecFromBuf(
	PGPContextRef	context,
	PGPByte const *	buf,
	PGPSize			size,
	PGPError *		error)
{
	PGPSecKey *seckey;
	ECsecPlus *sec;
	PGPByte *cryptk;
	PGPError	err	= kPGPError_OutOfMemory;
	PGPMemoryMgrRef		mgr	= PGPPeekContextMemoryMgr( context );

	bnInit();
	cryptk = (PGPByte *)pgpContextMemAlloc(context,
		size, kPGPMemoryMgrFlags_Clear);
	if (cryptk) {
		sec = (ECsecPlus *)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);
				sec->cryptkey = cryptk;
				sec->cklen = sec->ckalloc = size;
				sec->locked = 1;
				/* We only need this to try unlocking... */
				seckey->pkAlg = kPGPPublicKeyAlgorithm_ECSign;
				seckey->priv = sec;
				
				if (ecUnlock(seckey, NULL, 0, FALSE) >= 0) {
					ecFillSecKey(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 EC secret key with prime of the specified number of bits.
 * We only support the pre-computed sizes, with fixed curves.
 * Make callbacks to progress function periodically.
 * Secret key is returned in the unlocked form, with no passphrase set.
 * fastgen has no effect.
 */
PGPSecKey *
ecSecGenerate(
	PGPContextRef	context,
	unsigned bits, PGPBoolean fastgen,
	PGPRandomContext const *rc,
	int progress(void *arg, int c), void *arg, PGPError *error)
{
	PGPSecKey *seckey	= NULL;
	ECsecPlus *sec;
	BigNum bnorder, bnx;
	ecContextRef ec = NULL;
	PGPInt32 curve;
	PGPUInt32 coordSize, scalarSize, pointSize;
	PGPByte *xbuf = NULL;
	PGPMemoryMgrRef		mgr	= PGPPeekContextMemoryMgr( context );
	PGPEnv *			pgpEnv = pgpContextGetEnvironment( context );

	(void) fastgen;

	*error = kPGPError_NoErr;

	curve = sCurveIndexFromBitsize( bits );
	if( curve < 0 )
	{
		*error = kPGPError_BadParams;
		return NULL;
	}

	/* Initialize local pointers (simplify cleanup below) */
	seckey = NULL;
	sec = NULL;
	
	/* Allocate data structures */
	seckey = (PGPSecKey *)pgpContextMemAlloc( context,
		sizeof(*seckey), kPGPMemoryMgrFlags_Clear);
	if (!seckey)
		goto memerror;
	seckey->context	= context;
	sec = (ECsecPlus *)PGPNewSecureData( mgr, sizeof(*sec), 0 );
	if (!sec)
		goto memerror;
	pgpClearMemory( sec, sizeof(*sec) );
	sec->context	= context;
	
	bnBegin( &bnorder, mgr, INSECURE );
	bnBegin( &bnx, mgr, SECURE );

	if( ecCreate2mContext( mgr, sCurves[curve].bitsize,
						   EC_MEM_USAGE_HIGH, &sec->s.ec ) < 0 )
		goto memerror;
	ec = sec->s.ec;

	ecSetEC2mParamAInt( ec, sCurves[curve].a );
	ecSetEC2mParamB( ec, sCurves[curve].b );

	ecGetBufferSize( ec, &coordSize, &scalarSize, NULL, &pointSize );

	if( ecPointCreate( ec, &sec->s.y ) < 0
		|| ecPointCreate( ec, &sec->s.g ) < 0
		|| ecScalarCreate( ec, &sec->s.order, INSECURE ) < 0
		|| ecScalarCreate( ec, &sec->s.x, SECURE ) < 0 )
		goto memerror;
	sec->s.cofactor = sCurves[curve].cofactor;

	/* Use fixed field and generator */
	if ( ecPointInsertBytes( sec->s.g, sCurves[curve].g, 0 ) < 0
		|| bnInsertBigBytes( &bnorder, sCurves[curve].order,
							 0, scalarSize ) < 0
		|| sBNtoScalar( &bnorder, sec->s.order, mgr, scalarSize ) < 0 )
		goto memerror;

	/* Choose the random x scalar for the secret key */
	xbuf = PGPNewSecureData( mgr, scalarSize+8, 0 );
	if( IsNull( xbuf ) )
		goto memerror;
	pgpRandomGetBytes( rc, xbuf, scalarSize+8 );
	if( bnInsertBigBytes( &bnx, xbuf, 0, scalarSize+8 ) < 0
		|| bnMod( &bnx, &bnx, &bnorder ) < 0
		|| sBNtoScalar( &bnx, sec->s.x, mgr, scalarSize ) < 0 )
		goto memerror;

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

	/* And calculate x*g as public key */
	if( ecPointMul( sec->s.g, sec->s.x, FALSE, sec->s.y ) < 0 )
		goto memerror;

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

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

	/* Fill in cryptkey structure, unencrypted */
	if( ecChangeLock (seckey, pgpEnv, NULL, NULL, 0, FALSE, NULL, 0,
					  kPGPStringToKey_Simple) < 0 )
		goto memerror;

	goto done;

memerror:
	if ( IsntNull( seckey ) )
		pgpContextMemFree( context, seckey);
	if ( IsntNull( sec ) ) {
		if( IsntNull( sec->s.y ) )
			ecPointFree( sec->s.y );
		if( IsntNull( sec->s.g ) )
			ecPointFree( sec->s.g );
		if( IsntNull( sec->s.x ) )
			ecScalarFree( sec->s.x );
		if( IsntNull( sec->s.order ) )
			ecScalarFree( sec->s.order );
		PGPFreeData( sec );			/* Wipes as it frees */
	}
	if( IsntNull( ec ) )
		ecFreeContext( ec );
	seckey = NULL;
	*error = kPGPError_OutOfMemory;
	/* Fall through */
done:
	bnEnd( &bnorder );
	bnEnd( &bnx );
	if( IsntNull( xbuf ) )
		PGPFreeData( xbuf );

	return seckey;
}


#endif /* PGP_EC */

⌨️ 快捷键说明

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