需要一个能获取到序列号的U盘(若获取不到安全程度将会退化为无法保证不同U盘不同密钥),且至少有10KB空间用于存储密钥

#include <iostream>
#include <windows.h>
#include <fstream>
#include <vector>
#include <setupapi.h>
#include <winioctl.h>
#include <cfgmgr32.h>
#pragma comment(lib, "setupapi.lib")
using namespace std;

#define ROTR(x, n) (((x) >> (n)) | ((x) << (64 - (n))))
#define SHR(x, n)  ((x) >> (n))

static const uint64_t K[80] = {
    0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
    0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
    0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
    0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694,
    0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
    0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
    0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4,
    0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70,
    0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
    0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
    0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30,
    0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
    0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
    0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
    0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
    0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b,
    0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
    0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
    0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
    0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817
};

static const uint64_t H0[8] = {
    0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
    0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179
};

inline uint64_t Ch(uint64_t x, uint64_t y, uint64_t z)   { return (x & y) ^ (~x & z); }
inline uint64_t Maj(uint64_t x, uint64_t y, uint64_t z)  { return (x & y) ^ (x & z) ^ (y & z); }
inline uint64_t Sigma0(uint64_t x) { return ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39); }
inline uint64_t Sigma1(uint64_t x) { return ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41); }
inline uint64_t sigma0(uint64_t x) { return ROTR(x, 1) ^ ROTR(x, 8) ^  SHR(x, 7); }
inline uint64_t sigma1(uint64_t x) { return ROTR(x,19) ^ ROTR(x,61) ^  SHR(x, 6); }

static void sha512_transform(uint64_t state[8], const uint8_t block[128]) {
    uint64_t W[80];
    uint64_t a, b, c, d, e, f, g, h, t1, t2;

    for (int t = 0; t < 16; ++t)
        W[t] = ((uint64_t)block[t*8+0] << 56) | ((uint64_t)block[t*8+1] << 48) |
               ((uint64_t)block[t*8+2] << 40) | ((uint64_t)block[t*8+3] << 32) |
               ((uint64_t)block[t*8+4] << 24) | ((uint64_t)block[t*8+5] << 16) |
               ((uint64_t)block[t*8+6] <<  8) | ((uint64_t)block[t*8+7]);
    for (int t = 16; t < 80; ++t)
        W[t] = sigma1(W[t-2]) + W[t-7] + sigma0(W[t-15]) + W[t-16];

    a = state[0]; b = state[1]; c = state[2]; d = state[3];
    e = state[4]; f = state[5]; g = state[6]; h = state[7];

    for (int t = 0; t < 80; ++t) {
        t1 = h + Sigma1(e) + Ch(e,f,g) + K[t] + W[t];
        t2 = Sigma0(a) + Maj(a,b,c);
        h = g; g = f; f = e; e = d + t1;
        d = c; c = b; b = a; a = t1 + t2;
    }
    for (int i = 0; i < 8; ++i) state[i] += (&a)[i];
}

void sha512(const uint8_t *msg, size_t len, uint8_t digest[64]) {
    uint64_t state[8];
    uint8_t  buffer[128] = {0};
    uint64_t bit_len = len * 8;

    memcpy(state, H0, sizeof(H0));

    size_t i = 0;
    for (; i + 128 <= len; i += 128)
        sha512_transform(state, msg + i);

    size_t rem = len - i;
    memcpy(buffer, msg + i, rem);
    buffer[rem] = 0x80;                  
    if (rem >= 112) {
        sha512_transform(state, buffer);
        memset(buffer, 0, 128);
    }
    buffer[120] = (uint8_t)(bit_len >> 56);
    buffer[121] = (uint8_t)(bit_len >> 48);
    buffer[122] = (uint8_t)(bit_len >> 40);
    buffer[123] = (uint8_t)(bit_len >> 32);
    buffer[124] = (uint8_t)(bit_len >> 24);
    buffer[125] = (uint8_t)(bit_len >> 16);
    buffer[126] = (uint8_t)(bit_len >>  8);
    buffer[127] = (uint8_t)(bit_len);
    sha512_transform(state, buffer);

    for (int j = 0; j < 8; ++j) {
        digest[j*8+0] = (uint8_t)(state[j] >> 56);
        digest[j*8+1] = (uint8_t)(state[j] >> 48);
        digest[j*8+2] = (uint8_t)(state[j] >> 40);
        digest[j*8+3] = (uint8_t)(state[j] >> 32);
        digest[j*8+4] = (uint8_t)(state[j] >> 24);
        digest[j*8+5] = (uint8_t)(state[j] >> 16);
        digest[j*8+6] = (uint8_t)(state[j] >>  8);
        digest[j*8+7] = (uint8_t)(state[j]);
    }
}

string sha512_to_string(const uint8_t hash[8]) {
    static const char hex[] = "0123456789abcdef";
    string result;
    result.reserve(128);
    
    const unsigned char* p = reinterpret_cast<const unsigned char*>(hash);
    
    for (int i = 0; i < 64; ++i) {
        result += hex[(p[i] >> 4) & 0x0F];
        result += hex[p[i] & 0x0F];
    }
    
    return result;
}

