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

📄 pgpkeymisc.c

📁 可以实现对邮件的加密解密以及签名
💻 C
📖 第 1 页 / 共 3 页
字号:
			pgpClearMemory( tmp,  sizeof(tmp));
			return kPGPError_OutOfMemory;
		}

		/* Checksum */
		if (state)
			PGPContinueHash( state, tmp, l );
	}
	pgpClearMemory( tmp,  sizeof(tmp));

	return (int)t+2;
}

/* 
 * Read checksum (as computed above) or hash (SHA1) from the buffer
 * for comparison. Input data can be encrypted, in this case cfb 
 * object must be provided. 
 *
 * alg0 is the first octet indicating string-to-key 
 * usage conventions from Section 5.5.3 Secret Key Packet Formats, RFC 2440.
 *
 * Returns number of bytes it reads from buf or writes into out.
 * Can be called with everything but alg0 set to NULL to get the checksum length.
 */
unsigned
pgpChecksumGet(PGPByte const *buf, PGPCFBContext *cfb, PGPByte alg0, 
			   PGPHashContextRef state, PGPByte *out)
{
	PGPSize hashSize = 0; 

	pgpAssert( state );
	PGPGetHashSize( state, &hashSize );

	if( out!=NULL )  {	
		if (alg0==0 || !cfb) {
			out[0] = buf[0];
			out[1] = buf[1];
		} else {
			pgpCFBDecryptInternal(cfb, buf, hashSize, out);
		}
	}

	return hashSize;
}

/*
 * Convert an MPI to a big-endian byte buffer, with a length prefix.
 * Returns number of bytes put into buffer.
 */
unsigned
pgpBnPutPlain(BigNum const *bn, PGPByte *buf)
{
	unsigned t;

	t = bnBits(bn);
	buf[0] = (PGPByte)(t>>8 & 255);
	buf[1] = (PGPByte)(t & 255);
	t = (t+7)/8;
	bnExtractBigBytes(bn, buf+2, 0, t);
	return t+2;
}

/*
 * Convert an MPI to a big-endian byte buffer.  PGP format uses a
 * length prefix.
 * Returns number of bytes put into buffer.
 */
unsigned
pgpBnPutFormatted(BigNum const *bn, PGPByte *buf,
	unsigned modbytes, PGPPublicKeyMessageFormat format)
{
	unsigned extra = 0;

	if (format == kPGPPublicKeyMessageFormat_PGP) {
		return pgpBnPutPlain( bn, buf );
	}

	if (format == kPGPPublicKeyMessageFormat_X509) {
		/* Insert integer prefix in DER encoding */
		PGPUInt32 lenlen;
		PGPUInt32 len;
		if (bnBits(bn) == 8*modbytes)
			modbytes += 1;
		len = modbytes;
		*buf++ = X509_TAG_INTEGER;
		++extra;
		lenlen = pgpBnX509LenLen(len);
		if (--lenlen == 0) {
			*buf++ = len;
			++extra;
		} else {
			*buf++ = 0x80 | lenlen;
			++extra;
			len <<= 8 * (4-lenlen);
			while (lenlen--) {
				*buf++ = (PGPByte)(len >> 24);
				++extra;
				len <<= 8;
			}
		}
	}
	bnExtractBigBytes(bn, buf, 0, modbytes);
	return modbytes + extra;
}

/*
 * Helper function for ChangeLock.
 * Convert an MPI to a big-endian byte buffer, with optional encryption and
 * checksums.  Accepts cfb == NULL to mean "unencrypted".
 * Returns number of bytes put into buffer.
 */
unsigned
pgpBnPut(BigNum const *bn, PGPByte *buf,
	PGPCFBContext *cfb, unsigned *checksump, int old)
{
	unsigned t, u;

	t = pgpBnPutPlain(bn, buf);
	if (checksump)
		for (u = 0; u < t; u++)
			*checksump += buf[u];
	if (cfb) {
		if (old) {
			PGPCFBSync(cfb);
			pgpCFBEncryptInternal(cfb, buf+2, t-2, buf+2);
		} else {
			pgpCFBEncryptInternal(cfb, buf, t, buf);
		}
	}
	return t;
}

