~ubuntu-branches/ubuntu/feisty/mailcrypt/feisty

« back to all changes in this revision

Viewing changes to tests/make_gpg_testcases.py

  • Committer: Bazaar Package Importer
  • Author(s): Davide G. M. Salvetti
  • Date: 2004-02-28 12:11:35 UTC
  • Revision ID: james.westby@ubuntu.com-20040228121135-m0b6y3bqbvhtcdot
Tags: upstream-3.5.8
ImportĀ upstreamĀ versionĀ 3.5.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#! /usr/bin/python
 
2
 
 
3
import os, commands, re, time
 
4
import GnuPGInterface
 
5
 
 
6
# emit test case files into test-cases/*
 
7
 
 
8
# keys:
 
9
#  1: owner1 <user@test>
 
10
#  2: owner2 <user@test>
 
11
#  3: other <other@test>
 
12
#  4: unknown key
 
13
 
 
14
homedir = "gpg-keys/full-rings"
 
15
testcasedir = "gpg-testcases"
 
16
users = ("owner1", "owner2", "other", "unknown", "trusted", "untrusted")
 
17
 
 
18
def get_keyid(name):
 
19
    # now what keyid did it get?
 
20
    cmd = "gpg --homedir %s --with-colons --fingerprint %s" % (homedir,name)
 
21
    (s,out) = commands.getstatusoutput(cmd)
 
22
    assert(s==0)
 
23
    r = re.search(r'^fpr:::::::::(\w+):',out, re.M)
 
24
    if r == None:
 
25
        print "problem, out '%s'" % out
 
26
        return None
 
27
    id = r.group(1) # long form
 
28
    return id
 
29
 
 
30
class Encrypt(GnuPGInterface.GnuPG):
 
31
    def __init__(self):
 
32
        GnuPGInterface.GnuPG.__init__(self)
 
33
        self.setup_my_options()
 
34
 
 
35
    def setup_my_options(self):
 
36
        self.options.armor = 1
 
37
        self.options.meta_interactive = 0
 
38
        self.options.extra_args.append('--no-secmem-warning')
 
39
        self.options.homedir = homedir
 
40
 
 
41
    def encrypt_string(self, string, recipients):
 
42
        self.options.recipients = recipients   # a list!
 
43
        proc = self.run(['--encrypt'], create_fhs=['stdin', 'stdout'])
 
44
        proc.handles['stdin'].write(string)
 
45
        proc.handles['stdin'].close()
 
46
        output = proc.handles['stdout'].read()
 
47
        proc.handles['stdout'].close()
 
48
        proc.wait()
 
49
        return output
 
50
 
 
51
    def signencrypt_string(self, string, signer, passphrase, recipients):
 
52
        self.options.recipients = recipients   # a list!
 
53
        self.options.default_key = signer
 
54
        self.passphrase = passphrase
 
55
        proc = self.run(['--sign', '--encrypt'],
 
56
                        create_fhs=['stdin', 'stdout'])
 
57
        proc.handles['stdin'].write(string)
 
58
        proc.handles['stdin'].close()
 
59
        output = proc.handles['stdout'].read()
 
60
        proc.handles['stdout'].close()
 
61
        proc.wait()
 
62
        return output
 
63
 
 
64
    def sign_string(self, string, signer, passphrase):
 
65
        self.options.recipients = []
 
66
        self.options.default_key = signer
 
67
        self.passphrase = passphrase
 
68
        proc = self.run(['--sign'],
 
69
                        create_fhs=['stdin', 'stdout'])
 
70
        proc.handles['stdin'].write(string)
 
71
        proc.handles['stdin'].close()
 
72
        output = proc.handles['stdout'].read()
 
73
        proc.handles['stdout'].close()
 
74
        proc.wait()
 
75
        return output
 
76
 
 
77
    def sym_string(self, string, passphrase):
 
78
        self.options.recipients = []
 
79
        self.passphrase = passphrase
 
80
        proc = self.run(['--symmetric'],
 
81
                        create_fhs=['stdin', 'stdout'])
 
82
        proc.handles['stdin'].write(string)
 
83
        proc.handles['stdin'].close()
 
84
        output = proc.handles['stdout'].read()
 
85
        proc.handles['stdout'].close()
 
86
        proc.wait()
 
87
        return output
 
88
 
 
89
    def armor_string(self, string):
 
90
        self.options.recipients = []
 
91
        proc = self.run(['--enarmor'],
 
92
                        create_fhs=['stdin', 'stdout'])
 
93
        proc.handles['stdin'].write(string)
 
94
        proc.handles['stdin'].close()
 
