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

📄 pgpmsrsaglue.c

📁 vc环境下的pgp源码
💻 C
📖 第 1 页 / 共 2 页
字号:
{
	HCRYPTPROV hProv = 0;
	HCRYPTKEY hDummy = 0;
	HCRYPTKEY hKey = 0;
	HCRYPTKEY hSession = 0;
	PUBLICKEYBLOBHDR *rpubk = NULL;
	SIMPLEBLOBHDR *rsesk = NULL;
	PGPUInt32 rpubksize;
	PGPUInt32 rsesksize;
	PGPByte *rseskdata;
	PGPMemoryMgrRef mgr = pub->n.mgr;
	PGPError err = kPGPError_NoErr;

	/* Set the return number to 0 to start */
	(void)bnSetQ(bn, 0);

	if (!(pgpCAPIuse() & PGP_PKUSE_ENCRYPT))
		return kPGPError_PublicKeyUnimplemented;

	/* Get handle to the enhanced PROV_RSA_FULL provider */
	/* Use our reserved container name, always start with an empty one */
	ex.CryptAcquireContext(&hProv, PGPCONTAINER, MS_ENH_PROV, PROV_RSA_FULL,
						CRYPT_DELETEKEYSET);
	if(!ex.CryptAcquireContext(&hProv, PGPCONTAINER, MS_ENH_PROV,
						PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
		err = kPGPError_PublicKeyUnimplemented;
		goto error;
	}

	/* Initialize CAPI public key structure */
	rpubksize = rpubk_size (pub);

	rpubk = PGPNewData (mgr, rpubksize, 0);
	if (IsNull (rpubk)) {
		err = kPGPError_OutOfMemory;
		goto error;
	}

	rpubk_init(rpubk, pub);

	/* Create dummy key for importing session key */
	if (!ex.CryptImportKey (hProv, (BYTE *)&dummyKeyBlob,
						sizeof(dummyKeyBlob), 0, 0, &hDummy)) {
		err = kPGPError_PublicKeyUnimplemented;
		goto error;
	}

	/* Initialize and import session key */
	rsesksize = rsesk_size (DUMMYBITS);

	rsesk = PGPNewSecureData (mgr, rsesksize, 0);
	if (IsNull (rsesk)) {
		err = kPGPError_OutOfMemory;
		goto error;
	}
							
	rsesk_initfrom_buf (rsesk, in, len, DUMMYBITS, mgr, rc);

	if (!ex.CryptImportKey (hProv, (BYTE *)rsesk, rsesksize, hDummy,
						 CRYPT_EXPORTABLE, &hSession)) {
		err = kPGPError_PublicKeyUnimplemented;
		goto error;
	}
	PGPFreeData (rsesk);
	rsesk = NULL;

	/* Export session key now encrypted with user's public key */
	if (!ex.CryptImportKey (hProv, (BYTE *)rpubk, rpubksize, 0, 0, &hKey)) {
		err = kPGPError_PublicKeyUnimplemented;
		goto error;
	}

	/* CAPI ovewrites more data than it should with nonstandard key sizes */
	rsesksize = sizeof(*rsesk) + MULOF(bnBytes(&pub->n), 8);
	rsesk = (SIMPLEBLOBHDR *)PGPNewData (mgr, rsesksize, 0);
	if (!rsesk) {
		err = kPGPError_OutOfMemory;
		goto error;
	}

	pgpAssert (sizeof(rsesksize) == sizeof(DWORD));
	if (!ex.CryptExportKey (hSession, hKey, SIMPLEBLOB, 0, (BYTE *)rsesk,
						   &rsesksize)) {
		err = kPGPError_PublicKeyUnimplemented;
		goto error;
	}
	pgpAssert (rsesksize == sizeof(*rsesk) + bnBytes(&pub->n));

	/* Return in PGP bn format */
	rseskdata = (PGPByte *)rsesk + sizeof(*rsesk);
	bnInsertLittleBytes(bn, rseskdata, 0, bnBytes(&pub->n));

error:

	if (hSession)
		ex.CryptDestroyKey (hSession);
	if (hKey)
		ex.CryptDestroyKey (hKey);
	if (hDummy)
		ex.CryptDestroyKey (hDummy);

	ex.CryptReleaseContext(hProv, 0);
	ex.CryptAcquireContext(&hProv, PGPCONTAINER, MS_ENH_PROV, PROV_RSA_FULL,
							CRYPT_DELETEKEYSET);

	if (rsesk) {
		pgpClearMemory (rsesk, rsesksize);
		PGPFreeData (rsesk);
	}
	if (rpubk) {
		pgpClearMemory (rpubk, rpubksize);
		PGPFreeData (rpubk);
	}

	return err;
}



/*
 * Performs an RSA decryption.  Returns a prefix of the unwrapped
 * data in the given buf.  Returns the length of the untruncated
 * data, which may exceed "len". Returns <0 on error.
 */
int
rsaPrivateDecrypt(PGPByte *outbuf, unsigned len, BigNum *bn,
	RSAsec const *sec)
{
	HCRYPTPROV hProv = 0;
	HCRYPTKEY hDummy = 0;
	HCRYPTKEY hKey = 0;
	HCRYPTKEY hSession = 0;
	PRIVATEKEYBLOBHDR *rprivk = NULL;
	SIMPLEBLOBHDR *rsesk = NULL;
	PGPUInt32 rprivksize;
	PGPUInt32 rsesksize;
	PGPByte *rseskdata;
	PGPMemoryMgrRef	mgr	= bn->mgr;
	PGPError err = kPGPError_NoErr;
	BigNum bnsk;

	if (!(pgpCAPIuse() & PGP_PKUSE_ENCRYPT))
		return kPGPError_PublicKeyUnimplemented;

	/* CAPI has bugs with keys not mult of 64 bits */
	if ((bnBytes(bn) % 8) != 0)
		return kPGPError_CAPIUnsupportedKey;
		
	/* Get handle to the enhanced PROV_RSA_FULL provider */
	/* Use our reserved container name, always start with an empty one */
	ex.CryptAcquireContext(&hProv, PGPCONTAINER, MS_ENH_PROV, PROV_RSA_FULL,
						CRYPT_DELETEKEYSET);
	if(!ex.CryptAcquireContext(&hProv, PGPCONTAINER, MS_ENH_PROV,
						PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
		err = kPGPError_PublicKeyUnimplemented;
		goto error;
	}

	/* Initialize and import private key structure */
	rprivksize = rprivk_size (sec);
	rprivk = PGPNewSecureData (mgr, rprivksize, 0);
	if (IsNull (rprivk)) {
		err = kPGPError_OutOfMemory;
		goto error;
	}
	rprivk_init(rprivk, sec, mgr, FALSE);

	if (!ex.CryptImportKey (hProv, (BYTE *)rprivk, rprivksize, 0, 0, &hKey)) {
		err = kPGPError_PublicKeyUnimplemented;
		goto error;
	}

	/* Create SIMPLEBLOB from encrypted session key in bn */
	rsesksize = rsesk_size (bnBits(&sec->n));

	rsesk = PGPNewData (mgr, rsesksize, 0);
	if (IsNull (rsesk)) {
		err = kPGPError_OutOfMemory;
		goto error;
	}
	rsesk_initfrom_bn (rsesk, bn, bnBits(&sec->n));

	/* Import the blob, decrypting it with the private key */
	if (!ex.CryptImportKey (hProv, (BYTE *)rsesk, rsesksize, hKey,
						 CRYPT_EXPORTABLE, &hSession)) {
		err = kPGPError_PublicKeyUnimplemented;
		goto error;
	}
	PGPFreeData (rsesk);
	rsesk = NULL;

	/* Create a dummy key suitable for clearly exporting the session key */
	if (!ex.CryptImportKey (hProv, (BYTE *)&dummyKeyBlob,
						   sizeof(dummyKeyBlob), 0, 0, &hDummy)) {
		err = kPGPError_PublicKeyUnimplemented;
		goto error;
	}

	/* Export session key in the clear as a PKCS1 formatted SIMPLEBLOB */
	rsesksize = sizeof (*rsesk) + DUMMYBITS/8;
	rsesk = PGPNewData (mgr, rsesksize, 0);
	if (IsNull (rsesk)) {
		err = kPGPError_OutOfMemory;
		goto error;
	}

	pgpAssert (sizeof(rsesksize) == sizeof(DWORD));
	if (!ex.CryptExportKey (hSession, hDummy, SIMPLEBLOB, 0, (BYTE *)rsesk,
						   &rsesksize)) {
		err = kPGPError_PublicKeyUnimplemented;
		goto error;
	}
	pgpAssert (rsesksize == sizeof(*rsesk) + DUMMYBITS/8);

	/* Unpack PKCS formatted exported session key and return it */
	rseskdata = (PGPByte *)rsesk + sizeof(*rsesk);
	bnBegin (&bnsk, mgr, TRUE);
	bnInsertLittleBytes (&bnsk, rseskdata, 0, DUMMYBITS/8);
	err = (PGPError) pgpPKCSUnpack(outbuf, len, &bnsk, PKCS_PAD_ENCRYPTED,
								   DUMMYBITS/8);
	bnEnd (&bnsk);

error:

	if (hSession)
		ex.CryptDestroyKey (hSession);
	if (hKey)
		ex.CryptDestroyKey (hKey);
	if (hDummy)
		ex.CryptDestroyKey (hDummy);

	ex.CryptReleaseContext(hProv, 0);
	ex.CryptAcquireContext(&hProv, PGPCONTAINER, MS_ENH_PROV, PROV_RSA_FULL,
							CRYPT_DELETEKEYSET);

	if (rsesk) {
		pgpClearMemory (rsesk, rsesksize);
		PGPFreeData (rsesk);
	}
	if (rprivk) {
		pgpClearMemory (rprivk, rprivksize);
		PGPFreeData (rprivk);
	}

	return err;
}



/*
 * Do an RSA signing operation using the secret key on the specified hash
 */
int
rsaSignHash(BigNum *bn, RSAsec const *sec, PGPHashVTBL const *h,
	PGPByte const *hash)
{
	HCRYPTPROV hProv = 0;
	HCRYPTKEY hKey = 0;
	HCRYPTHASH hHash = 0;
	PRIVATEKEYBLOBHDR *rprivk = NULL;
	ALG_ID capihashalg;
	PGPUInt32 rprivksize;
	PGPByte *sigbuf = NULL;
	PGPUInt32 sigsize;
	PGPMemoryMgrRef	mgr	= bn->mgr;
	PGPError err = kPGPError_NoErr;

	/* SET the return number to 0 to start */
	(void)bnSetQ(bn, 0);

	if (!(pgpCAPIuse() & PGP_PKUSE_SIGN))
		return kPGPError_PublicKeyUnimplemented;

	/* CAPI has bugs with keys not mult of 64 bits */
	if ((bnBytes(&sec->n) % 8) != 0)
		return kPGPError_CAPIUnsupportedKey;
		
	/* Get handle to the base PROV_RSA_FULL provider */
	/* Use our reserved container name, always start with an empty one */
	ex.CryptAcquireContext(&hProv, PGPCONTAINER, MS_DEF_PROV, PROV_RSA_FULL,
						CRYPT_DELETEKEYSET);
	if(!ex.CryptAcquireContext(&hProv, PGPCONTAINER, MS_DEF_PROV,
							PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
		err = kPGPError_PublicKeyUnimplemented;
		goto error;
	}

	/* Determine what hash algorithm to use */
	if (h->algorithm == kPGPHashAlgorithm_MD5) {
		capihashalg = CALG_MD5;
	} else if (h->algorithm == kPGPHashAlgorithm_MD2) {
		capihashalg = CALG_MD2;
	} else if (h->algorithm == kPGPHashAlgorithm_SHA) {
		capihashalg = CALG_SHA;
	} else {
		err = kPGPError_PublicKeyUnimplemented;
		goto error;
	}

	/* Create and load the hash value */
	if (!ex.CryptCreateHash (hProv, capihashalg, 0, 0, &hHash)) {
		err = kPGPError_PublicKeyUnimplemented;
		goto error;
	}
	if (!ex.CryptSetHashParam (hHash, HP_HASHVAL, (BYTE *)hash, 0)) {
		err = kPGPError_PublicKeyUnimplemented;
		goto error;
	}

	/* Initialize private key structure */
	rprivksize = rprivk_size (sec);
	rprivk = PGPNewSecureData (mgr, rprivksize, 0);
	if (IsNull (rprivk)) {
		err = kPGPError_OutOfMemory;
		goto error;
	}
	rprivk_init(rprivk, sec, mgr, TRUE);

	/*
	 * Importing private key into an otherwise empty key container should
	 * make it be used as the signing key.
	 */

	if (!ex.CryptImportKey (hProv, (BYTE *)rprivk, rprivksize, 0, 0, &hKey)) {
		err = kPGPError_PublicKeyUnimplemented;
		goto error;
	}

	/* Perform the signature operation */
	sigsize = bnBytes (&sec->n);
	sigbuf = PGPNewData (mgr, sigsize, 0);
	if (IsNull (sigbuf)) {
		err = kPGPError_OutOfMemory;
		goto error;
	}

	pgpAssert (sizeof(sigsize) == sizeof(DWORD));
	if (!ex.CryptSignHash (hHash, AT_SIGNATURE, 0, 0, sigbuf, &sigsize)) {
		err = kPGPError_PublicKeyUnimplemented;
		sigsize = 0;
		goto error;
	}
	pgpAssert (sigsize = bnBytes(&sec->n));

	/* Return in PGP bn format */
	bnInsertLittleBytes(bn, sigbuf, 0, sigsize);
	
error:

	if (hKey)
		ex.CryptDestroyKey (hKey);
	if (hHash)
		ex.CryptDestroyHash (hHash);

	ex.CryptReleaseContext(hProv, 0);
	ex.CryptAcquireContext(&hProv, PGPCONTAINER, MS_ENH_PROV, PROV_RSA_FULL,
							CRYPT_DELETEKEYSET);

	if (sigbuf) {
		pgpClearMemory (sigbuf, sigsize);
		PGPFreeData (sigbuf);
	}
	if (rprivk) {
		pgpClearMemory (rprivk, rprivksize);
		PGPFreeData (rprivk);
	}

	return err;
}


/*
 * Return TRUE if the bignum holding the signature value is valid.
 */
PGPBoolean
rsaVerifyHashSignature(BigNum *bn, RSApub const *pub, PGPHashVTBL const *h,
	PGPByte const *hash)
{
	HCRYPTPROV hProv = 0;
	HCRYPTKEY hKey = 0;
	HCRYPTHASH hHash = 0;
	PUBLICKEYBLOBHDR *rpubk = NULL;
	ALG_ID capihashalg;
	PGPUInt32 rpubksize;
	PGPByte *sigbuf = NULL;
	PGPUInt32 sigsize;
	PGPMemoryMgrRef	mgr	= bn->mgr;
	PGPBoolean valid = FALSE;

	if (!(pgpCAPIuse() & PGP_PKUSE_SIGN))
		return FALSE;

	/* Get handle to the base PROV_RSA_FULL provider */
	/* Signature verification does not need a key container */

#if PGP_USECAPIFORMD2	/* [ */
	if (h->algorithm == kPGPHashAlgorithm_MD2) {
		hProv = ((HCRYPTPROV *)hash)[0];
	} else
#endif
	{
		if (!ex.CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
									CRYPT_VERIFYCONTEXT)) {
			goto error;
		}
	}

	/* Determine what hash algorithm to use */
	if (h->algorithm == kPGPHashAlgorithm_MD5) {
		capihashalg = CALG_MD5;
	} else if (h->algorithm == kPGPHashAlgorithm_MD2) {
		capihashalg = CALG_MD2;
	} else if (h->algorithm == kPGPHashAlgorithm_SHA) {
		capihashalg = CALG_SHA;
	} else {
		goto error;
	}

	/* Create and load the hash value */
#if PGP_USECAPIFORMD2	/* [ */
	if (h->algorithm == kPGPHashAlgorithm_MD2) {
		hHash = ((HCRYPTHASH *)hash)[1];
	} else
#endif /* ] */
	{
		if (!ex.CryptCreateHash (hProv, capihashalg, 0, 0, &hHash)) {
			goto error;
		}
		if (!ex.CryptSetHashParam (hHash, HP_HASHVAL, (BYTE *)hash, 0)) {
			goto error;
		}
	}

	/* Initialize and import public key structure */
	rpubksize = rpubk_size (pub);
	rpubk = PGPNewData (mgr, rpubksize, 0);
	if (IsNull (rpubk)) {
		goto error;
	}
	rpubk_init(rpubk, pub);

	if (!ex.CryptImportKey (hProv, (BYTE *)rpubk, rpubksize, 0, 0, &hKey)) {
		goto error;
	}

	/* Extract and verify signature */
	sigsize = bnBytes(&pub->n);
	sigbuf = PGPNewData (mgr, sigsize, 0);
	if (IsNull (sigbuf)) {
		goto error;
	}

	bnExtractLittleBytes(bn, sigbuf, 0, sigsize);	

	valid = ex.CryptVerifySignature (hHash, sigbuf, sigsize, hKey, 0, 0);

error:

	if (hKey)
		ex.CryptDestroyKey (hKey);
	if (hHash)
		ex.CryptDestroyHash (hHash);

	ex.CryptReleaseContext(hProv, 0);

	if (sigbuf) {
		pgpClearMemory (sigbuf, sigsize);
		PGPFreeData (sigbuf);
	}
	if (rpubk) {
		pgpClearMemory (rpubk, rpubksize);
		PGPFreeData (rpubk);
	}

	return valid;
}


#endif	/* ] PGP_USECAPIFORRSA */

⌨️ 快捷键说明

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