# Android OpenPGP



## arpi (1. Okt 2014)

Hi Leute, 

ich habe vor einiger Zeit eine kleine Chat-Anwendung mit Nodejs, Socketio und OpenPGP.js | OpenPGP JavaScript Implementation geschrieben und würde nun gern einen passende Android-App dazu erstellen.

Mein Problem ist das ich noch relativ neu bei dem Thema Java und Android Programmierung bin und kaum Tutorials zum Thema Java und PGP finde....

Im Internet bin ich auf folgende Library gestoßen:

bouncycastle.org

und noch ein passendens Tutorial:

Revisited: PGP Encryption/Decryption in Java | Waiting for Wit

Mit dieser Anleitung habe ich es geschafft eine Nachricht die Empfangen wird mit dem passenden PrivateKey + Passphrase zu entschlüsseln, nur verstehe ich nicht ganze wie ich die Daten vor dem Senden mit dem PublicKey verschlüsseln kann..

In der Anleitung und den anderen Tutorials im Internet die ich gefunden wird immer eine Datei verschlüsselt und kein String....

```
public static void encryptFile(
        OutputStream out,
        String fileName,
        PGPPublicKey encKey,
        boolean armor,
        boolean withIntegrityCheck)
        throws IOException, NoSuchProviderException, PGPException
    {
    	Security.addProvider(new BouncyCastleProvider());

        if (armor) {
            out = new ArmoredOutputStream(out);
        }

        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
        PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(PGPCompressedData.ZIP);

        PGPUtil.writeFileToLiteralData(
                comData.open(bOut),
                PGPLiteralData.BINARY,
                new File(fileName) );

        comData.close();

        BcPGPDataEncryptorBuilder dataEncryptor = new BcPGPDataEncryptorBuilder(PGPEncryptedData.TRIPLE_DES);
        dataEncryptor.setWithIntegrityPacket(withIntegrityCheck);
        dataEncryptor.setSecureRandom(new SecureRandom());

        PGPEncryptedDataGenerator encryptedDataGenerator = new PGPEncryptedDataGenerator(dataEncryptor);
        encryptedDataGenerator.addMethod(new BcPublicKeyKeyEncryptionMethodGenerator(encKey));

        byte[] bytes = bOut.toByteArray();
        OutputStream cOut = encryptedDataGenerator.open(out, bytes.length);
        cOut.write(bytes);
        cOut.close();
        out.close();
    }
```

Die PublicKeys werden von einem Server per GET-Request heruntergeladen und sind deshalb nur als "String" vorhanden.

Könnt ihr mir erklären wie ich die Library mit einem String verwende ?

beste grüße

arpi


----------



## dzim (1. Okt 2014)

Also ich würde es entweder in eine temporäre Datei werfen (wobei bei den PubKeys eigentlich nichts dagegen spricht, die auch länger zu cachen!), oder mal schauen, was andere so machen... 

Verschlüsseln:
Java Pretty Good Privacy (PGP) | Java Code Geeks

KeyBasedFileProcessorUtil als Bsp.:
https://github.com/matthewmcculloug...tideas/encrypt/KeyBasedFileProcessorUtil.java

Vielleicht kannst du daraus ja was mitnehmen.
Auf jeden Fall schein bouncycastle wirklich die beste Wahl zu sein...


----------



## arpi (1. Okt 2014)

erstmal danke für die Antwort.

Das Problem ist das ich nichts dazu finde wie es andere machen. Alle Beispiele verwenden eine Datei.....

ich habe es jetzt geschaft einen PublicKey von einem String einzulesen:


```
InputStream publicKeyStream = new ByteArrayInputStream(publicKey.getBytes());

        PGPPublicKey pgpPublicKey = null;
        try {
            pgpPublicKey = KeyBasedFileProcessorUtil.readPublicKey(publicKeyStream);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (PGPException e) {
            e.printStackTrace();
        }
```

Scheint auf jeden fall zu gehen, zumindest fliegt kein Fehler....

Danach mach ich folgendes:

```
OutputStream out = new ByteArrayOutputStream();

        File cDir = getBaseContext().getCacheDir();

        String test = cDir.getPath() + "/test.txt";

        try {
            KeyBasedFileProcessorUtil.encryptFile(out, test, pgpPublicKey, true, false);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoSuchProviderException e) {
            e.printStackTrace();
        }
```

Da bekomme ich jetzt folgende Fehlermeldung:

 java.io.FileNotFoundException: /data/data/com.example.openpgp.test/cache/test.txt: open failed: ENOENT (No such file or directory)

in meinem AndroidManifest.xml habe ich folgende Zeilen eingefügt:

```
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
```

Gibt es irgendeinen weg das ganze ohne Dateien zu verwenden, sondern direkt in einen String zu schreiben ? 

Im Prinzip müsste ja nur diese Stelle umgeschrieben werden: 

```
PGPCompressedDataGenerator  comData = new PGPCompressedDataGenerator(
                    PGPCompressedData.ZIP);

            PGPUtil.writeFileToLiteralData(comData.open(bOut), PGPLiteralData.BINARY, new File(fileName));

 comData.close();
```

oder bin ich da Falsch ? 

Grüße arpi


----------



## dzim (1. Okt 2014)

/data/data/<pkg-name> ist der interne Pfad. Solange dein Gerät nicht gerootet ist, kommst du da nicht ran. 

Verwende Context#getExternalFilesDir:
Context | Android Developers
(wird erst gelöscht, wenn die App deinstalliert wird)

Oder Context#getExternalCacheDir:
Context | Android Developers
(kann das System löschen, wenn es Platz braucht, bzw. wird gelöscht, wenn man den Cache im App-Manager löscht)


----------



## arpi (9. Okt 2014)

danke für die Antwort, ist eine sehr gute idee =)

Ich habe es nach langem suchen und probieren auch endlich geschafft den PublicKey als String zu verwenden.  Die Methode writeFileToLiteralData habe ich mit dieser hier ersetzt:


```
private static void writeStringToLiteralData(OutputStream out, String inString) throws IOException {

        PGPLiteralDataGenerator lData = new PGPLiteralDataGenerator();

        OutputStream pOut = lData.open(out, PGPLiteralData.BINARY, "", inString.length(), new Date());

        pOut.write(inString.getBytes());

        lData.close();
    }
```


----------