95
        output = proc.handles['stdout'].read()
 
96
        proc.handles['stdout'].close()
 
97
        proc.wait()
 
98
        return output
 
99
 
 
100
    def clearsign_string(self, string, signer, passphrase):
 
101
        self.options.recipients = []
 
102
        self.options.default_key = signer
 
103
        self.passphrase = passphrase
 
104
        proc = self.run(['--clearsign'],
 
105
                        create_fhs=['stdin', 'stdout'])
 
106
        proc.handles['stdin'].write(string)
 
107
        proc.handles['stdin'].close()
 
108
        output = proc.handles['stdout'].read()
 
109
        proc.handles['stdout'].close()
 
110
        proc.wait()
 
111
        return output
 
112
 
 
113
def emit_alist(f, d):
 
114
    f.write("(\n")
 
115
    keys = d.keys()
 
116
    keys.sort()
 
117
    for k in keys:
 
118
        if d[k] == None:
 
119
            f.write("(%s . nil)\n" % (k))
 
120
        else:
 
121
            f.write("(%s . \"%s\")\n" % (k, d[k]))
 
122
    f.write(")\n")
 
123
 
 
124
encryptor = Encrypt()
 
125
def encrypt(to, plaintext):
 
126
    return encryptor.encrypt_string(plaintext, [to])
 
127
def signencrypt(to, signer, plaintext):
 
128
    return encryptor.signencrypt_string(plaintext, signer, signer, [to])
 
129
def sign(signer, plaintext):
 
130
    return encryptor.sign_string(plaintext, signer, signer)
 
131
def sym(passphrase, plaintext):
 
132
    return encryptor.sym_string(plaintext, passphrase)
 
133
def armor(plaintext):
 
134
    # note: this isn't very useful, you must use 'gpg --dearmor' to
 
135
    # extract the result, not --decrypt. It also has a different banner.
 
136
    return encryptor.armor_string(plaintext)
 
137
def clearsign(signer, plaintext):
 
138
    return encryptor.clearsign_string(plaintext, signer, signer)
 
139
 
 
140
#def encrypt(to, plaintext):
 
141
    #cmd = "gpg --armor --homedir %s --recipient %s --batch --encrypt" % (homedir, to)
 
142
    #(stdout,stdin) = popen2.popen2(cmd)
 
143
    #stdin.write(plaintext)
 
144
    #stdin.close()
 
145
    #crypttext = stdout.read()
 
146
    #return crypttext
 
147
 
 
148
class TestCase:
 
149
    def __init__(self, filename):
 
150
        self.filename = filename
 
151
        self.plaintext = self.make_plaintext()
 
152
        self.d = {}
 
153
        self.d['name'] = self.filename
 
154
        self.d['plaintext'] = self.plaintext
 
155
        self.d['error'] = None
 
156
        self.d['signature_status'] = None
 
157
 
 
158
    def make_plaintext(self):
 
159
        return "This is a plaintext message\n"
 
160
    def date_string(self):
 
161
        # mc-gpg.el takes the YYYY-MM-DD date string from the SIG_ID
 
162
        # status-fs line and delivers it to the user. This appears to be the
 
163
        # GMT date of the signature. Extract the same thing here so we can
 
164
        # tell the test harness what to expect. This needs to run on the
 
165
        # same day as the gpg invocation used to create the signature, but
 
166
        # this whole program only takes a few seconds to execute.
 
167
        return time.strftime("%Y-%m-%d", time.gmtime()) # GMT
 
168
 
 
169
    def encrypted_fields(self, recip):
 
170
        # run this after signed_fields so [signature_status] gets cleared
 
171
        self.d['encryption_id'] = "0x%s" % id[recip][-16:]
 
172
        self.d['passphrase'] = recip
 
173
        if recip == "other" or recip == "unknown":
 
174
            self.d['error'] = "This message is not addressed to you"
 
175
            self.d['plaintext'] = None
 
176
            self.d['signature_status'] = None
 
177
 
 
178
    def symencrypted_fields(self):
 
179
        self.d['encryption_id'] = "***** CONVENTIONAL *****"
 
180
        self.d['passphrase'] = self.passphrase
 
181
 
 
182
    def signed_fields(self, signer):
 
183
        self.d['signature_status'] = ("Good signature from '%s <%s@test>' " + \
 
184
                                 "TRUST_%s made %s") % \
 
185
                                 (signer, signer,
 
186
                                  trustmap[signer], self.date_string())
 
187
        if signer == "unknown":
 
188
            self.d['signature_status'] = "cannot check signature " + \
 
189
                                         "from keyid %s" % \
 
190
                                         id[signer][-16:]
 
