Techniken zum Verschleiern sensibler Zeichenfolgen in C ++

87

Ich muss vertrauliche Informationen (einen symmetrischen Verschlüsselungsschlüssel, den ich privat halten möchte) in meiner C ++ - Anwendung speichern. Der einfache Ansatz besteht darin, dies zu tun:

std::string myKey = "mysupersupersecretpasswordthatyouwillneverguess";

Wenn Sie die Anwendung jedoch durch den stringsProzess ausführen (oder eine andere, die Zeichenfolgen aus einer binären App extrahiert), wird die obige Zeichenfolge angezeigt.

Welche Techniken sollten verwendet werden, um solche sensiblen Daten zu verschleiern?

Bearbeiten:

OK, so ziemlich alle von Ihnen haben gesagt "Ihre ausführbare Datei kann rückentwickelt werden" - natürlich! Dies ist ein Liebling von mir, also werde ich hier ein bisschen schimpfen:

Warum werden 99% (OK, vielleicht übertreibe ich ein wenig) aller sicherheitsrelevanten Fragen auf dieser Website mit dem Strom "Es gibt keine Möglichkeit, ein perfekt sicheres Programm zu erstellen" beantwortet - das ist nicht hilfreich Antworten! Sicherheit ist eine gleitende Skala zwischen perfekter Benutzerfreundlichkeit und keiner Sicherheit an einem Ende und perfekter Sicherheit, aber keiner Benutzerfreundlichkeit am anderen Ende.

Der Punkt ist, dass Sie Ihre Position auf dieser gleitenden Skala auswählen, je nachdem, was Sie versuchen und in welcher Umgebung Ihre Software ausgeführt wird. Ich schreibe keine App für eine militärische Installation, ich schreibe eine App für einen Heim-PC . Ich muss Daten über ein nicht vertrauenswürdiges Netzwerk mit einem bekannten Verschlüsselungsschlüssel verschlüsseln. In diesen Fällen ist "Sicherheit durch Dunkelheit" wahrscheinlich gut genug! Sicher, jemand mit genügend Zeit, Energie und Geschick könnte die Binärdatei rückentwickeln und das Passwort finden, aber wissen Sie was? Es ist mir egal:

Die Zeit, die ich für die Implementierung eines erstklassigen sicheren Systems benötige, ist teurer als der Umsatzverlust aufgrund der geknackten Versionen (nicht, dass ich das tatsächlich verkaufe, aber Sie verstehen, worum es geht). Dieser Trend des Programmierens unter den Programmierern unter neuen Programmierern ist, gelinde gesagt, dumm.

Vielen Dank, dass Sie sich die Zeit genommen haben, diese Frage zu beantworten - sie waren sehr hilfreich. Leider kann ich nur eine Antwort akzeptieren, aber ich habe alle nützlichen Antworten hochgestimmt.

Thomi
quelle
2
Wenn Sie beschreiben, was Sie mit dem Verschlüsselungsschlüssel erreichen möchten, können wir Ihnen möglicherweise Tipps geben, wie Sie dies vermeiden können.
Joshperry
3
Genaues Duplikat: stackoverflow.com/questions/926172/…
Kirill V. Lyadvinsky
4
@Kirill: Es ist schwer, diese Frage genauso zu nennen wie die, die Sie erwähnen. In der Tat ist die Idee dieselbe. Die Frage ist nicht.
xtofl
1
@xtofl, du bist frei, nicht abzustimmen. Für mich sieht es nach zwei identischen Fragen aus.
Kirill V. Lyadvinsky
2
(Ohne Bezug zu schimpfen) Die Definition eines "privaten Schlüssels" ist die Hälfte eines öffentlichen / privaten Schlüsselpaars, die Sie nicht herausgeben. Auch in diesem Fall ist der private Schlüssel derjenige, den Sie auf Ihrem Server behalten. Die in Ihrer Client-App ist öffentlich.
MSalters

Antworten:

42

Grundsätzlich kann und wird jeder, der Zugriff auf Ihr Programm und einen Debugger hat , den Schlüssel in der Anwendung finden, wenn er möchte.

Wenn Sie jedoch nur sicherstellen möchten, dass der Schlüssel beim Ausführen stringsIhrer Binärdatei nicht angezeigt wird, können Sie beispielsweise sicherstellen, dass der Schlüssel nicht im druckbaren Bereich liegt.

Verdeckter Schlüssel mit XOR

