📄 crypto.cpp
字号:
// Copyright (C) 2005 Sean E. Covel All Rights Reserved.
//
// Created by Sean E. Covel
//
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
//
// If the source code for the program is not available from the place from
// which you received this file, check
// http://home.comcast.net/~msrc4plugin
// or
// mail: msrc4plugin@comcast.net
//
//
//
/////////////////////////////////////////////////////////////////////////////
//#include "stdafx.h"
#define _WIN32_WINNT 0x0410 //must be defined for the crypto api
#define _WIN32_WINDOWS 0x0410
#define WINVER 0x0400
#include <stdio.h>
#include <windows.h>
//#include <time.h>
//#include <tchar.h>
#include <wincrypt.h> //windows crypto api
#include "crypto.h"
#include "logging.h"
#include "utils.h"
int CSP_PROV = PROV_RSA_FULL; //Microsoft Basic/Enhanced provider
char DEFAULTKEY[KEYSize];
CHAR szUserName[100]; // Buffer to hold the name of the key container.
DWORD dwUserNameLen = 100; // Length of the buffer.
char CSP_NAME[CSP_SIZE];
DWORD VERIFY_CONTEXT_FLAG = CRYPT_VERIFYCONTEXT;
DWORD MACHINE_CONTEXT_FLAG = CRYPT_MACHINE_KEYSET; //Test for Win98 winvnc problem
DWORD NULL_CONTEXT_FLAG = 0;
DWORD CONTEXT_FLAG = CRYPT_VERIFYCONTEXT;
DWORD KEYLEN = KEYLEN_128BIT;
DWORD MAXKEYLEN = KEYLEN_128BIT; //I'm going to do something with this some day...
BOOL GenKey(char * sDefaultGenKey, DWORD keyLen)
{
//Generates the RC4 key and writes it to a file
//The key contains information about the algorithm used and
//the key length.
char GkeyFile[KEYFILENAME_SIZE];
const int IN_BUFFER_SIZE = 2048;
const int OUT_BUFFER_SIZE = IN_BUFFER_SIZE + 64; // extra padding
HANDLE hGKeyFile = 0;
BYTE pbBuffer[OUT_BUFFER_SIZE];
HCRYPTPROV hGProvider = 0;
HCRYPTKEY hGKey = 0;
HCRYPTKEY hGExchangeKey = 0;
DWORD dwByteCount;
DWORD dwBytesWritten;
long rc;
long iWinVer=0;
long iCryptVer=0;
KEYLEN = keyLen;
InitVars(CSP_NAME, &iWinVer, &iCryptVer, &MAXKEYLEN);
PrintLog((DEST,"GenKey. %d bit", (DWORD)(HIWORD(KEYLEN))));
PrintLog((DEST,"OS is '%s'",WindowsName[iWinVer]));
PrintLog((DEST,"Using provider |%s|",CSP_NAME));
PrintLog((DEST,"Max Key Length %d",(DWORD)(HIWORD(MAXKEYLEN))));
#ifdef _WITH_REGISTRY
REGISTRY *m_pREGISTRY;
m_pREGISTRY = new REGISTRY(HKEY_CURRENT_USER, MSRC4_KEY_FILE, false);
m_pREGISTRY->ReadItem(GkeyFile, KEYFILENAME_SIZE, INDEXVAL_KEYGEN, NULL);
delete m_pREGISTRY;
#else
strcpy(GkeyFile,sDefaultGenKey);
#endif
//Windows OS before 2000 won't import ExponentOfOne key in a verify context.
if (iWinVer >= WIN2000)
{
PrintLog((DEST,"Using NULL_CONTEXT"));
CONTEXT_FLAG = NULL_CONTEXT_FLAG;
szUserName[0] = '\0';
}
else
{
//PrintLog((DEST,"Using VERIFY_CONTEXT"));
//CONTEXT_FLAG = VERIFY_CONTEXT_FLAG;
PrintLog((DEST,"Using MACHINE_KEYSET"));
CONTEXT_FLAG = MACHINE_CONTEXT_FLAG;
//CONTEXT_FLAG = VERIFY_CONTEXT_FLAG;
strcpy(szUserName, CTX);
CreateContainer(szUserName);
}
rc = 0;
rc = PrepContext(iWinVer, &hGProvider);
PrintLog((DEST,"Generating key file: %s",GkeyFile));
//open both the output file
hGKeyFile = CreateFile(GkeyFile, GENERIC_WRITE, FILE_SHARE_READ,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
//check if the file created ok
if (hGKeyFile == INVALID_HANDLE_VALUE)
{
PrintLog((DEST,"Failed to create key file. "));
return false;
}
PrintLog((DEST,"Importing ExponentOfOne KeyBlob"));
//HCRYPTKEY ExponentOfOneKey = NULL;
if( !CryptImportKey(hGProvider, PrivateKeyWithExponentOfOne, sizeof(PrivateKeyWithExponentOfOne), 0, 0, &hGExchangeKey))
{
PrintLog((DEST,"Import ExponentOfOne Key failed.(GenKey)"));
return false;
}
PrintLog((DEST,"Generating random key blob"));
// Generate a random key blob
if (! CryptGenKey(hGProvider, CALG_RC4, CRYPT_EXPORTABLE + KEYLEN, &hGKey))
{
PrintLog((DEST,"CryptGenKey failed. " ));
return false;
}
// The first call to ExportKey with NULL gets the key size.
dwByteCount=0;
if (! CryptExportKey(hGKey, hGExchangeKey, SIMPLEBLOB, 0, NULL, &dwByteCount))
{
PrintLog((DEST,"CryptExportKey failed. " ));
return false;
}
if (dwByteCount == 0)
{
PrintLog((DEST,"CryptKeyLen == 0."));
return false;
}
PrintLog((DEST,"Export the key blob"));
//Generate the actual key
rc = CryptExportKey(hGKey, hGExchangeKey, SIMPLEBLOB, 0, pbBuffer,
&dwByteCount);
if (rc == 0)
{
PrintLog((DEST,"CryptExportKey2 failed. "));
return false;
}
//assertion
if (dwByteCount != BLOBSIZE)
{
PrintLog((DEST,"CryptKeyLen != BLOBSIZE."));
return false;
}
// Write the "bitness" of the key.
if (KEYLEN == 0x00800000)
{
DebugLog((DEST,"128 bit key."));
WriteFile(hGKeyFile, "128 bit", 7, &dwBytesWritten, NULL);
}
else {
if (KEYLEN == 0x00380000)
{
DebugLog((DEST,"56 bit key."));
WriteFile(hGKeyFile, " 56 bit", 7, &dwBytesWritten, NULL);
}
else
{
DebugLog((DEST,"40 bit key."));
WriteFile(hGKeyFile, " 40 bit", 7, &dwBytesWritten, NULL);
}
}
// Write size of key blob
WriteFile(hGKeyFile, &dwByteCount, sizeof(dwByteCount), &dwBytesWritten, NULL);
//Write key blob itself
WriteFile(hGKeyFile, pbBuffer, dwByteCount, &dwBytesWritten, NULL);
// Clean up: release handles
CryptDestroyKey(hGKey);
CryptDestroyKey(hGExchangeKey);
//We抮e finished using the CSP handle, so we must release it. We close the input and output files, and we抮e finished.
CryptReleaseContext(hGProvider, 0);
CloseHandle(hGKeyFile);
return true;
}
long GetCryptoVersion() {
//Determine the Crypto API version
BYTE pbData[1000];
unsigned long cbData;
HCRYPTPROV hProvider = 0;
BYTE *ptr = NULL;
DWORD version;
long rc = 0;
PrintLog((DEST,"GetCryptoVersion."));
PrintLog((DEST,"Acquiring the Crypto Context."));
// Get handle for the default provider (use RSA encryption).
PrintLog((DEST,"CryptAcquireContext |%d| |%s| |%s| |%d| |%d|",hProvider, NULL, NULL, PROV_RSA_FULL, CONTEXT_FLAG));
CryptAcquireContext(&hProvider, NULL, NULL, PROV_RSA_FULL , CONTEXT_FLAG );
if (hProvider == 0){
PrintLog((DEST,"Crypto could not acquire a Crypto Provider Context. "));
return 0;
}
else {
PrintLog((DEST,"Crypto acquired a Crypto Provider Context. "));
cbData = 1000;
rc = CryptGetProvParam(
hProvider, // handle to an open cryptographic provider
PP_VERSION, //get VERSION information
(BYTE *)&pbData, // information on the version
&cbData, // number of bytes
0); // flag for enumeration functions
if (rc != TRUE)
{
PrintLog((DEST,"CryptGetProvParam failed to return the PP_VERSION. %d",rc));
return 0;
}
}
if(!CryptReleaseContext(hProvider, 0)) {
PrintLog((DEST,"Error during CryptReleaseContext."));
return 0;
}
ptr = pbData;
version = *(DWORD *)ptr;
//version - M = major version, mm = minor version...
// 0x00000101 = Version 1.1
// Mmm Mmm
if (version < 511) //0x00000100-0x000001FF (0-511)
return 1;
// Mmm Mmm
if (version < 767) //0x00000200-0x000002FF (512-767)
return 2;
return 0;
}
BOOL InitVars(char *szCSPName, long *iWinVer, long *iCryptVer, DWORD * iMaxKey) {
//Get the windows version, crypto version, best crypto provider, and best bit-depth supported.
HCRYPTPROV hProvider = 0; // crypto provider
*iWinVer = 0;
*iCryptVer = 0;
*iMaxKey = 0;
*iWinVer = WhatWindowsVer();
PrintLog((DEST,"InitVars"));
//*iCryptVer
*iCryptVer = GetCryptoVersion();
if (*iCryptVer == 1) {
//Version 1 doesn't support anything usefull for finding bit depth and whatnot...
//I think you only see this on 95 anyway...
//*** Only on 95 without the High Encryption pack ***
//not much works with version 1.
szCSPName[0] = '\0'; //default
*iMaxKey = KEYLEN_40BIT;
}
else
{
//Version 2 has better features, but we don't want to waste a lot of time...
if (*iWinVer>= WINXP) { //XP and up come with 128bit out of the box.
szCSPName[0] = '\0'; //default
*iMaxKey = KEYLEN_128BIT;
}
else {
if (*iWinVer == WINNT) { //NT does not support GetDefaultProvider function...
//look for MS_ENHANCED_PROV
PrintLog((DEST,"CryptAcquireContext |%d| |%s| |%s| |%d| |%d|",hProvider, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT));
CryptAcquireContext(&hProvider, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
if (hProvider != 0){
strcpy(szCSPName,MS_ENHANCED_PROV);
*iMaxKey = KEYLEN_128BIT;
}
else {
szCSPName[0] = '\0';
*iMaxKey = KEYLEN_40BIT;
}
CryptReleaseContext(hProvider, 0);
}
else { //98, 98SE, ME, 2000
//We gotta look and see what we have available...
//I was going to use GetDefaultProvider, but it returns MS Base Provider
//Even when the Enhanced provider is available...
PrintLog((DEST,"CryptAcquireContext |%d| |%s| |%s| |%d| |%d|",hProvider, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT));
CryptAcquireContext(&hProvider, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
if (hProvider != 0){
strcpy(szCSPName, MS_ENHANCED_PROV);
*iMaxKey = KEYLEN_128BIT;
}
else {
szCSPName[0] = '\0';
*iMaxKey = KEYLEN_40BIT;
}
CryptReleaseContext(hProvider, 0);
}
}
}
//copy the values to the global variables
strcpy(CSP_NAME, szCSPName);
MAXKEYLEN = *iMaxKey;
return true;
}
int ResetCrypto(HCRYPTKEY hKey)
{
DWORD dwByteCount = 1;
CHAR temp[] = "a"; //decrypt/encrypt some junk.
//reset the crypto context to prepare for the next connection
//true means "this is the last bunch of data, so reset"
return CryptDecrypt(hKey, 0, true, 0, (BYTE *)temp, &dwByteCount);
}
int PrepContext(int iWinVer, HCRYPTKEY * hProvider)
{
PrintLog((DEST,"PrepContext"));
//Windows OS before 2000 won't import ExponentOfOne key in a verify context.
if (iWinVer >= WIN2000)
{
PrintLog((DEST,"Using VERIFY_CONTEXT"));
CONTEXT_FLAG = VERIFY_CONTEXT_FLAG;
szUserName[0] = '\0';
}
else
{
//PrintLog((DEST,"Using NULL_CONTEXT"));
//CONTEXT_FLAG = NULL_CONTEXT_FLAG;
PrintLog((DEST,"Using MACHINE_KEYSET"));
CONTEXT_FLAG = MACHINE_CONTEXT_FLAG;
//CONTEXT_FLAG = NULL_CONTEXT_FLAG;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -