Forum: PC-Programmierung Ver- und Entschlüsselung mit OPENSSL in C


von Robert B. (rsb89)


Lesenswert?

Hallo zusammen,

ich möchte einige versuche bezüglich Ver- und Entschlüsselung machen und 
benutze dafür den OPENSSL-Stack. Einige Sachen habe ich auch schon 
hinbekommen, aber es gibt so Ecken bei denen es hakt und ich hoffe, dass 
mir hier jemand helfen kann.

Ich versuche gerade mit der Funktion
1
void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, size_t length, const AES_KEY *key, unsigned char *ivec, const int enc);
etwas zu verschlüsseln, nur ist mir die Bedeutung der letzten beiden 
Parameter nicht klar. Mit AES_encrypt() und AES_decrypt() läuft es 
bereits, aber welcher Modus wird da verwendet?

von Εrnst B. (ernst)


Lesenswert?

"enc" ist ein Flag, AES_DECRYPT oder AES_ENCRYPT, dass sagt, was gemacht 
werden soll.

"ivec" ist der initialization vector. (16 Byte IIRC). Beim ersten Aufruf 
(beliebig, aber für En- und Decrypt gleich) initialisieren.

von Robert B. (rsb89)


Lesenswert?

Danke für die schnelle Antwort!

Εrnst B✶ schrieb:
> "ivec" ist der initialization vector. (16 Byte IIRC). Beim ersten Aufruf
> (beliebig, aber für En- und Decrypt gleich) initialisieren.

Was wird denn initialisiert? Gebe ich da eine beliebige Zeichenfolge 
(mit länge des Schlüssels nehme ich an) an? So richtig steig ich da noch 
nicht hinter :-/

: Bearbeitet durch User
von ConverstQuestionsToAnswers (Gast)


Lesenswert?

"CBC" ist der Cipher Block Chaining Modus.

In ihm wird der jeweils vorhergehende chiffrierte Block mit dem 
aktuellen Klartext XOder-Verknüpft und der enstehende Block 
chiffrieriert.

Dabei entsteht das Problem, womit denn der erster Block des Klartextes 
XOder-Verknüpft wird. Dafür nimmt man einen Initialisierungsvektor.
Im allgemeinen ist das eine zufällige Zahl oder ein Zeitstempel. Schau 
mal selbst wie das bei SSL (neuer Begriff "TLS") ist.

Ein Diagramm (nebst einer Erklärung) siehst Du hier: 
http://de.wikipedia.org/wiki/Cipher_Block_Chaining_Mode

von Robert B. (rsb89)


Lesenswert?

Danke, das Diagramm ist super! Jetzt wird mir einiges klarer.

von Stefan R. (srand)


Lesenswert?

Εrnst B✶ schrieb:
> Beim ersten Aufruf
> (beliebig, aber für En- und Decrypt gleich) initialisieren.

Nein. Zufällig, nicht beliebig.

Wenns nicht nur Spielerei ist, sondern was ernsthaftes, sollte der OP 
aber tunlichst die Finger von OpenSSL lassen und NaCL, Keyczar oder 
cryptlib verwenden.

von Robert B. (rsb89)


Lesenswert?

Stefan Rand schrieb:
> Wenns nicht nur Spielerei ist, sondern was ernsthaftes, sollte der OP
> aber tunlichst die Finger von OpenSSL lassen und NaCL, Keyczar oder
> cryptlib verwenden.

Danke für den Tip, es ist aber nichts ernsthaftes. Aber vielleicht 
kannst du noch sagen warum man eher die anderen nehmen sollte?

von ConvertsQuestionsToAnswers (Gast)


Lesenswert?

> ...warum man eher die anderen nehmen sollte?

Das lässt sich in Kürze nicht so leicht beantworten wenn man 
gleichzeitig die Begründungen dafür verständlich darstellen will. Ich 
selbst bin eigentlich nur in der Lage gewisse Grundlagen darzustellen.

Einfacher ist natürlich die Behauptung XYZ sei besser als ABC. Ob Du 
Dich dann auf den, der diese Behauptung aufstellt, verlassen kannst ist 
dann eine weitere Frage.

Eine allgemeine Antwort wird darauf hinauslaufen, das sich die 
Benutzbarkeit, vor allem aber die Sicherheit der Bibliothek selbst 
voneinander unterscheiden. Letzteres ist wesentlich, denn was nützt Dir 
die schönste Verschlüsselung am Netz, wenn der Code selbst angreifbar 
ist (sagen wir wegen Pufferüberläufen)?

Falls Du das ernsthaft selbst wissen willst, empfehle ich Dir die Namen 
der genannten Bibliotheken als Suchworte zu benutzen und auf den 
Projektseiten die Selbstdarstellungen zu lesen.


Es gibt dabei drei elementare Schwierigkeiten:

1. Es ist fast unvermeidbar, dass Du einigermaßen gut Englisch kannst 
oder willens bist es zu lernen. Das ist eine gute Gelegenheit dazu, wenn 
auch nicht die allerbeste da noch die zweite Schwierigkeit hinzukommt.

2. Du solltest schon weitreichendere Kenntnisse in Mathematik 
(insbesondere der Zahlentheorie und der Gruppen und Körper) haben oder 
willens sein, Dir sie anzueignen. Das ist der steinige Teil. Ein gut 
Teil der Mathematik in der Kryptografie hält sich weit jenseits der 
Schulmathematik auf, selbst der in der 13. Klasse des Gymnasiums 
gelehrten.

3. Deine Kenntnisse der Programmierung, insbesondere von Datenstrukturen 
und Algorithmen sollte deutlich über Anfängerniveau hinausgehen oder Du 
solltest willens sein sie zu erwerben. Eine Erfahrung von mehr als drei 
Jahren beim Schreiben von realen Anwendungen währe meiner Ansicht nach 
die Richtschnur.

Ich will damit sagen, das Du Dich entscheiden musst, ob Du in das Thema 
einsteigst oder nicht. Wenn ja, dann mache Dich auf eine längere Reise 
gefasst. Willst Du nur mal ein bisschen spielen aber keine echte 
Anwendung im Netz haben, dann reicht die Spielerei mit irgendeiner 
Bibliothek.

Du wirst HIER nur zufällig jemanden finden, der bereit ist, Dir eine 
komplette aber kurze und dennoch nachvollziehbaren Vergleich der 
Bibliotheken zu geben. Das würde in eine ziemliche Arbeit ausarten.


Ein Mittelweg wäre die suche nach einem Forum, das sich speziell mit 
Kryptographie beschäftigt. Ein Ansatz wäre mal die Suche in den yahoo- 
oder google-Gruppen.

von Stefan R. (srand)


Lesenswert?

Robert B. schrieb:
> Stefan Rand schrieb:
>> Wenns nicht nur Spielerei ist, sondern was ernsthaftes, sollte der OP
>> aber tunlichst die Finger von OpenSSL lassen und NaCL, Keyczar oder
>> cryptlib verwenden.
>
> Danke für den Tip, es ist aber nichts ernsthaftes. Aber vielleicht
> kannst du noch sagen warum man eher die anderen nehmen sollte?

Weil du die Kryptoprimitiven aus Low-Level-Bibliotheken wie OpenSSL mit 
an Sicherheit grenzender Wahrscheinlichkeit nicht korrekt zu einem 
sicheren System zusammengebaut bekommst.

Ich übrigens auch nicht. Und auch sonst niemand, der hier mitliest.

Deswegen verwendet man als normaler Entwickler High-Level-Bibliotheken, 
die grob gesagt nur "encrypt" und "decrypt" anbieten, ohne daß du bei 
Auswahl des IV, Nonce, Verschlüsselungsmodus oder an drei Millionen 
anderen Stellen ein kleines Detail falsch machst, woraufhin dein 
"AES-256-gesichertes System" mittels einer Skriptsprache und dreißig 
Sekunden Rechenzeit vollständig gebrochen wird.

