kỹ thuật che khuất các chuỗi nhạy cảm trong C ++


87

Tôi cần lưu trữ thông tin nhạy cảm (khóa mã hóa đối xứng mà tôi muốn giữ riêng tư) trong ứng dụng C ++ của mình. Cách tiếp cận đơn giản là làm điều này:

std::string myKey = "mysupersupersecretpasswordthatyouwillneverguess";

Tuy nhiên, việc chạy ứng dụng thông qua stringsquy trình (hoặc bất kỳ quy trình nào khác trích xuất chuỗi từ ứng dụng nhị phân) sẽ tiết lộ chuỗi trên.

Những kỹ thuật nào nên được sử dụng để che khuất những dữ liệu nhạy cảm như vậy?

Biên tập:

OK, rất nhiều bạn đã nói rằng "tệp thực thi của bạn có thể được thiết kế ngược" - tất nhiên! Đây là một con vật cưng của tôi, vì vậy tôi sẽ nói một chút ở đây:

Tại sao 99% (OK, có lẽ tôi phóng đại một chút) tất cả các câu hỏi liên quan đến bảo mật trên trang web này đều được trả lời bằng một dòng torrent là "không có cách nào khả thi để tạo một chương trình hoàn toàn an toàn" - điều đó không hữu ích câu trả lời! Bảo mật là một thang trượt giữa khả năng sử dụng hoàn hảo và không có bảo mật ở một đầu và bảo mật hoàn hảo nhưng không có khả năng sử dụng ở đầu kia.

Vấn đề là bạn chọn vị trí của mình trên thang trượt đó tùy thuộc vào những gì bạn đang cố gắng làm và môi trường mà phần mềm của bạn sẽ chạy. Tôi không viết ứng dụng cho cài đặt quân sự, tôi đang viết ứng dụng cho PC gia đình . Tôi cần mã hóa dữ liệu trên một mạng không đáng tin cậy bằng khóa mã hóa đã biết trước. Trong những trường hợp này, "bảo mật thông qua che khuất" có lẽ là đủ tốt! Chắc chắn, ai đó có đủ thời gian, năng lượng và kỹ năng có thể thiết kế ngược lại hệ nhị phân và tìm mật khẩu, nhưng hãy đoán xem? Tôi không quan tâm:

Thời gian để tôi triển khai một hệ thống bảo mật hàng đầu còn tốn kém hơn cả việc mất doanh số do các phiên bản bị bẻ khóa (không phải tôi thực sự bán cái này, nhưng bạn hiểu ý tôi). Xu hướng "cho phép làm điều đó theo cách tốt nhất có thể" của bầu trời xanh này trong lập trình giữa các lập trình viên mới là điều ngu ngốc khi ít nói.

Cảm ơn bạn đã dành thời gian trả lời câu hỏi này - chúng hữu ích nhất. Thật không may, tôi chỉ có thể chấp nhận một câu trả lời, nhưng tôi đã bầu chọn tất cả các câu trả lời hữu ích.


2
Có lẽ nếu bạn mô tả những gì bạn đang cố gắng thực hiện với khóa mã hóa, chúng tôi có thể đưa ra lời khuyên về cách tránh cần phải làm điều này.
joshperry


4
@Kirill: thật khó để gọi câu hỏi này giống hệt như câu bạn đề cập. Thật vậy, ý tưởng là như nhau. Câu hỏi là không.
xtofl

1
@xtofl, bạn được tự do không bỏ phiếu. Đối với tôi, nó giống như hai câu hỏi giống hệt nhau.
Kirill V. Lyadvinsky

2
(Không liên quan đến rant) Chính định nghĩa về "khóa riêng tư" là một nửa của cặp khóa công khai / riêng tư mà bạn không đưa ra. Trong trường hợp này, khóa cá nhân là khóa bạn giữ trên máy chủ của mình; một trong ứng dụng khách của bạn là công khai.
MSalters

Câu trả lời:


42

Về cơ bản, bất kỳ ai có quyền truy cập vào chương trình của bạn và trình gỡ lỗi đều có thểsẽ tìm thấy khóa trong ứng dụng nếu họ muốn.