191
            # comes from 'cannot check signature' warning
 
192
    def process(self, testcasedir):
 
193
        self.make_crypttext()
 
194
        f = open(os.path.join(testcasedir, self.filename), "w")
 
195
        emit_alist(f, self.d)
 
196
        f.close()
 
197
        
 
198
 
 
199
class E_Case(TestCase):
 
200
    def __init__(self, filename, recip):
 
201
        TestCase.__init__(self, filename)
 
202
        self.recip = recip
 
203
        self.encrypted_fields(recip)
 
204
    def make_crypttext(self):
 
205
        self.d['crypttext'] = "\n" + encrypt(self.recip, self.plaintext)
 
206
        
 
207
class ES_Case(TestCase):
 
208
    def __init__(self, filename, recip, signer):
 
209
        TestCase.__init__(self, filename)
 
210
        self.recip = recip
 
211
        self.signer = signer
 
212
        self.signed_fields(signer)
 
213
        self.encrypted_fields(recip)
 
214
    def make_crypttext(self):
 
215
        self.d['crypttext'] = "\n" + signencrypt(self.recip,
 
216
                                                 self.signer,
 
217
                                                 self.plaintext)
 
218
 
 
219
class S_Case(TestCase):
 
220
    def __init__(self, filename, signer):
 
221
        TestCase.__init__(self, filename)
 
222
        self.signer = signer
 
223
        self.signed_fields(signer)
 
224
    def make_crypttext(self):
 
225
        self.d['crypttext'] = "\n" + sign(self.signer, self.plaintext)
 
226
 
 
227
class CS_Case(TestCase):
 
228
    def __init__(self, filename, signer):
 
229
        TestCase.__init__(self, filename)
 
230
        self.signer = signer
 
231
        self.signed_fields(signer)
 
232
    def make_crypttext(self):
 
233
        self.d['crypttext'] = "\n" + clearsign(self.signer, self.plaintext)
 
234
 
 
235
class SYM_Case(TestCase):
 
236
    def __init__(self, filename, passphrase):
 
237
        TestCase.__init__(self, filename)
 
238
        self.passphrase = passphrase
 
239
        self.symencrypted_fields()
 
240
    def make_crypttext(self):
 
241
        self.d['crypttext'] = "\n" + sym(self.passphrase, self.plaintext)
 
242
 
 
243
def make_cases():
 
244
    d = testcasedir
 
245
    E_Case("E.e1r", "owner1").process(d)
 
246
    E_Case("E.e2r", "owner2").process(d)
 
247
    E_Case("E.e3", "other").process(d)
 
248
    E_Case("E.e4", "unknown").process(d)
 
249
    ES_Case("ES.e1r.s1v", "owner1", "owner1").process(d)
 
250
    ES_Case("ES.e1r.s2v", "owner1", "trusted").process(d)
 
251
    ES_Case("ES.e1r.s3v", "owner1", "untrusted").process(d)
 
252
    ES_Case("ES.e1r.s4", "owner1", "unknown").process(d)
 
253
    ES_Case("ES.e3.s1v", "other", "owner1").process(d)
 
254
    ES_Case("ES.e4.s1v", "unknown", "owner1").process(d)
 
255
    S_Case("S.s1v", "owner1").process(d)
 
256
    S_Case("S.s2v", "trusted").process(d)
 
257
    S_Case("S.s3v", "untrusted").process(d)
 
258
    S_Case("S.s4", "unknown").process(d)
 
259
    SYM_Case("SE", "password").process(d)
 
260
    CS_Case("CS.s1v", "owner1").process(d)
 
261
    CS_Case("CS.s2v", "trusted").process(d)
 
262
    CS_Case("CS.s3v", "untrusted").process(d)
 
263
    CS_Case("CS.s4", "unknown").process(d)
 
264
 
 
265
# get keyids
 
266
id = {}
 
267
for u in users:
 
268
    id[u] = get_keyid(u)
 
269
 
 
270
trustmap = {
 
271
    'owner1': "ULTIMATE",
 
272
    'owner2': "ULTIMATE",
 
273
    'other': "FULL",
 
274
    'unknown': "NONE",
 
275
    'trusted': "MARGINAL",
 
276
    'untrusted': "UNDEFINED",
 
277
    }
 
278
    
 
279
if __name__ == "__main__":
 
280
    if not os.path.isdir(testcasedir):
 
281
        os.mkdir(testcasedir)
 
282
    make_cases()
 
283
    
 
284
 
 
285
# todo:
 
286
#  hardcoded date in es()
 
287
#  cs(): corrupt the signatures by editing the crypttext after signing