Sie können beispielsweise XOR verwenden, um den Schlüssel in zwei Byte-Arrays aufzuteilen:

key = key1 XOR key2

Wenn Sie key1 mit derselben Bytelänge erstellen, wie keySie (vollständig) zufällige Bytewerte verwenden können, und dann Folgendes berechnen key2:

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

Sie können in Ihrer Build - Umgebung tun dies, und auch nur dann speichern key1und key2in Ihrer Anwendung.

Schützen Sie Ihre Binärdatei

Ein anderer Ansatz besteht darin, ein Tool zum Schutz Ihrer Binärdatei zu verwenden. Beispielsweise gibt es mehrere Sicherheitstools, mit denen sichergestellt werden kann, dass Ihre Binärdatei verschleiert ist und eine virtuelle Maschine gestartet wird, auf der sie ausgeführt wird. Dies erschwert das Debuggen und ist auch die übliche Art und Weise, wie viele kommerzielle sichere Anwendungen (leider auch Malware) geschützt werden.

Eines der wichtigsten Tools ist Themida , das Ihre Binärdateien hervorragend schützt. Es wird häufig von bekannten Programmen wie Spotify zum Schutz vor Reverse Engineering verwendet. Es verfügt über Funktionen zum Verhindern des Debuggens in Programmen wie OllyDbg und Ida Pro.

Es gibt auch eine größere, möglicherweise etwas veraltete Liste von Tools zum Schutz Ihrer Binärdatei .
Einige von ihnen sind kostenlos.

Passwortabgleich

Jemand hier hat über Hashing-Passwort + Salt gesprochen.

Wenn Sie den Schlüssel speichern müssen, um ihn mit einem vom Benutzer übermittelten Kennwort abzugleichen, sollten Sie eine Einweg-Hashing-Funktion verwenden, vorzugsweise durch Kombinieren von Benutzername, Kennwort und Salt. Das Problem dabei ist jedoch, dass Ihre Anwendung das Salz kennen muss, um die Einbahnstraße ausführen und die resultierenden Hashes vergleichen zu können. Daher müssen Sie das Salz immer noch irgendwo in Ihrer Anwendung aufbewahren. Wie @Edward in den Kommentaren unten ausführt, schützt dies jedoch effektiv vor einem Wörterbuchangriff, bei dem beispielsweise Regenbogentabellen verwendet werden.

Schließlich können Sie eine Kombination aller oben genannten Techniken verwenden.

csl
quelle
Wenn es sich um ein Passwort handelt, das der Benutzer eingeben muss, speichern Sie den Hash + Salt des Passworts. Siehe Antwort unten.
1
@hapalibashi: Wie lagern Sie das Salz sicher in Ihrer Anwendung? Ich glaube nicht, dass das OP ein Einweg-Passwort-Matching-System brauchte, sondern nur eine allgemeine Methode zum Speichern statischer Schlüssel.
CSL
2
Ich habe festgestellt, dass bei der Betrachtung zerlegter Programme normalerweise nicht sehr viele XORs vorhanden sind. Wenn Sie also XOR verwenden möchten, um etwas zu verschleiern, denken Sie daran, dass sie auf sich aufmerksam machen.
kb.
2
@kb - das ist ein interessanter Punkt. Ich würde vermuten, dass Sie bitweise ands and ors sehen würden, die viel mehr passieren als xor. a ^ b == (a & ~ b) || (~ a & b)
Jeremy Powell
4
Das Wissen um den Salzwert verschafft einem Gegner normalerweise keinen Vorteil - der Sinn des Salzes besteht darin, einen "Wörterbuchangriff" zu vermeiden, bei dem der Angreifer die Hashes für viele wahrscheinliche Eingaben vorberechnet hat. Die Verwendung eines Salzes zwingt sie, ihr Wörterbuch mit einem neuen Wörterbuch vorab zu berechnen. Wenn jedes Salz nur einmal verwendet wird, wird der Wörterbuchangriff völlig nutzlos.
Edward Dixon
8

Stellen Sie zunächst fest, dass Sie nichts tun können, was einen ausreichend entschlossenen Hacker aufhält, und es gibt viele davon. Der Schutz für jedes Spiel und jede Konsole ist irgendwann aufgehoben, daher ist dies nur eine vorübergehende Korrektur.

Es gibt 4 Dinge, die Sie tun können, um Ihre Chancen zu erhöhen, eine Weile verborgen zu bleiben.