Tuy nhiên, nếu bạn chỉ muốn đảm bảo khóa không hiển thị khi chạy stringstrên tệp nhị phân của mình, ví dụ: bạn có thể đảm bảo rằng khóa không nằm trong phạm vi có thể in được.

Khóa che khuất bằng XOR

Ví dụ: bạn có thể sử dụng XOR để chia khóa thành hai mảng byte:

key = key1 XOR key2

Nếu bạn tạo key1 có cùng độ dài byte thì keybạn có thể sử dụng (hoàn toàn) các giá trị byte ngẫu nhiên và sau đó tính key2:

key1[n] = crypto_grade_random_number(0..255)
key2[n] = key[n] XOR key1[n]

Bạn có thể thực hiện việc này trong môi trường xây dựng của mình, sau đó chỉ lưu trữ key1key2trong ứng dụng của bạn.

Bảo vệ tệp nhị phân của bạn

Một cách tiếp cận khác là sử dụng một công cụ để bảo vệ tệp nhị phân của bạn. Ví dụ: có một số công cụ bảo mật có thể đảm bảo rằng tệp nhị phân của bạn bị xáo trộn và khởi động một máy ảo chạy trên đó. Điều này làm cho việc gỡ lỗi trở nên khó khăn (er) và cũng là cách thông thường mà nhiều ứng dụng an toàn cấp thương mại (cũng có thể là phần mềm độc hại) được bảo vệ.

Một trong những công cụ hàng đầu là Themida , thực hiện một công việc tuyệt vời trong việc bảo vệ các tệp nhị phân của bạn. Nó thường được các chương trình nổi tiếng, chẳng hạn như Spotify, sử dụng để bảo vệ chống lại kỹ thuật đảo ngược. Nó có các tính năng để ngăn chặn việc gỡ lỗi trong các chương trình như OllyDbg và Ida Pro.

Ngoài ra còn có một danh sách lớn hơn, có thể hơi lỗi thời, các công cụ để bảo vệ tệp nhị phân của bạn .
Một số trong số chúng là miễn phí.

Đối sánh mật khẩu

Ai đó ở đây đã thảo luận về mật khẩu băm + muối.

Nếu bạn cần lưu trữ khóa để khớp với một số loại mật khẩu do người dùng gửi, bạn nên sử dụng hàm băm một chiều, tốt hơn là bằng cách kết hợp tên người dùng, mật khẩu và một muối. Tuy nhiên, vấn đề với điều này là ứng dụng của bạn phải biết muối để có thể thực hiện một chiều và so sánh các hàm băm kết quả. Vì vậy, bạn vẫn cần lưu trữ muối ở đâu đó trong ứng dụng của mình. Tuy nhiên, như @Edward chỉ ra trong các nhận xét bên dưới, điều này sẽ bảo vệ hiệu quả chống lại cuộc tấn công từ điển bằng cách sử dụng, ví dụ: bảng cầu vồng.

Cuối cùng, bạn có thể sử dụng kết hợp tất cả các kỹ thuật trên.


Nếu mật khẩu của nó mà người dùng phải nhập, hãy lưu trữ hàm băm + muối của mật khẩu. Xem câu trả lời bên dưới.

1
@hapalibashi: Làm cách nào để bạn lưu trữ muối an toàn trong ứng dụng của mình? Tôi không nghĩ OP cần một hệ thống khớp mật khẩu một chiều, chỉ là một cách tổng quát để lưu trữ các khóa tĩnh.
csl

2
Tôi đã phát hiện ra khi xem xét các chương trình được tháo rời thường không có nhiều XOR, vì vậy nếu bạn đang hy vọng sử dụng XOR để che khuất điều gì đó, hãy lưu ý rằng chúng thu hút sự chú ý đến chính chúng.
kb.

2
@kb - đó là một điểm thú vị. Tôi đoán rằng bạn sẽ thấy những điều tương tự xảy ra nhiều hơn xor. a ^ b == (a & ~ b) || (~ a & b)
Jeremy Powell

