- 编程
USBKey
- @ 2025-12-14 10:22:16
需要一个能获取到序列号的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 条评论
目前还没有评论...