1) Verstecken Sie die Elemente der Zeichenfolge auf irgendeine Weise - etwas Offensichtliches wie das Xoring (der Operator ^) der Zeichenfolge mit einer anderen Zeichenfolge ist gut genug, um die Suche nach der Zeichenfolge unmöglich zu machen.

2) Teilen Sie die Zeichenfolge in Teile auf - teilen Sie die Zeichenfolge auf und fügen Sie Teile davon in seltsam benannte Methoden in seltsamen Modulen ein. Machen Sie es sich nicht leicht, die Methode mit der Zeichenfolge zu durchsuchen und zu finden. Natürlich muss eine Methode alle diese Bits aufrufen, aber es macht es immer noch etwas schwieriger.

3) Erstellen Sie die Zeichenfolge niemals im Speicher - die meisten Hacker verwenden Tools, mit denen sie die Zeichenfolge im Speicher sehen können, nachdem Sie sie codiert haben. Wenn möglich, vermeiden Sie dies. Wenn Sie beispielsweise den Schlüssel an einen Server senden, senden Sie ihn zeichenweise, damit die gesamte Zeichenfolge nie vorhanden ist. Wenn Sie es mit einer RSA-Codierung verwenden, ist dies natürlich schwieriger.

4) Führen Sie einen Ad-hoc-Algorithmus durch - fügen Sie zusätzlich ein oder zwei eindeutige Wendungen hinzu. Fügen Sie einfach 1 zu allem hinzu, was Sie produzieren, oder führen Sie eine Verschlüsselung zweimal durch oder fügen Sie einen Zucker hinzu. Dies macht es für den Hacker, der bereits weiß, wonach er suchen muss, wenn jemand beispielsweise Vanilla MD5-Hashing oder RSA-Verschlüsselung verwendet, etwas schwieriger.

Stellen Sie vor allem sicher, dass es nicht zu wichtig ist, wann (und wenn Ihre Anwendung populär genug wird) Ihr Schlüssel entdeckt wird!

Chris Jefferson
quelle
5

Eine Strategie, die ich in der Vergangenheit verwendet habe, besteht darin, eine Reihe von scheinbar zufälligen Zeichen zu erstellen. Sie fügen zunächst Ihre bestimmten Zeichen ein und suchen sie dann mit einem algebraischen Prozess, wobei jeder Schritt von 0 bis N eine Zahl <Größe des Arrays ergibt, das das nächste Zeichen in Ihrer verschleierten Zeichenfolge enthält. (Diese Antwort fühlt sich jetzt verschleiert an!)

Beispiel:

Bei einer Reihe von Zeichen (Zahlen und Bindestriche dienen nur als Referenz)

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

Und eine Gleichung, deren erste sechs Ergebnisse sind: 3, 6, 7, 10, 21, 47

Würde das Wort "HALLO!" aus dem Array oben.

Paul Sasik
quelle
Gute Idee - Ich denke, Sie könnten es weiter verbessern, indem Sie nicht druckbare Zeichen im Array verwenden ...
Thomi
4

Ich stimme @Checkers zu, Ihre ausführbare Datei kann rückentwickelt werden.

Ein bisschen besser ist es, es dynamisch zu erstellen, zum Beispiel:

std::string myKey = part1() + part2() + ... + partN();
Nick Dandoulakis
quelle
Dies verhindert zwar, dass die Zeichenfolge beim Durchsuchen der Binärdatei angezeigt wird. Ihre Zeichenfolge befindet sich jedoch immer noch im Speicher. Ihre Lösung ist jedoch wahrscheinlich gut genug für das, was ich tue.
Thomi
@Thomi, du kannst es natürlich zerstören , sobald du damit fertig bist. Trotzdem ist es nicht der beste Weg, mit sensiblen Zeichenfolgen umzugehen.
Nick Dandoulakis
... da die Zerstörung nicht garantiert, dass der Speicher sofort wiederverwendet wird.
Thomi
4

Das Speichern privater Daten in Software, die an den Benutzer gesendet wird, ist natürlich immer ein Risiko. Jeder ausreichend ausgebildete (und engagierte) Ingenieur kann die Daten rückentwickeln.

Abgesehen davon können Sie häufig die Sicherheit erhöhen, indem Sie die Barriere erhöhen, die die Benutzer überwinden müssen, um Ihre privaten Daten preiszugeben. Das ist normalerweise ein guter Kompromiss.