4
Biết giá trị của muối thường không mang lại lợi thế cho kẻ thù - điểm của muối là tránh một "cuộc tấn công từ điển", theo đó kẻ tấn công đã tính toán trước các hàm băm cho nhiều đầu vào có thể xảy ra. Việc sử dụng muối buộc họ phải tính toán trước từ điển của mình với một từ điển mới dựa trên muối. Nếu mỗi muối chỉ được sử dụng một lần, thì cuộc tấn công từ điển trở nên hoàn toàn vô dụng.
Edward Dixon

8

Trước hết, hãy nhận ra rằng bạn không thể làm gì để ngăn chặn một hacker đủ quyết tâm và có rất nhiều kẻ xung quanh. Bảo vệ trên mọi trò chơi và bảng điều khiển xung quanh cuối cùng đã bị bẻ khóa, vì vậy đây chỉ là một bản sửa lỗi tạm thời.

Có 4 điều bạn có thể làm để tăng cơ hội ở ẩn trong một thời gian.

1) Ẩn các phần tử của chuỗi theo một cách nào đó - một cái gì đó hiển nhiên như xoring (toán tử ^) chuỗi với một chuỗi khác sẽ đủ tốt để làm cho chuỗi không thể tìm kiếm được.

2) Chia chuỗi thành nhiều phần - chia nhỏ chuỗi của bạn và bật các bit của nó thành các phương thức có tên lạ trong các mô-đun lạ. Đừng làm cho nó dễ dàng tìm kiếm và tìm thấy phương pháp với chuỗi trong đó. Tất nhiên một số phương thức sẽ phải gọi tất cả các bit này, nhưng nó vẫn làm cho nó khó hơn một chút.

3) Đừng bao giờ tạo chuỗi trong bộ nhớ - hầu hết các tin tặc sử dụng các công cụ cho phép họ nhìn thấy chuỗi trong bộ nhớ sau khi bạn đã mã hóa nó. Nếu có thể, hãy tránh điều này. Ví dụ: nếu bạn đang gửi khóa đến một máy chủ, hãy gửi khóa đó theo từng ký tự, vì vậy toàn bộ chuỗi không bao giờ có xung quanh. Tất nhiên, nếu bạn đang sử dụng nó từ một thứ gì đó như mã hóa RSA, thì điều này sẽ phức tạp hơn.

4) Thực hiện một thuật toán đặc biệt - trên hết, hãy thêm một hoặc hai bước ngoặt độc đáo. Có thể chỉ cần thêm 1 vào mọi thứ bạn sản xuất, hoặc thực hiện bất kỳ mã hóa nào hai lần hoặc thêm đường. Điều này chỉ khiến hacker gặp khó khăn hơn một chút, những người đã biết phải tìm kiếm gì khi ai đó đang sử dụng, chẳng hạn như băm vani md5 hoặc mã hóa RSA.

Trên tất cả, hãy đảm bảo rằng nó không quá quan trọng khi (và sẽ là khi ứng dụng của bạn đủ phổ biến) khóa của bạn được phát hiện!


5

Một chiến lược tôi đã sử dụng trong quá khứ là tạo một mảng các ký tự dường như ngẫu nhiên. Ban đầu, bạn chèn và sau đó xác định vị trí các ký tự cụ thể của mình bằng quy trình đại số trong đó mỗi bước từ 0 đến N sẽ mang lại một số <kích thước của mảng chứa ký tự tiếp theo trong chuỗi bị xáo trộn của bạn. (Câu trả lời này bây giờ đang cảm thấy khó hiểu!)

Thí dụ:

Cho một mảng ký tự (số và dấu gạch ngang chỉ để tham khảo)

0123456789
----------
ALFHNFELKD
LKFKFLEHGT
FLKRKLFRFK
FJFJJFJ!JL

Và một phương trình có sáu kết quả đầu tiên là: 3, 6, 7, 10, 21, 47

Sẽ mang lại từ "HELLO!" từ mảng trên.


Ý tưởng hay - Tôi đoán bạn tiếp tục có thể cải thiện nó bằng cách sử dụng các ký tự không in trong mảng ...
Thomi

4

Tôi đồng ý với @Checkers, tệp thực thi của bạn có thể được thiết kế ngược.

Một cách tốt hơn một chút là tạo động, ví dụ:

