Daten verschlüsselt übertragen zum Webspace

  • 16 Antworten
  • Neuester Beitrag
Diskutiere Daten verschlüsselt übertragen zum Webspace im Android App Entwicklung im Bereich Betriebssysteme & Apps.
1

123thomas

Fortgeschrittenes Mitglied
Hallo Leute,

ich habe mal wieder eine Frage.

Ich habe eine App die mit einer Webseite kommuniziert. Nun möchte ich allerdings ein Login einbauen und das Passwort verschlüsselt übergeben. Das Problem ist, dass mein Webspace kein https anbietet.

Gibt es eine gute Verschlüsselung die in Java und PHP umgesetzt werden kann oder muss ich mir selber eine bauen?

Mit freundlichen Grüßen
Thomas
 
swa00

swa00

Moderator
Teammitglied
Wie wärs mit AES ???

wenn du den Source brauchst ( beide seiten ) bitte PN
 
Kiwi++Soft

Kiwi++Soft

Ehrenmitglied
Ich würde eher eine Public/Privat Key Verschlüsselung empfehlen, denn sonst müsste in der Client-APP der KEY enthalten sein, denn man dann leicht heraus finden kann.

Bei PublicKey/Private Key wäre im Client nur der Public Key enthalten, und mit dem kann man man an den Server gesendete Nachrichten entschlüsseln.

Als Bibliothek würde sich Bouncy Castle empfehlen, da sind die wichtigsten Verschlüsselung-Algrithem enthalten und ist OpenSource
 
Zuletzt bearbeitet:
markus.tullius

markus.tullius

Experte
Noch ein Nachtrag:

Beide Vorschläge funktionieren nur, wenn Du die komplette Übertragung verschlüsselst. Sonst ist der Akt völlig sinnlos, da das verschlüsselte Passwort der eigentliche Schlüssel ist. Und das wird dann ohne Schutz übertragen.

Bevor du die komplette Kommunikation selber verschlüsselst, solltest Du Dir ein Webspace suchen, der HTTPS unterstützt.
Wie oben gesehen, kann man recht viel bei der Verschlüsselung falsch machen, und die ganze Sache konterkarieren.
-- Dieser Beitrag wurde automatisch mit dem folgenden Beitrag zusammengeführt --
---
Außerdem muss man bei einer AES - Verschlüsselung den Key nicht fest im Programmcode speichern. Man kann zum Beispiel das Passwort als Key benutzen. Mache ich wenigsten so.
 
1

123thomas

Fortgeschrittenes Mitglied
Danke für die Hilfe.

Das mit dem HTTPS Webspace lohnt sich nicht, da die App nur für ausgewählte Benutzer sein soll. Das verschlüsseln dient nur dazu, dass der Ottonormalverbraucher (Die Benutzer sind alles Leute die mit Programmieren nichts zu tun haben) nicht mit irgendeiner Sniff App das Passwort abfangen kann.

Gruß Thomas
 
Kiwi++Soft

Kiwi++Soft

Ehrenmitglied
markus.tullius schrieb:
Außerdem muss man bei einer AES - Verschlüsselung den Key nicht fest im Programmcode speichern. Man kann zum Beispiel das Passwort als Key benutzen. Mache ich wenigsten so.
Ist zwar (leider) oft gelebte Praxis, aber ein potentieller Schwachpunkt in der Verschlüsselung. Professionelle Verschlüsselungsstandards raten davon ab!

Wenn man es so machen sollte, sollte man zumindest ein Password-Policy einführen, die eine Mindest-Länge der Passwörter und auch eine gewisse Komplexität (Groß/Klein, Nummern, Sonderzeichen) erfordert. Ebenso sollte ein regelmäßiger Passwort-Wechsel erzwungen werden.

Eine recht sichere Verschlüsselung erreicht man, wenn der Client einen 'Per-Session-Key' für jede neue Session mit einem 'Secure-Random' erzeugt. Dieser 'Pro-Session-Schlüssel' muss dann nur einmal vom Client an den Server übertragen werden. 'State of the Art' ist hierzu die Verschlüsselung mit dem 'Public-Key' des Servers (das vom Server unverschlüsselt als Server-Zertifikat an den Client übertragen werden kann, und daher auch bei einem (wichtig, regelmäßig durchführen!) Zertifikat-Wechsel immer aktuell auf dem Client zur Verfügung steht) oder mit einem Diffie-Hellmann Verfahren übertragen werden kann.
 
swa00

swa00

Moderator
Teammitglied
Moin Moin :)

ich widerspreche weder Markus, noch Kiwi.

Es stellt sich bei der Entwicklung jedoch die Frage, welcher Aufwand für welchen Zweck.
Geht es ausschliesslich darum , ein Passwort als Key zu benutzen, es intern auf dem Device in den Prefs ( meinetwegen schon verschlüsselt) und dann
das Login als AES durch die Welt zu schicken um lediglich ein Compare auf Server-Seite durchzuführen und nicht im Klartext, dann reicht mMn es völlig aus
das so simpel zu tun. (Obwohl unsicher ist es ja nicht gerade)

Ok, man könnte jetzt sagen : "Wenn ich aber das Device in der Hand habe , dann kann ich alles" - da gibt es aber auch mehrere Szenarien , die man sich ausmalen könnte :)



Ich denke , das ist auch das, was Thomas wollte
 
Zuletzt bearbeitet:
markus.tullius

markus.tullius

Experte
@swa00,

es reicht nicht einfach nur ein verschlüsseltes Passwort zu übertragen. Jeder kann ein HTTP-Übertragung kopieren, wenn er sich ein bisschen Mühe gibt. Wenn jetzt jemand die Kopie an den Server überträgt, bekomme dieser die gleiche Antwort, wie der eigentliche Benutzer (Der Server konnte auch diesmal das Passwort richtig entschlüsseln).
Außerdem kann man auch die unverschlüsselte Antwort einfach mit scheiden.:)
Das heißt, man verschlüsselt entweder die gesamte Kommunikation (Anfrage und Antwort), oder man lässt es gleich ganz. ;)
Alles andere macht es einen Angreifer viel zu einfach.

@Kiwi++Soft

Eine Password-Policy ist ein zweischneidiges Schwert. Jede zusätzliche Regel reduziert die Anzahl der möglichen Passwörter.
Insbesondere wenn ein Mensch dieses Passwort festlegt.
(Regel: mindestens eine Zahl, ein Zeichen muss großgeschrieben werden - Wahrscheinlichste Variante: "Password123" ).

Deine Verschlüsselung - Variante gefällt mir immer wieder. Sie ist relativ einfach, und sehr sicher. :thumbup:
 
swa00

swa00

Moderator
Teammitglied
Moin Markus,

öhm, natürlich gehe ich davon aus , dass man das "Frage-Antwort" spiel als Basis benutzt - ansonsten macht das Ganze NULL sinn.
Ich bin bei Thomas davon ausgegangen, dass er gerne erst mal das ganze Graffel als java & php benötigt - ich will jetzt hoffen , dass er mit dem von mir
zugeschickten Klassen auch sinnvoll umsetzt :)

Bis dato hat er sich nicht wieder gemeldet :)
 
1

123thomas

Fortgeschrittenes Mitglied
swa00 schrieb:
Moin Markus,

öhm, natürlich gehe ich davon aus , dass man das "Frage-Antwort" spiel als Basis benutzt - ansonsten macht das Ganze NULL sinn.
Ich bin bei Thomas davon ausgegangen, dass er gerne erst mal das ganze Graffel als java & php benötigt - ich will jetzt hoffen , dass er mit dem von mir
zugeschickten Klassen auch sinnvoll umsetzt :)

Bis dato hat er sich nicht wieder gemeldet :)
Hallo, was meint ihr mit Frage Antwort?

Also ich habe nun AES benutzt. Ich habe das so gelöst, dass einmal das php Script und die App den Key hat. Das hin und her schicken ist nur verschlüsselt, so brauch ich nichts unverschlüsselt senden.

Ich weiß das wenn man die App decompilieren würde den Key dann auslesen kann. Aber von meinen Anwendern macht sich keiner die Mühe bzw. kann es keiner. Oder gibt es noch eine sichere Methode, die aber auch einfach ist?

Oder habe ich da was falsch verstanden?

Gruß
 
Kiwi++Soft

Kiwi++Soft

Ehrenmitglied
Mit Frage-Antwort ist gemeint, dass der Client nicht einfach verschlüsselt das Passwort an den Server schickt, dann dann ein Hacker, der das Paket abfängt, das gleiche Paket schicken kann, und damit als der selbe Client identifiziert ist, sondern dass der Server vorher ein 'immer unterschiedliches Paket' schickt (z.B. den aktuellen Server-Timestamp), dessen Inhalt beim Senden des Passworts mit enthalten sein muss. Dann nutzt das Abfangen des Passwort-Pakets nichts, da der Server zum Einloggen des nächsten eben wieder ein (diesmal anderes) Paket schickt, das beim Passwort mit enthalten sein muss, und somit das 'vorher abgefangene' Paket nicht zum Einloggen verwendet werden kann.

Diese Verfahren nennt man eine 'Challange'-basierte Authentisierung.
 
markus.tullius

markus.tullius

Experte
swa00 schrieb:
Ich bin bei Thomas davon ausgegangen, dass er gerne erst mal das ganze Graffel als java & php benötigt - ich will jetzt hoffen , dass er mit dem von mir
zugeschickten Klassen auch sinnvoll umsetzt :)
Hallo, es wäre nett, wenn du das "ganze Geraffel" einfach noch mal im Thread öffentlich posten könntest. Vielen Dank schon mal in voraus. :)
 
swa00

swa00

Moderator
Teammitglied
Lieber Markus , anbei Geraffel 1 &2 :)

Java Geraffel :

Code:
import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

///////////////////////////////////////////////////////////////////////////////////////////////////
public class AESCrypt {

    private String AESiv        = "FBn=v\\qkn?H#%9rd";
    private String AESKey       = "0123456789abcdef";//Dummy secretKey (CHANGE IT!)

    private IvParameterSpec ivspec;
    private SecretKeySpec keyspec;
    private Cipher cipher;


    ///////////////////////////////////////////////////////////////////////////////////////////////
    public AESCrypt(String in_password)
    {

        AESKey = in_password;


        ivspec = new IvParameterSpec(AESiv.getBytes());

        keyspec = new SecretKeySpec(AESKey.getBytes(), "AES");

        try {
            cipher = Cipher.getInstance("AES/CBC/NoPadding");
        } catch (NoSuchAlgorithmException e)
        {

            e.printStackTrace();
        } catch (NoSuchPaddingException e) {

            e.printStackTrace();
        }
    }
    ///////////////////////////////////////////////////////////////////////////////////////////////
    public byte[] encrypt(String text) throws Exception
    {
        if(text == null || text.length() == 0)
            throw new Exception("Empty string");

        byte[] encrypted = null;

        try {
            cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);

            encrypted = cipher.doFinal(padString(text).getBytes());
        } catch (Exception e)
        {
            throw new Exception("[encrypt] " + e.getMessage());
        }

        return encrypted;
    }
    ///////////////////////////////////////////////////////////////////////////////////////////////
    public byte[] decrypt(String code) throws Exception
    {
        if(code == null || code.length() == 0)
            throw new Exception("Empty string");

        byte[] decrypted = null;

        try {
            cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);

            decrypted = cipher.doFinal(hexToBytes(code));
        } catch (Exception e)
        {
            throw new Exception("[decrypt] " + e.getMessage());
        }
        return decrypted;
    }


    ///////////////////////////////////////////////////////////////////////////////////////////////
    public static String bytesToHex(byte[] data)
    {
        if (data==null)
        {
            return null;
        }

        int len = data.length;
        String str = "";
        for (int i=0; i<len; i++) {
            if ((data[i]&0xFF)<16)
                str = str + "0" + java.lang.Integer.toHexString(data[i]&0xFF);
            else
                str = str + java.lang.Integer.toHexString(data[i]&0xFF);
        }
        return str;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////
    public static byte[] hexToBytes(String str) {
        if (str==null) {
            return null;
        } else if (str.length() < 2) {
            return null;
        } else {
            int len = str.length() / 2;
            byte[] buffer = new byte[len];
            for (int i=0; i<len; i++) {
                buffer[i] = (byte) Integer.parseInt(str.substring(i*2,i*2+2),16);
            }
            return buffer;
        }
    }


    ///////////////////////////////////////////////////////////////////////////////////////////////
    private static String padString(String source)
    {
        char paddingChar = ' ';
        int size = 16;
        int x = source.length() % size;
        int padLength = size - x;

        for (int i = 0; i < padLength; i++)
        {
            source += paddingChar;
        }

        return source;
    }
}
und PHP Geraffel

PHP:
<?php

        class AESCrypt
        {
                private $iv  = '';
                private $key = '';
               
                /////////////////////////////////////////////////////////////////////////
                function __construct($in_iv,$in_key)
                {
                  $this->iv  = $in_iv; 
                  $this->key = $in_key; 
                }
               
                /////////////////////////////////////////////////////////////////////////
                function encrypt($str)
                 {
                  $iv = $this->iv;
                  $key = $this->key;
                 
                  $td = mcrypt_module_open('rijndael-128', '', 'cbc', $iv);

                  mcrypt_generic_init($td, $key, $iv);
                  $encrypted = mcrypt_generic($td, $str);

                  mcrypt_generic_deinit($td);
                  mcrypt_module_close($td);

                  return bin2hex($encrypted);
                }
               
                /////////////////////////////////////////////////////////////////////////
                function decrypt($code)
                 {
             
                  $code = $this->hex2bin($code);
                  $iv = $this->iv;
                  $key = $this->key;

                  $td = mcrypt_module_open('rijndael-128', '', 'cbc', $iv);

                  mcrypt_generic_init($td, $key, $iv);
                  $decrypted = mdecrypt_generic($td, $code);

                  mcrypt_generic_deinit($td);
                  mcrypt_module_close($td);

                  return utf8_encode(trim($decrypted));
                }
               
                /////////////////////////////////////////////////////////////////////////
                protected function hex2bin($hexdata)
                {
                  $bindata = '';

                  for ($i = 0; $i < strlen($hexdata); $i += 2) {
                        $bindata .= chr(hexdec(substr($hexdata, $i, 2)));
                  }

                  return $bindata;
                }
        }
        ?>

lg
Stefan
 
markus.tullius

markus.tullius

Experte
@123thomas

Ich hänge noch mal den Link zum Original des Codes von swa00 an, für den Fall das jemand noch die Diskussion dazu lesen möchten.
Encrypt / Decrypt Between Android and PHP - Android Snippets

Es können bei der obigen Lösung ein paar Probleme auftreten, die dort behandelt werden.

Wenn möglich sollte man bei AES ein Blöcke (Padding) benutzen. Padding (Informatik) – Wikipedia

Ein Ansatz dazu steht in der Diskussion des obigen Link. Die Verschlüsselung wäre dann "AES/CBC/PKCS5Padding" statt AES/CBC/NoPadding

Hier noch ein Link dazu: Encryption between Java/Android and PHP | blog.cwill-dev.com
 
1

123thomas

Fortgeschrittenes Mitglied
Hallo,
also ich glaube ich stehe auf dem Schlauch, mit dem "Frage-Antwort" Ding. Also wenn ich z.B. ein Passwort mit der aktuellen Zeit schicke. Woher weiß dann der Server das der Client diese aktuelle Zeit. Oder würde man da für eventuelle Verzögerungen einen Puffer einbauen z.B.(+-10 Sekunden)?

Ich habe jetzt nochmal das Padding hinzugefügt.
Zur Vollständigkeit, die Zeilen die geändert werden müssen. Steht auch in einem Kommentar von dem ersten Link aus dem Post #14 von markus.tullius.
Code:
**IN JAVA (MCrypt Class):**
**CHANGE:** cipher = Cipher.getInstance("AES/CBC/NoPadding");
**TO:** cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

**CHANGE:** encrypted = cipher.doFinal(padString(text).getBytes());
**TO:** encrypted = cipher.doFinal(text.getBytes("UTF-8"));

**DELETE** padString method (not used anymore)

**IN JAVA (Main Class):**
**CHANGE:** String decrypted = new String( mcrypt.decrypt( encrypted ) );
**TO:** String decrypted = new String(MCrypt.decrypt(encrypted), "UTF-8");

**IN PHP:**
Add the following functions to be used before you encrypt and after you decrypt:

function pkcs5_pad ($text) {
    $blocksize = 16;
    $pad = $blocksize - (strlen($text) % $blocksize);
    return $text . str_repeat(chr($pad), $pad);
}

function pkcs5_unpad($text) {
    $pad = ord($text{strlen($text)-1});
    if ($pad > strlen($text))
        return false;

    if (strspn($text, chr($pad), strlen($text) - $pad) != $pad)
        return false;

    return substr($text, 0, -1 * $pad);
}

**ENCRYPT EX:** $encrypted = $mcrypt->encrypt(pkcs5_pad("Text to Encrypt"));
**DECRYPT EX:** $decrypted = pkcs5_unpad($mcrypt->decrypt($encrypted));
 
Kiwi++Soft

Kiwi++Soft

Ehrenmitglied
123thomas schrieb:
also ich glaube ich stehe auf dem Schlauch, mit dem "Frage-Antwort" Ding. Also wenn ich z.B. ein Passwort mit der aktuellen Zeit schicke. Woher weiß dann der Server das der Client diese aktuelle Zeit. Oder würde man da für eventuelle Verzögerungen einen Puffer einbauen z.B.(+-10 Sekunden)?
Nee, das läuft so:

  • Client sendet Server eine Anfrage, dass er einloggen will.
  • Server sendet Client den aktuellen Server Timestamp (oder einfach eine beliebige, Serverseitig generierte, aufsteigende Zahl, oder andere unique Zeichenfolge). So etwas nennt eine 'Challenge'.
  • Client kreiert aus dieser einzigartigen Server-Challenge ein Paket, in dem dieser Timestamp/Zahl/Zeichenfolge und das Passwort enthalten sind und schickt es an den Server.
Durch die vorher vom Server gesendete 'Herausforderung/Challange' ist die 'Login-Antwort' des Clients einzigartig, und kann von keinem anderen (Hacker) zum Einloggen missbraucht werden.
 
1

123thomas

Fortgeschrittenes Mitglied
Okay das habe ich nun verstanden. Wenn ich soweit bin, dass es mit normaler Verschlüsselung läuft, dann baue ich auf Frage- Antwort um. Aktuell habe ich aber noch andere Baustellen, die dringlicher sind.

Danke an alle die geholfen haben.
 
Ähnliche Themen - Daten verschlüsselt übertragen zum Webspace Antworten Datum
17
7
3