In Ihrem Fall könnten Sie Ihre Zeichenfolgen mit nicht druckbaren Daten überladen und diese dann zur Laufzeit mithilfe einer einfachen Hilfsfunktion wie folgt dekodieren:

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;
    // ...
}
Frerich Raabe
quelle
4

Ich habe ein einfaches Verschlüsselungswerkzeug für Zeichenfolgen erstellt. Es kann automatisch verschlüsselte Zeichenfolgen generieren und verfügt über einige zusätzliche Optionen, einige Beispiele:

Zeichenfolge als globale Variable:

// 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;

Als Unicode-String mit Entschlüsselungsschleife:

// 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;

Zeichenfolge als globale Variable:

// 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;
Bartosz Wójcik
quelle
Nein, ich habe die Website stringencrypt.com verwendet , um die Arbeit zu erledigen. Es enthält Beispiele für C / C ++ stringencrypt.com/c-cpp-encryption, die Sie möglicherweise zur Automatisierung der einfachen Zeichenfolgenverschlüsselung verwenden können.
Bartosz Wójcik
2

Etwas abhängig von dem, was Sie schützen wollen, wie Joshperry hervorhebt. Aus Erfahrung würde ich sagen, wenn es Teil eines Lizenzierungsschemas zum Schutz Ihrer Software ist, dann stören Sie sich nicht. Sie werden es eventuell zurückentwickeln. Verwenden Sie einfach eine einfache Chiffre wie ROT-13, um sie vor einfachen Angriffen zu schützen (darüber laufende Strings). Wenn es darum geht, sensible Daten für Benutzer zu schützen, würde ich mich fragen, ob der Schutz dieser Daten mit einem lokal gespeicherten privaten Schlüssel sinnvoll ist. Wieder kommt es darauf an, was Sie schützen wollen.

EDIT: Wenn Sie es tun wollen, dann ist eine Kombination von Techniken, auf die Chris hinweist, weitaus besser als rot13.

Nic Strong
quelle
2

Wie bereits gesagt, gibt es keine Möglichkeit, Ihre Saite vollständig zu schützen. Es gibt jedoch Möglichkeiten, es mit angemessener Sicherheit zu schützen.

Als ich dies tun musste, habe ich eine unschuldig aussehende Zeichenfolge in den Code eingefügt (z. B. einen Copyright-Hinweis oder eine gefälschte Benutzeraufforderung oder irgendetwas anderes, das nicht von jemandem geändert wird, der nicht verwandten Code repariert), und diese mit sich selbst verschlüsselt Als Schlüssel habe ich das gehasht (etwas Salz hinzugefügt) und das Ergebnis als Schlüssel verwendet, um das zu verschlüsseln, was ich eigentlich verschlüsseln wollte.

Natürlich könnte dies gehackt werden, aber es braucht einen entschlossenen Hacker, um dies zu tun.

sbi
quelle
Gute Idee - eine andere Form der Dunkelheit ist die Verwendung einer Saite, die noch einigermaßen stark ist (lang, Interpunktion und all dieser Jazz), aber offensichtlich nicht wie ein Passwort aussieht.
Thomi
1

Wenn Sie unter Windows-Benutzer DPAPI arbeiten, rufen Sie http://msdn.microsoft.com/en-us/library/ms995355.aspx auf

Wie bereits in einem früheren Beitrag erwähnt, verwenden Sie den Schlüsselbund, wenn Sie einen Mac verwenden.

Grundsätzlich sind all diese niedlichen Ideen, wie Sie Ihren privaten Schlüssel in Ihrer Binärdatei speichern können, aus Sicherheitsgründen so schlecht, dass Sie sie nicht tun sollten. Jeder, der Ihren privaten Schlüssel erhält, ist eine große Sache. Behalten Sie ihn nicht in Ihrem Programm. Abhängig davon, wie wichtig Ihre App ist, können Sie Ihre privaten Schlüssel auf einer Smartcard, auf einem Remotecomputer, mit dem Ihr Code kommuniziert, aufbewahren oder das tun, was die meisten Benutzer tun, und sie an einem sehr sicheren Ort auf dem lokalen Computer aufbewahren (den "Schlüssel" store "(das ist wie eine seltsame sichere Registrierung), die durch Berechtigungen und die ganze Stärke Ihres Betriebssystems geschützt ist.

Dies ist ein gelöstes Problem und die Antwort ist NICHT, den Schlüssel in Ihrem Programm zu behalten :)

Collin
quelle
1