std::string myKey = part1() + part2() + ... + partN();

Đúng, điều đó tránh bị lộ chuỗi khi tìm kiếm nhị phân. Tuy nhiên, chuỗi của bạn vẫn nằm trong bộ nhớ .. Mặc dù vậy, giải pháp của bạn có lẽ đủ tốt cho những gì tôi đang làm.
Thomi

@Thomi, tất nhiên, bạn có thể phá hủy nó ngay sau khi bạn làm xong. Tuy nhiên, nó không phải là cách tốt nhất để xử lý các chuỗi nhạy cảm .
Nick Dandoulakis

... vì việc phá hủy nó không thực sự đảm bảo rằng bộ nhớ sẽ được sử dụng lại ngay lập tức.
Thomi

4

Tất nhiên, việc lưu trữ dữ liệu cá nhân trong phần mềm được chuyển đến tay người dùng luôn là một rủi ro. Bất kỳ kỹ sư nào được đào tạo đầy đủ (và tận tâm) đều có thể thiết kế ngược lại dữ liệu.

Nói như vậy, bạn thường có thể đảm bảo mọi thứ đủ an toàn bằng cách nâng cao rào cản mà mọi người cần vượt qua để tiết lộ dữ liệu cá nhân của bạn. Đó thường là một thỏa hiệp tốt.

Trong trường hợp của bạn, bạn có thể làm lộn xộn các chuỗi của mình với dữ liệu không thể in được và sau đó giải mã dữ liệu đó trong thời gian chạy bằng một hàm trợ giúp đơn giản, như sau:

void unscramble( char *s )
{
    for ( char *str = s + 1; *str != 0; str += 2 ) {
        *s++ = *str;
    }
    *s = '\0';
}

void f()
{
    char privateStr[] = "\001H\002e\003l\004l\005o";
    unscramble( privateStr ); // privateStr is 'Hello' now.

    string s = privateStr;
    // ...
}

4

Tôi đã tạo một công cụ mã hóa đơn giản cho các chuỗi, nó có thể tự động tạo các chuỗi được mã hóa và có một vài tùy chọn bổ sung để làm điều đó, một vài ví dụ:

Chuỗi như một biến toàn cục:

// myKey = "mysupersupersecretpasswordthatyouwillneverguess";
unsigned char myKey[48] = { 0xCF, 0x34, 0xF8, 0x5F, 0x5C, 0x3D, 0x22, 0x13, 0xB4, 0xF3, 0x63, 0x7E, 0x6B, 0x34, 0x01, 0xB7, 0xDB, 0x89, 0x9A, 0xB5, 0x1B, 0x22, 0xD4, 0x29, 0xE6, 0x7C, 0x43, 0x0B, 0x27, 0x00, 0x91, 0x5F, 0x14, 0x39, 0xED, 0x74, 0x7D, 0x4B, 0x22, 0x04, 0x48, 0x49, 0xF1, 0x88, 0xBE, 0x29, 0x1F, 0x27 };

myKey[30] -= 0x18;
myKey[39] -= 0x8E;
myKey[3] += 0x16;
myKey[1] += 0x45;
myKey[0] ^= 0xA2;
myKey[24] += 0x8C;
myKey[44] ^= 0xDB;
myKey[15] ^= 0xC5;
myKey[7] += 0x60;
myKey[27] ^= 0x63;
myKey[37] += 0x23;
myKey[2] ^= 0x8B;
myKey[25] ^= 0x18;
myKey[12] ^= 0x18;
myKey[14] ^= 0x62;
myKey[11] ^= 0x0C;
myKey[13] += 0x31;
myKey[6] -= 0xB0;
myKey[22] ^= 0xA3;
myKey[43] += 0xED;
myKey[29] -= 0x8C;
myKey[38] ^= 0x47;
myKey[19] -= 0x54;
myKey[33] -= 0xC2;
myKey[40] += 0x1D;
myKey[20] -= 0xA8;
myKey[34] ^= 0x84;
myKey[8] += 0xC1;
myKey[28] -= 0xC6;
myKey[18] -= 0x2A;
myKey[17] -= 0x15;
myKey[4] ^= 0x2C;
myKey[9] -= 0x83;
myKey[26] += 0x31;
myKey[10] ^= 0x06;
myKey[16] += 0x8A;
myKey[42] += 0x76;
myKey[5] ^= 0x58;
myKey[23] ^= 0x46;
myKey[32] += 0x61;
myKey[41] ^= 0x3B;
myKey[31] ^= 0x30;
myKey[46] ^= 0x6C;
myKey[35] -= 0x08;
myKey[36] ^= 0x11;
myKey[45] -= 0xB6;
myKey[21] += 0x51;
myKey[47] += 0xD9;