/*
 * Write the 2-byte simple checksum (as computed above) to the
 * buffer for comparison.  Old-style is unencrypted, new-style is
 * encrypted.
 */
void
pgpChecksumPut(unsigned checksum, PGPByte *buf, PGPCFBContext *cfb,
	int old)
{
	buf[0] = (PGPByte)(checksum>>8 & 255);
	buf[1] = (PGPByte)(checksum & 255);
	if (cfb && !old)
		pgpCFBEncryptInternal(cfb, buf, 2, buf);
}

#if 0
/*
 * Write the checksum or hash to the buffer for comparison. 
 * Old-style is unencrypted and indicated by passing NULL as cfb.
 */
unsigned pgpChecksumPutEx( const PGPByte *checksum, PGPByte *buf, PGPCFBContext *cfb, PGPByte alg0 )  
{
	unsigned size = pgpChecksumGetEx(NULL, NULL, alg0, NULL);

	if (cfb != NULL)
		pgpCFBEncryptInternal(cfb, checksum, size, buf);
	else
		pgpCopyMemory( checksum, buf, size );
	return size;
}
#endif

/*
 * Generate a random bignum of the specified length, with the given
 * high and low 8 bits. "High" is merged into the high 8 bits of the
 * number.  For example, set it to 0x80 to ensure that the number is
 * exactly "bits" bits long (i.e. 2^(bits-1) <= bn < 2^bits).
 * "Low" is merged into the low 8 bits.  For example, set it to
 * 1 to ensure that you generate an odd number.
 */
int
pgpBnGenRand(BigNum *bn, PGPRandomContext const *rc,
	     unsigned bits, PGPByte high, PGPByte low, unsigned effective)
{
	unsigned char buf[64];
	unsigned bytes;
	unsigned l;
	unsigned leffective;
	int err;

	bnSetQ(bn, 0);

	/* Get high random bits */
	bytes = (bits+7) / 8;
	l = bytes < sizeof(buf) ? bytes : sizeof(buf);
	leffective = pgpMin(l*8, effective);
	pgpRandomGetBytesEntropy(rc, buf, l, leffective);
	effective -= leffective;

	/* Mask off excess high bits */
	buf[0] &= 255 >> (-(int)bits & 7);
	/* Merge in specified high bits */
	buf[0] |= high >> (-(int)bits & 7);
	if (bits & 7)
		buf[1] |= high << (bits & 7);

	for (;;) {
		bytes -= l;
		if (!bytes)	/* Last word - merge in low bits */
			buf[l-1] |= low;
		err = bnInsertBigBytes(bn, buf, bytes, l);
		if (!bytes || err < 0)
			break;
		l = bytes < sizeof(buf) ? bytes : sizeof(buf);
		leffective = pgpMin(l*8, effective);
		pgpRandomGetBytesEntropy(rc, buf, l, leffective);
		effective -= leffective;
	}

	/* Burn and return */
	pgpClearMemory( buf,  sizeof(buf));
	return err;
}

/*
 * Parse a buffer containing n mpi format numbers (two bytes of length in bits,
 * followed by data).  Make sure data is well formed and doesn't exceed
 * buffer length.  Take n pointers to offsets where the n numbers start
 * (pointers may be null but must not be left off arg list).
 * Return offset past last value, or negative for error.
 */
int
pgpBnParse(PGPByte const *buf, unsigned size, int n, ...)
{
	va_list ap;
	unsigned nb;
	unsigned off;
	unsigned *poff;

	va_start (ap, n);
	if (size < 2U*n)
		return kPGPError_KeyPacketTruncated;
	off = 0;
	while (n--) {
		poff = va_arg(ap, unsigned *);
		nb = ((unsigned)buf[0+off] << 8) + buf[1+off];
		if (!nb || buf[2+off] >> ((nb-1) & 7) != 1)
			return kPGPError_MalformedKeyComponent; /* Bad bit length */
		nb = (nb+7)/8;
		/* Need nb+2 bytes for this, plus 2*n for remainder */
		if (size-off < nb + 2 + 2*n)
			return kPGPError_KeyPacketTruncated;
		if (poff)
			*poff = off;
		off += nb+2;
	}
	va_end (ap);
	return off;
}