cryptlib von Peter Gutmann ist uralt und hat einen exzellenten Ruf.

Keyczar von Google hat den Charme, für Java und Python verfügbar zu 
sein, hatte kürzlich eine wirklich peinliche Timing-Attacke gegen sich, 
aber die Leute da sind trotzdem absolut kompetent.

Und NaCL von djb ist... halt djb. Ungewöhnliche Algorithmen, Liebe zum 
Detail. Bizarr, aber gut.

von Stefan R. (srand)


Lesenswert?

Und falls jemand mal sehen will, was bei der Implementierung so in die 
Hose gehen kann, sollte er das hier mitmachen. Highly recommended!

http://www.matasano.com/articles/crypto-challenges/

von Stefan R. (srand)


Lesenswert?

Stefan Rand schrieb:
> hatte kürzlich eine wirklich peinliche Timing-Attacke gegen sich

Die ist übrigens sehr erhellend und leicht zu begreifen.

Hand aufs Herz: wer hätte spontan gewußt, daß ein simpler Vergleich 
zweier Bytestrings so falsch gemacht werden kann, daß das System 
anschließend komplett gebrochen ist?

Und dummerweise ist diese katastrophal falsche Art genau die simple Art, 
die jeder zuerst programmieren würde:
1
    return self.Sign(msg) == sig_bytes

Und der Fix war dann...
1
    correctMac = self.Sign(msg)
2
    if len(correctMac) != len(sig_bytes):
3
        return False
4
    result = 0
5
    for x, y in zip(correctMac, sig_bytes):
6
        result |= ord(x) ^ ord(y)
7
    return result == 0
Autsch!

von Robert B. (rsb89)


Lesenswert?

Danke Stefan, das leuchtet natürlich ein!

Ich hänge nun bei den publickey-Verfahren, und zwar bei RSA.
1
//seed Random-Number-Generator
2
  err = RAND_poll(); 
3
4
  rsa = RSA_new();
5
  bn = BN_new();
6
  BN_dec2bn(&bn, EXPONENT);
7
8
  err = RSA_generate_key_ex(rsa, KEYSIZE, bn, NULL);
9
10
  encdata = (char *)malloc(datasize+(KEYSIZE/8)+1);
11
  decdata = (char *)malloc(datasize+1);
12
13
  err = RSA_private_encrypt(datasize+1, (unsigned char *)plaindata, (unsigned char *)encdata, rsa, RSA_NO_PADDING);
14
  err = RSA_public_decrypt(datasize+(KEYSIZE/8)+1, (unsigned char *)encdata, (unsigned char *)decdata, rsa, RSA_NO_PADDING);

Die Encryption-(und Decryption-)Funktion geben beide -1 zurück. Was 
mache ich nur falsch? :-/

von Robert B. (rsb89)


Lesenswert?

Habe es nun hinbekommen und die Lösung gleich posten! Muss erstmal alles 
sortieren ;)

von Robert B. (rsb89)


Lesenswert?

Falls es jemandem hilft:
1
  rsa = RSA_new();
2
  bn = BN_new();
3
  BN_dec2bn(&bn, EXPONENT);
4
5
  err = RSA_generate_key_ex(rsa, KEYSIZE, bn, NULL);
6
7
  encdata = (char *)malloc(RSA_size(rsa));
8
  decdata = (char *)malloc(datasize+1);
9
10
  err = RSA_public_encrypt(strlen(plaindata), (unsigned char *)plaindata, (unsigned char *)encdata, rsa,  RSA_PKCS1_OAEP_PADDING);
11
  err = RSA_private_decrypt(KEYSIZE/8, (unsigned char *)encdata, (unsigned char *)decdata, rsa, RSA_PKCS1_OAEP_PADDING);

Der Fehler lag im letzten Parameter der encryption bzw decryption-Fkt.

von Robert B. (rsb89)


Lesenswert?

Erstmal ein frohes und gesundes neues Jahr an alle hier im Forum!