Dưới dạng chuỗi unicode với vòng lặp giải mã:

// myKey = "mysupersupersecretpasswordthatyouwillneverguess";
wchar_t myKey[48];

myKey[21] = 0x00A6;
myKey[10] = 0x00B0;
myKey[29] = 0x00A1;
myKey[22] = 0x00A2;
myKey[19] = 0x00B4;
myKey[33] = 0x00A2;
myKey[0] = 0x00B8;
myKey[32] = 0x00A0;
myKey[16] = 0x00B0;
myKey[40] = 0x00B0;
myKey[4] = 0x00A5;
myKey[26] = 0x00A1;
myKey[18] = 0x00A5;
myKey[17] = 0x00A1;
myKey[8] = 0x00A0;
myKey[36] = 0x00B9;
myKey[34] = 0x00BC;
myKey[44] = 0x00B0;
myKey[30] = 0x00AC;
myKey[23] = 0x00BA;
myKey[35] = 0x00B9;
myKey[25] = 0x00B1;
myKey[6] = 0x00A7;
myKey[27] = 0x00BD;
myKey[45] = 0x00A6;
myKey[3] = 0x00A0;
myKey[28] = 0x00B4;
myKey[14] = 0x00B6;
myKey[7] = 0x00A6;
myKey[11] = 0x00A7;
myKey[13] = 0x00B0;
myKey[39] = 0x00A3;
myKey[9] = 0x00A5;
myKey[2] = 0x00A6;
myKey[24] = 0x00A7;
myKey[46] = 0x00A6;
myKey[43] = 0x00A0;
myKey[37] = 0x00BB;
myKey[41] = 0x00A7;
myKey[15] = 0x00A7;
myKey[31] = 0x00BA;
myKey[1] = 0x00AC;
myKey[47] = 0x00D5;
myKey[20] = 0x00A6;
myKey[5] = 0x00B0;
myKey[38] = 0x00B0;
myKey[42] = 0x00B2;
myKey[12] = 0x00A6;

for (unsigned int fngdouk = 0; fngdouk < 48; fngdouk++) myKey[fngdouk] ^= 0x00D5;

Chuỗi như một biến toàn cục:

// myKey = "mysupersupersecretpasswordthatyouwillneverguess";
unsigned char myKey[48] = { 0xAF, 0xBB, 0xB5, 0xB7, 0xB2, 0xA7, 0xB4, 0xB5, 0xB7, 0xB2, 0xA7, 0xB4, 0xB5, 0xA7, 0xA5, 0xB4, 0xA7, 0xB6, 0xB2, 0xA3, 0xB5, 0xB5, 0xB9, 0xB1, 0xB4, 0xA6, 0xB6, 0xAA, 0xA3, 0xB6, 0xBB, 0xB1, 0xB7, 0xB9, 0xAB, 0xAE, 0xAE, 0xB0, 0xA7, 0xB8, 0xA7, 0xB4, 0xA9, 0xB7, 0xA7, 0xB5, 0xB5, 0x42 };

for (unsigned int dzxykdo = 0; dzxykdo < 48; dzxykdo++) myKey[dzxykdo] -= 0x42;

Không, tôi đã sử dụng trang web stringencrypt.com để thực hiện công việc. Nó có các ví dụ cho C / C ++ stringencrypt.com/c-cpp-encryption mà bạn có thể cân nhắc sử dụng nó để tự động mã hóa chuỗi đơn giản.
Bartosz Wójcik

2