/*
 * Given a cipher algorithm descriptor in (buf,len) and a passphrase,
 * initialize the passed-in PGPCFBContext pointer and return the
 * number of bytes of descriptor used, or <0 on error.  (In which
 * case *cfbp is NULL.)  If hashedPhrase is true, the passphrase has
 * already been hashed using the s2k object and we use it literally
 * as the key.
 */
int
pgpCipherSetup(
PGPByte const *buf, unsigned len, char const *phrase, PGPSize plen,
	PGPBoolean hashedPhrase, PGPBoolean twofishRetry, PGPContextRef context,
	PGPCFBContext **cfbp)
{
	PGPCipherVTBL const *cipher;
	PGPStringToKey *s2k;
	unsigned alg;
	int alglen;
	PGPByte key[PGP_CIPHER_MAXKEYSIZE];

	/* Sanity check on lengths, otherwise we take forever */
	pgpAssert( plen < 0x10000U );
	pgpAssert( len < 0x10000U );

	/* First things first, in case of error... */
	*cfbp = NULL;

	if (len < 1)
		return kPGPError_KeyPacketTruncated;

	alg = buf[0] & 255;

	if (!alg)	/* The key isn't encrypted; just read it in */
		return 1;

	if (alg == 0xff || alg == 0xfe) {
		/* New style, with a separate string-to-key */

		if (len == 1)
			return kPGPError_KeyPacketTruncated;
		alg = buf[1];
		alglen = pgpS2Kdecode(&s2k, context, buf+2, len-2);
		if (alglen < 0)
			return alglen;
		alglen += 2;
		if (len < (unsigned)alglen)
			return kPGPError_KeyPacketTruncated;
	} else {
		/* Old-style string-to-key */
		s2k = pgpS2Ksimple(context, pgpHashByNumber(kPGPHashAlgorithm_MD5));
		if (!s2k)
			return kPGPError_OutOfMemory;
		alglen = 1;
	}
	if( alg == kPGPCipherAlgorithm_Twofish256 && twofishRetry )
	{
		/* Had a mis-implementation of Twofish on bigendian machines, so for
		 * backwards compatibility we must retry unlocking failures using
		 * the old, bad algorithm
		 */
		alg = kPGPCipherAlgorithm_BadTwofish256;
	}
	/* Okay now, do the conversion */
	cipher = pgpCipherGetVTBL( (PGPCipherAlgorithm)alg);
	if (!cipher) {
		pgpS2Kdestroy(s2k);
		return kPGPError_BadCipherNumber;
	}
	if (len < alglen + cipher->blocksize) {
		pgpS2Kdestroy(s2k);
		return kPGPError_KeyPacketTruncated;
	}
	*cfbp = pgpCFBCreate( PGPPeekContextMemoryMgr( context ), cipher);
	if (!*cfbp) {
		pgpS2Kdestroy(s2k);
		return kPGPError_OutOfMemory;
	}
	pgpAssert(cipher->keysize <= sizeof(key));
	if (hashedPhrase) {
		pgpCopyMemory (phrase, key, plen);
	} else {
		pgpStringToKey(s2k, phrase, plen, key, cipher->keysize);
	}
	PGPInitCFB(*cfbp, key, buf + alglen);
	pgpClearMemory( key,  sizeof(key));
	pgpS2Kdestroy(s2k);

	return alglen + cipher->blocksize;
}


/*
 * Helper function: seed a RandomContext from a BigNum.
 * Be very sure to leave nothing in memory!
 */
void
pgpRandomBnSeed(PGPRandomContext const *rc, BigNum const *bn)
{
	PGPByte buf[32];	/* Big enough for 99.9% of all keys */
	unsigned bytes = (bnBits(bn) + 7)/8;
	unsigned off = 0;

	while (bytes > sizeof(buf)) {
		bnExtractLittleBytes(bn, buf, off, sizeof(buf));
		pgpRandomAddBytes(rc, buf, sizeof(buf));
		bytes -= sizeof(buf);
		off += sizeof(buf);
	}
	bnExtractLittleBytes(bn, buf, off, bytes);
	pgpRandomAddBytes(rc, buf, bytes);

	pgpClearMemory( buf,  sizeof(buf));
}

⌨️ 快捷键说明

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