aboutsummaryrefslogtreecommitdiff
path: root/plugins/openpgp/src/gpgme_helper.vala
blob: c53437d37f8702600df898d3d14d2ac19d54dc50 (plain) (blame)
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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
using Gee;
using GPG;

namespace GPGHelper {

private static bool initialized = false;

public static string encrypt_armor(string plain, Key[] keys, EncryptFlags flags) throws GLib.Error {
    global_mutex.lock();
    try {
        initialize();
        Data plain_data = Data.create_from_memory(plain.data, false);
        Context context = Context.create();
        context.set_armor(true);
        Data enc_data = context.op_encrypt(keys, flags, plain_data);
        return get_string_from_data(enc_data);
    } finally {
        global_mutex.unlock();
    }
}

public static uint8[] encrypt_file(string uri, Key[] keys, EncryptFlags flags, string file_name) throws GLib.Error {
    global_mutex.lock();
    try {
        initialize();
        Data plain_data = Data.create_from_file(uri);
        plain_data.set_file_name(file_name);
        Context context = Context.create();
        context.set_armor(true);
        Data enc_data = context.op_encrypt(keys, flags, plain_data);
        return get_uint8_from_data(enc_data);
    } finally {
        global_mutex.unlock();
    }
}

public static string decrypt(string encr) throws GLib.Error {
    global_mutex.lock();
    try {
        initialize();
        Data enc_data = Data.create_from_memory(encr.data, false);
        Context context = Context.create();
        Data dec_data = context.op_decrypt(enc_data);
        return get_string_from_data(dec_data);
    } finally {
        global_mutex.unlock();
    }
}

public class DecryptedData {
    public uint8[] data { get; set; }
    public string filename { get; set; }
}

public static DecryptedData decrypt_data(uint8[] data) throws GLib.Error {
    global_mutex.lock();
    try {
        initialize();
        Data enc_data = Data.create_from_memory(data, false);
        Context context = Context.create();
        Data dec_data = context.op_decrypt(enc_data);
        DecryptResult* dec_res = context.op_decrypt_result();
        return new DecryptedData() { data=get_uint8_from_data(dec_data), filename=dec_res->file_name};
    } finally {
        global_mutex.unlock();
    }
}

public static string sign(string plain, SigMode mode, Key? key = null) throws GLib.Error {
    global_mutex.lock();
    try {
        initialize();
        Data plain_data = Data.create_from_memory(plain.data, false);
        Context context = Context.create();
        if (key != null) context.signers_add(key);
        Data signed_data = context.op_sign(plain_data, mode);
        return get_string_from_data(signed_data);
    } finally {
        global_mutex.unlock();
    }
}

public static string? get_sign_key(string signature, string? text) throws GLib.Error {
    global_mutex.lock();
    try {
        initialize();
        Data sig_data = Data.create_from_memory(signature.data, false);
        Data text_data;
        if (text != null) {
            text_data = Data.create_from_memory(text.data, false);
        } else {
            text_data = Data.create();
        }
        Context context = Context.create();
        context.op_verify(sig_data, text_data);
        VerifyResult* verify_res = context.op_verify_result();
        if (verify_res == null || verify_res.signatures == null) return null;
        return verify_res.signatures.fpr;
    } finally {
        global_mutex.unlock();
    }
}

public static Gee.List<Key> get_keylist(string? pattern = null, bool secret_only = false) throws GLib.Error {
    global_mutex.lock();
    try {
        initialize();

        Gee.List<Key> keys = new ArrayList<Key>();
        Context context = Context.create();
        context.op_keylist_start(pattern, secret_only ? 1 : 0);
        try {
            while (true) {
                Key key = context.op_keylist_next();
                if (!key.expired && !key.revoked){
                    debug("PGP Key " + key.fpr + " is valid!");
                    keys.add(key);
                }
                else {
                    debug("PGP Key " + key.fpr + " is either expired or revoked!");
                }
            }
        } catch (Error e) {
            if (e.code != GPGError.ErrorCode.EOF) throw e;
        }
        context.op_keylist_end();
        return keys;
    } finally {
        global_mutex.unlock();
    }
}

public static Key? get_public_key(string sig) throws GLib.Error {
    return get_key(sig, false);
}

public static Key? get_private_key(string sig) throws GLib.Error {
    return get_key(sig, true);
}

private static Key? get_key(string sig, bool priv) throws GLib.Error {
    global_mutex.lock();
    try {
        initialize();
        Context context = Context.create();
        Key key = context.get_key(sig, priv);
        return key;
    } finally {
        global_mutex.unlock();
    }
}

private static string get_string_from_data(Data data) {
    const size_t BUF_SIZE = 256;
    data.seek(0);
    uint8[] buf = new uint8[BUF_SIZE + 1];
    ssize_t len = 0;
    string res = "";
    do {
        len = data.read(buf, BUF_SIZE);
        if (len > 0) {
            buf[len] = 0;
            res += (string) buf;
        }
    } while (len > 0);
    return res;
}

private static uint8[] get_uint8_from_data(Data data) {
    const size_t BUF_SIZE = 256;
    data.seek(0);
    uint8[] buf = new uint8[BUF_SIZE + 1];
    ssize_t len = 0;
    ByteArray res = new ByteArray();
    do {
        len = data.read(buf, BUF_SIZE);
        if (len > 0) {
            res.append(buf[0:len]);
        }
    } while (len > 0);
    return res.data;
}

private static void initialize() {
    if (!initialized) {
        check_version();
        initialized = true;
    }
}

}