Versuchen Sie dies . Im Quellcode wird erläutert, wie alle Zeichenfolgen in einem bestimmten Visual Studio c ++ - Projekt im laufenden Betrieb verschlüsselt und entschlüsselt werden.

Michael Haephrati
quelle
1

Eine Methode, die ich kürzlich ausprobiert habe, ist:

  1. Nehmen Sie den Hash (SHA256) der privaten Daten und füllen Sie ihn im Code als aus part1
  2. Nehmen Sie XOR von privaten Daten und deren Hash und füllen Sie sie in Code als part2
  3. Daten füllen: Speichern Sie sie nicht als char str [], sondern füllen Sie sie zur Laufzeit mithilfe von Zuweisungsanweisungen (wie im Makro unten gezeigt).
  4. Generieren Sie nun die privaten Daten zur Laufzeit, indem Sie das XOR von part1und verwendenpart2
  5. Zusätzlicher Schritt : Berechnen Sie den Hash der generierten Daten und vergleichen Sie ihn mit part1. Es wird die Integrität privater Daten überprüft.

MAKRO zum Auffüllen von Daten:

Angenommen, private Daten bestehen aus 4 Bytes. Wir definieren dafür ein Makro, das die Daten mit Zuweisungsanweisungen in zufälliger Reihenfolge speichert.

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

Verwenden Sie dieses Makro nun in Code, in dem Sie speichern müssen, part1und part2wie folgt:

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

Anstatt einen privaten Schlüssel in Ihrer ausführbaren Datei zu speichern, möchten Sie ihn möglicherweise vom Benutzer anfordern und über einen externen Kennwortmanager speichern , ähnlich wie bei Mac OS X Keychain Access.

Mouviciel
quelle
Nun ja und nein. Normalerweise stimme ich Ihnen zu, aber in diesem Fall versuche ich, dies vor dem Benutzer der Software zu verbergen. Daher ist es keine gute Idee, sie in einem externen System zu speichern (viele Schlüsselbundsysteme können dies Kennwörter als Klartext für Benutzer verfügbar machen, die über eine entsprechende Berechtigung verfügen). Die Schlüsselbundsoftware eignet sich hervorragend für Benutzerkennwörter, nicht jedoch für Anwendungsverschlüsselungsschlüssel.
Thomi
Wenn es sich unsicher anfühlt (obwohl es angesichts Ihrer Klarstellungen vielleicht angemessen ist), können Sie einen Schlüsselbund und etwas
0

Kontextabhängig, aber Sie können einfach den Hash des Schlüssels plus ein Salz speichern (konstante Zeichenfolge, leicht zu verdecken).

Wenn der Benutzer den Schlüssel eingibt, fügen Sie das Salz hinzu , berechnen den Hash und vergleichen.

Das Salz ist in diesem Fall wahrscheinlich nicht erforderlich. Es stoppt einen Brute-Force-Wörterbuchangriff, wenn der Hash isoliert werden kann (eine Google-Suche funktioniert ebenfalls).

Ein Hacker muss immer noch irgendwo eine jmp-Anweisung einfügen, um das ganze Los zu umgehen, aber das ist etwas komplizierter als eine einfache Textsuche.


quelle
Dies ist ein Verschlüsselungsschlüssel, kein Passwort-Hash. Ich benötige den eigentlichen Schlüssel zum Kodieren und Dekodieren von Daten. Der Benutzer sieht den Schlüssel nie, er wird nie außerhalb der Binärdatei gespeichert.
Thomi
0

Es gibt ein (sehr leicht) Kopf nur Projekt obfuscate von adamyaxley gefertigt, die perfekt funktioniert. Es basiert auf Lambda-Funktionen und Makros und verschlüsselt Zeichenfolgen zur Kompilierungszeit mit einer XOR-Verschlüsselung. Bei Bedarf können wir den Startwert für jede Zeichenfolge ändern.

Der folgende Code speichert die Zeichenfolge "Hallo Welt" nicht in der kompilierten Binärdatei.

#include "obfuscate.h"

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

Ich habe mit C ++ 17 und Visual Studio 2019 getestet und überprüfe über IDA, ob die Zeichenfolge ausgeblendet ist. Ein wertvoller Vorteil gegenüber ADVobfuscator ist, dass es in einen std :: string konvertierbar ist (während es immer noch in der kompilierten Binärdatei versteckt ist):

std::string var = AY_OBFUSCATE("string");
Malick
quelle