struct security{
	private:
		vector<string> GetUSBDriveLetters(){
		    vector<string> usbDrives;
		    char driveLetters[MAX_PATH];
		    if (GetLogicalDriveStringsA(MAX_PATH, driveLetters)){
		        char* pDrive = driveLetters;
		        while (*pDrive){
		            string drivePath(pDrive);
		            if (GetDriveTypeA(drivePath.c_str()) == DRIVE_REMOVABLE){
		                usbDrives.push_back(drivePath);
		            }
		            pDrive += strlen(pDrive) + 1;
		        }
		    }
		    else{
		        cerr << "$: " << GetLastError() << endl;
		    }
			
		    return usbDrives;
		}
		string GetUSBDriveSerial(const char* driveLetter) {
		    string result;
		    char devicePath[7] = "\\\\.\\X:";
		    devicePath[4] = driveLetter[0];
		    
		    HANDLE hDevice = CreateFile(devicePath,
		        GENERIC_READ | GENERIC_WRITE,
		        FILE_SHARE_READ | FILE_SHARE_WRITE,
		        NULL, OPEN_EXISTING, 0, NULL);
		    
		    if (hDevice == INVALID_HANDLE_VALUE) return "";
		    
		    STORAGE_PROPERTY_QUERY query;
		    query.PropertyId = StorageDeviceProperty;
		    query.QueryType = PropertyStandardQuery;
		    
		    STORAGE_DESCRIPTOR_HEADER header;
		    DWORD bytesReturned = 0;
		    
		    if (!DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
		        &query, sizeof(query), &header, sizeof(header),
		        &bytesReturned, NULL)) {
		        CloseHandle(hDevice);
		        return "";
		    }
		    
		    BYTE* buffer = new BYTE[header.Size];
		    if (DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
		        &query, sizeof(query), buffer, header.Size,
		        &bytesReturned, NULL)) {
		        STORAGE_DEVICE_DESCRIPTOR* desc = (STORAGE_DEVICE_DESCRIPTOR*)buffer;
		        if (desc->SerialNumberOffset) {
		            char* serial = (char*)(buffer + desc->SerialNumberOffset);
		            result = serial;
		        }
		    }
		    
		    delete[] buffer;
		    CloseHandle(hDevice);
		    return result;
		}
		vector<string> usbDrives;
	public:
		bool USBKey(string pwhash){
			usbDrives = GetUSBDriveLetters();
			vector <string> temps;
			vector <string> uuids;
			for(int i = 0;i<usbDrives.size();i++){
				fstream file1;
				string t;
				char usbd[2];
				usbd[0] = usbDrives[i][0];
				usbd[1] = '\0';
				string tuuid = GetUSBDriveSerial(usbd);
				file1.open(usbDrives[i].substr(0,2)+ "/" + "pwt.txt",ios::in);
				getline(file1,t);
				temps.push_back(t);
				file1.close();
				uuids.push_back(tuuid);
			}
			for(int i = 0;i<temps.size();i++){
				string hashs;
				string nhash;
				uint8_t hash[64];
				nhash = uuids[i] + pwhash;
			    sha512(reinterpret_cast<const uint8_t*>(nhash.data()), nhash.size(), hash);
			    hashs = sha512_to_string(hash);
			    if(hashs == temps[i]){
			    	return true;
				}
			}
			return false;
		}
		void newUSBKey(string dletter,string pwhash){
			char d[2];
			d[0] = dletter[0];
			d[1] = '\0';
			string uuid = GetUSBDriveSerial(d);
			string hashs;
			fstream file1;
			uint8_t hash[64];
			pwhash = uuid + pwhash;
		    sha512(reinterpret_cast<const uint8_t*>(pwhash.data()), pwhash.size(), hash);
		    hashs = sha512_to_string(hash);
			file1.open(dletter + ":/" + "pwt.txt",ios::out);
			file1 << hashs;
			file1.close();
		}
};

int main(){
	while(true){
		system("cls");
		security s;
		printf("Please input password:");
		string msg;
		string pwhash = "";
		cin >> msg;
	    uint8_t hash[64];
	    sha512(reinterpret_cast<const uint8_t*>(msg.data()), msg.size(), hash);
	    pwhash = sha512_to_string(hash);
	    printf("Please choose to add(0) or verify(1):");
	    char c;
	    cin >> c;
	    if(c == '0'){
	    	string p;
	    	printf("Please enter the drive letter:");
	    	cin >> p;
	    	s.newUSBKey(p,pwhash);
	    	cout << "Success" << endl;
	    	system("pause"); 
		}
	    else if(c == '1'){
	    	printf("Please wait...\n");
	    	if(s.USBKey(pwhash)){
	    		cout << "Success" << endl;
			}
			else{
				cout << "Fail" << endl;
			}
			system("pause"); 
		}
		else{
			continue;
		}
	}
	return 0;
}

Windows平台|Dev-C++|C++11

原理不难,大致上就是将密码的哈希与设备序列号结合起来再跑一次哈希,在U盘序列号唯一时能保证唯一性

0 条评论

目前还没有评论...