Hơi phụ thuộc vào những gì bạn đang cố gắng bảo vệ như joshperry chỉ ra. Từ kinh nghiệm, tôi sẽ nói rằng nếu nó là một phần của chương trình cấp phép nào đó để bảo vệ phần mềm của bạn thì đừng bận tâm. Cuối cùng họ sẽ thiết kế ngược lại nó. Chỉ cần sử dụng một mật mã đơn giản như ROT-13 để bảo vệ nó khỏi các cuộc tấn công đơn giản (dòng chạy chuỗi trên nó). Nếu đó là để bảo mật dữ liệu nhạy cảm của người dùng, tôi sẽ đặt câu hỏi liệu việc bảo vệ dữ liệu đó bằng khóa riêng được lưu trữ cục bộ có phải là một bước đi khôn ngoan hay không. Một lần nữa nó liên quan đến những gì bạn đang cố gắng bảo vệ.

CHỈNH SỬA: Nếu bạn định làm điều đó thì sự kết hợp của các kỹ thuật mà Chris chỉ ra sẽ tốt hơn nhiều so với rot13.


2

Như đã nói trước đây, không có cách nào để bảo vệ hoàn toàn chuỗi của bạn. Nhưng có những cách để bảo vệ nó một cách khôn ngoan và an toàn hợp lý.

Khi tôi phải làm điều này, tôi đã đặt một số chuỗi trông có vẻ ngây thơ vào mã (ví dụ: thông báo bản quyền hoặc một số lời nhắc người dùng giả mạo hoặc bất kỳ thứ gì khác sẽ không bị thay đổi bởi ai đó sửa mã không liên quan), mã hóa bằng chính nó như một khóa, băm đó (thêm một số muối) và sử dụng kết quả làm khóa để mã hóa những gì tôi thực sự muốn mã hóa.

Tất nhiên điều này có thể bị tấn công, nhưng phải cần một hacker kiên quyết để làm điều đó.


Ý tưởng hay - một hình thức che giấu khác là sử dụng một chuỗi vẫn còn mạnh hợp lý (dài, dấu chấm câu và tất cả những thứ đó là nhạc jazz) nhưng rõ ràng không giống mật khẩu.
Thomi

1

Nếu bạn đang sử dụng DPAPI của người dùng windows, hãy http://msdn.microsoft.com/en-us/library/ms995355.aspx

Như một bài trước đã nói nếu bạn đang sử dụng mac, hãy sử dụng keychain.

Về cơ bản, tất cả những ý tưởng dễ thương này về cách lưu trữ khóa cá nhân bên trong tệp nhị phân của bạn là đủ kém từ góc độ bảo mật mà bạn không nên làm chúng. Bất kỳ ai nhận được khóa riêng của bạn đều là một vấn đề lớn, đừng giữ nó trong chương trình của bạn. Tùy thuộc vào cách nhập ứng dụng của bạn, bạn có thể giữ khóa cá nhân của mình trên thẻ thông minh, trên một máy tính từ xa, mã của bạn nói chuyện với hoặc bạn có thể làm những gì hầu hết mọi người làm và giữ nó ở một nơi rất an toàn trên máy tính cục bộ (khóa " lưu trữ "giống như một sổ đăng ký bảo mật kỳ lạ) được bảo vệ bởi các quyền và tất cả sức mạnh của hệ điều hành của bạn.

Đây là một vấn đề đã được giải quyết và câu trả lời là KHÔNG giữ chìa khóa bên trong chương trình của bạn :)


1

Hãy thử điều này . Mã nguồn giải thích cách mã hóa và giải mã nhanh chóng tất cả các chuỗi trong một dự án Visual Studio c ++ nhất định.


1

Một phương pháp tôi đã thử gần đây là:

  1. Lấy băm (SHA256) của dữ liệu cá nhân và điền nó vào mã dưới dạng part1
  2. Lấy XOR của dữ liệu cá nhân và mã băm của nó và điền nó vào mã dưới dạng part2
  3. Điền dữ liệu: Không lưu trữ nó dưới dạng char str [], nhưng điền vào thời gian chạy bằng cách sử dụng hướng dẫn gán (như được hiển thị trong macro bên dưới)
  4. Bây giờ, tạo dữ liệu cá nhân trong thời gian chạy bằng cách lấy XOR của part1part2
  5. Bước bổ sung : Tính toán băm của dữ liệu đã tạo và so sánh với part1. Nó sẽ xác minh tính toàn vẹn của dữ liệu cá nhân.