Ich war mir ehrlich gesagt unsicher ob ich einen neuen Thread hierfür 
aufmachen soll, aber eigentlich passt mein Problem noch unter den Titel.

Also ich versuche mich nun mit "Elliptic Curve Diffie Hellman" bei 
OpenSSL, hänge aber auch hier wieder etwas.

Ich orientiere mich an folgendem Beispiel:
1
unsigned char *ecdh_low(size_t *secret_len)
2
{
3
  EC_KEY *key, *peerkey;
4
  int field_size;
5
  unsigned char *secret;
6
7
  /* Create an Elliptic Curve Key object and set it up to use the ANSI X9.62 Prime 256v1 curve */
8
  if(NULL == (key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1))) handleErrors();
9
10
  /* Generate the private and public key */
11
  if(1 != EC_KEY_generate_key(key)) handleErrors();
12
13
  /* Get the peer's public key, and provide the peer with our public key -
14
   * how this is done will be specific to your circumstances */
15
  peerkey = get_peerkey_low(key);
16
17
  /* Calculate the size of the buffer for the shared secret */
18
  field_size = EC_GROUP_get_degree(EC_KEY_get0_group(key));
19
  *secret_len = (field_size+7)/8;
20
21
  /* Allocate the memory for the shared secret */
22
  if(NULL == (secret = OPENSSL_malloc(*secret_len))) handleErrors();
23
24
  /* Derive the shared secret */
25
  *secret_len = ECDH_compute_key(secret, *secret_len, EC_KEY_get0_public_key(peerkey),
26
            key, NULL);
27
28
  /* Clean up */
29
  EC_KEY_free(key);
30
  EC_KEY_free(peerkey);
31
32
  if(*secret_len <= 0)
33
  {
34
    OPENSSL_free(secret);
35
    return NULL;
36
  }
37
38
  return secret;
39
}

Bis zu der Stelle wo "peerkey" auftaucht ist mir die Sache klar. Aber 
was ist nun dieser Peerkey? Man möchte mit ECDH ja etwas erzeugen, 
woraus der Partner dann einen Schlüssel generieren kann. Dieses "etwas" 
ist, wenn ich das richtig verstanden habe die Variable "secret", die am 
ende zurück gegeben wird. "key" ist der nur mir bekannte Schlüssel. Aber 
was ist dann der Peerkey in diesem Beispiel?

von Hans Ulli K. (Gast)


Lesenswert?

Robert B. schrieb:
> Bis zu der Stelle wo "peerkey" auftaucht ist mir die Sache klar. Aber
> was ist nun dieser Peerkey? Man möchte mit ECDH ja etwas erzeugen,
> woraus der Partner dann einen Schlüssel generieren kann. Dieses "etwas"
> ist, wenn ich das richtig verstanden habe die Variable "secret", die am
> ende zurück gegeben wird. "key" ist der nur mir bekannte Schlüssel. Aber
> was ist dann der Peerkey in diesem Beispiel?

Steht doch schon da

>   /* Get the peer's public key, and provide the peer with our public key
> -
>    * how this is done will be specific to your circumstances */
>   peerkey = get_peerkey_low(key);

Hier passiert der Schlüsseltausch.
Entweder Diffie Hellmann oder RSA.

peerkey ist der öffentliche Schlüssel von deinem Gegenüber und der will 
ja deinen öffentlichen Schlüsssel haben.

Der Rest ist im Web zu finden

von Robert B. (rsb89)


Lesenswert?

Danke! Da stand ich ganz schön auf dem Schlauch...

von Hans Ulli K. (Gast)


Lesenswert?

Hier mal der Crypto Talk vom letzten CCC Treffen in Hamburg.

www.youtube.com/watch?v=HJB1mYEZPPA

Beachte mal die Sache mit Lavabit aka Snoden Mailserver, so ab der 19 
Minute.

Versuche das mal zu verstehen. Mir ist danach die Kinnlade 
heruntergefallen. ;-)

Link vergessen

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.