aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java
blob: 1cf027721339adf477d6ab942df4c630703c7d6b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/*
 * Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
 * Copyright (C) 2010-2014 Thialfihar <thi@thialfihar.org>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.sufficientlysecure.keychain.pgp;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;

import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.Preferences;
import org.sufficientlysecure.keychain.util.Log;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.security.SecureRandom;
import java.util.regex.Pattern;

public class PgpHelper {

    public static final Pattern PGP_MESSAGE = Pattern.compile(
            ".*?(-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----).*", Pattern.DOTALL);

    public static final Pattern PGP_CLEARTEXT_SIGNATURE = Pattern
            .compile(".*?(-----BEGIN PGP SIGNED MESSAGE-----.*?-----" +
                    "BEGIN PGP SIGNATURE-----.*?-----END PGP SIGNATURE-----).*",
                    Pattern.DOTALL);

    public static final Pattern PGP_PUBLIC_KEY = Pattern.compile(
            ".*?(-----BEGIN PGP PUBLIC KEY BLOCK-----.*?-----END PGP PUBLIC KEY BLOCK-----).*",
            Pattern.DOTALL);

    public static String getVersion(Context context) {
        String version;
        try {
            PackageInfo pi = context.getPackageManager().getPackageInfo(Constants.PACKAGE_NAME, 0);
            version = pi.versionName;
            return version;
        } catch (NameNotFoundException e) {
            Log.e(Constants.TAG, "Version could not be retrieved!", e);
            return "0.0";
        }
    }

    public static String getVersionForHeader(Context context) {
        if(Preferences.getPreferences(context).getWriteVersionHeader()){
            return "OpenKeychain v" + getVersion(context);
        } else {
            return null;
        }
    }

//    public static final class content {
//        public static final int unknown = 0;
//        public static final int encrypted_data = 1;
//        public static final int keys = 2;
//    }
//
//    public static int getStreamContent(Context context, InputStream inStream) throws IOException {
//
//        InputStream in = PGPUtil.getDecoderStream(inStream);
//        PGPObjectFactory pgpF = new PGPObjectFactory(in);
//        Object object = pgpF.nextObject();
//        while (object != null) {
//            if (object instanceof PGPPublicKeyRing || object instanceof PGPSecretKeyRing) {
//                return Id.content.keys;
//            } else if (object instanceof PGPEncryptedDataList) {
//                return Id.content.encrypted_data;
//            }
//            object = pgpF.nextObject();
//        }
//
//        return Id.content.unknown;
//    }

    /**
     * Generate a random filename
     *
     * @param length
     * @return
     */
    public static String generateRandomFilename(int length) {
        SecureRandom random = new SecureRandom();

        byte bytes[] = new byte[length];
        random.nextBytes(bytes);
        String result = "";
        for (int i = 0; i < length; ++i) {
            int v = (bytes[i] + 256) % 64;
            if (v < 10) {
                result += (char) ('0' + v);
            } else if (v < 36) {
                result += (char) ('A' + v - 10);
            } else if (v < 62) {
                result += (char) ('a' + v - 36);
            } else if (v == 62) {
                result += '_';
            } else if (v == 63) {
                result += '.';
            }
        }
        return result;
    }

    /**
     * Go once through stream to get length of stream. The length is later used to display progress
     * when encrypting/decrypting
     *
     * @param in
     * @return
     * @throws IOException
     */
    public static long getLengthOfStream(InputStream in) throws IOException {
        long size = 0;
        long n = 0;
        byte dummy[] = new byte[0x10000];
        while ((n = in.read(dummy)) > 0) {
            size += n;
        }
        return size;
    }

    /**
     * Deletes file securely by overwriting it with random data before deleting it.
     * <p/>
     * TODO: Does this really help on flash storage?
     *
     * @param context
     * @param progressable
     * @param file
     * @throws IOException
     */
    public static void deleteFileSecurely(Context context, Progressable progressable, File file)
            throws IOException {
        long length = file.length();
        SecureRandom random = new SecureRandom();
        RandomAccessFile raf = new RandomAccessFile(file, "rws");
        raf.seek(0);
        raf.getFilePointer();
        byte[] data = new byte[1 << 16];
        int pos = 0;
        String msg = context.getString(R.string.progress_deleting_securely, file.getName());
        while (pos < length) {
            if (progressable != null) {
                progressable.setProgress(msg, (int) (100 * pos / length), 100);
            }
            random.nextBytes(data);
            raf.write(data);
            pos += data.length;
        }
        raf.close();
        file.delete();
    }
}