MACRO để điền dữ liệu:

Giả sử, dữ liệu riêng tư có kích thước 4 byte. Chúng tôi xác định một macro cho nó để lưu dữ liệu với các lệnh gán theo một số thứ tự ngẫu nhiên.

#define POPULATE_DATA(str, i0, i1, i2, i3)\
{\
    char *p = str;\
    p[3] = i3;\
    p[2] = i2;\
    p[0] = i0;\
    p[1] = i1;\
}

Bây giờ sử dụng macro này trong mã nơi bạn cần lưu part1part2như sau:

char part1[4] = {0};
char part2[4] = {0};
POPULATE_DATA(part1, 1, 2, 3, 4); 
POPULATE_DATA(part2, 5, 6, 7, 8);

0

Thay vì lưu trữ khóa cá nhân trong tệp thực thi của mình, bạn có thể muốn yêu cầu nó từ người dùng và lưu trữ nó bằng trình quản lý mật khẩu bên ngoài , một thứ tương tự như Mac OS X Keychain Access.


vâng và không .. thông thường tôi đồng ý với bạn, nhưng trong trường hợp này, tôi đang cố giấu điều này với người dùng phần mềm, vì vậy lưu trữ nó trong một hệ thống bên ngoài không phải là một ý tưởng hay (nhiều hệ thống chuỗi khóa có thể hiển thị mật khẩu dưới dạng văn bản thuần túy cho người dùng được cấp quyền phù hợp). Phần mềm chuỗi khóa rất tốt cho mật khẩu người dùng, nhưng không quá tuyệt vời cho các khóa mã hóa ứng dụng.
Thomi

nếu nó cảm thấy không an toàn (mặc dù được làm rõ của bạn có thể nó là đầy đủ), bạn có thể kết hợp một keychain và một cái gì đó hardcoded :)

0

Tùy thuộc vào ngữ cảnh nhưng bạn chỉ có thể lưu trữ băm của khóa cộng với một muối (chuỗi không đổi, dễ bị che khuất).

Sau đó, khi (nếu) người dùng nhập khóa, bạn thêm muối , tính toán băm và so sánh.

Các muối có lẽ là không cần thiết trong trường hợp này, nó dừng lại một cuộc tấn công brute-force dictionary nếu băm có thể được cô lập (một tìm kiếm Google cũng đã được bí quyết để làm việc).

Một hacker vẫn chỉ phải chèn một lệnh jmp vào đâu đó để vượt qua toàn bộ, nhưng điều đó khá phức tạp hơn so với một tìm kiếm văn bản đơn giản.


Đây là khóa mã hóa, không phải mã băm mật khẩu. Tôi cần chìa khóa thực tế để mã hóa và giải mã dữ liệu. Người dùng không bao giờ nhìn thấy khóa, nó không bao giờ được lưu trữ bên ngoài hệ nhị phân.
Thomi

0

Có một (rất nhẹ) header-chỉ dự án xáo trộn do adamyaxley rằng hoạt động hoàn hảo. Nó dựa trên các hàm lambda và macro và nó mã hóa các chuỗi nhỏ bằng mật mã XOR tại thời điểm biên dịch. Nếu cần, chúng ta có thể thay đổi hạt giống cho mỗi chuỗi.

Đoạn mã sau sẽ không lưu chuỗi "hello world" trong nhị phân đã biên dịch.

#include "obfuscate.h"

int main()
{
  std::cout << AY_OBFUSCATE("Hello World") << std::endl;
  return 0;
}

Tôi đã thử nghiệm với c ++ 17 và visual studio 2019, đồng thời kiểm tra qua IDA và tôi xác nhận chuỗi bị ẩn. Một lợi thế quý giá so với ADVobfuscator là nó có thể chuyển đổi thành chuỗi std :: (trong khi vẫn được ẩn trong tệp nhị phân đã biên dịch):

std::string var = AY_OBFUSCATE("string");
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.