1#!/usr/bin/env python
2
3# Copyright (C) 2017 g10 Code GmbH
4#
5# This file is part of GPGME.
6#
7# GPGME is free software; you can redistribute it and/or modify it
8# under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# GPGME is distributed in the hope that it will be useful, but WITHOUT
13# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
15# Public License for more details.
16#
17# You should have received a copy of the GNU Lesser General Public
18# License along with this program; if not, see <https://www.gnu.org/licenses/>.
19
20from __future__ import absolute_import, print_function, unicode_literals
21
22import gpg
23import itertools
24import time
25
26import support
27support.assert_gpg_version((2, 1, 2))
28
29del absolute_import, print_function, unicode_literals
30
31alpha = "Alpha <alpha@invalid.example.net>"
32
33with support.EphemeralContext() as ctx:
34    res = ctx.create_key(alpha)
35
36    keys = list(ctx.keylist())
37    assert len(keys) == 1, "Weird number of keys created"
38
39    key = keys[0]
40    assert key.fpr == res.fpr
41    assert len(key.subkeys) == 2, "Expected one primary key and one subkey"
42    assert key.subkeys[0].expires > 0, "Expected primary key to expire"
43
44    # Try to create a key with the same UID
45    try:
46        ctx.create_key(alpha)
47        assert False, "Expected an error but got none"
48    except gpg.errors.GpgError as e:
49        pass
50
51    # Try to create a key with the same UID, now with force!
52    res2 = ctx.create_key(alpha, force=True)
53    assert res.fpr != res2.fpr
54
55# From here on, we use one context, and create unique UIDs
56uid_counter = 0
57
58
59def make_uid():
60    global uid_counter
61    uid_counter += 1
62    return "user{0}@invalid.example.org".format(uid_counter)
63
64
65with support.EphemeralContext() as ctx:
66    # Check gpg.constants.create.NOEXPIRE...
67    res = ctx.create_key(make_uid(), expires=False)
68    key = ctx.get_key(res.fpr, secret=True)
69    assert key.fpr == res.fpr
70    assert len(key.subkeys) == 2, "Expected one primary key and one subkey"
71    assert key.subkeys[0].expires == 0, "Expected primary key not to expire"
72
73    t = 2 * 24 * 60 * 60
74    slack = 5 * 60
75    res = ctx.create_key(make_uid(), expires_in=t)
76    key = ctx.get_key(res.fpr, secret=True)
77    assert key.fpr == res.fpr
78    assert len(key.subkeys) == 2, "Expected one primary key and one subkey"
79    assert abs(time.time() + t - key.subkeys[0].expires) < slack, \
80        "Primary keys expiration time is off"
81
82    # Check capabilities
83    for sign, encrypt, certify, authenticate \
84            in itertools.product([False, True],
85                                 [False, True],
86                                 [False, True],
87                                 [False, True]):
88        # Filter some out
89        if not (sign or encrypt or certify or authenticate):
90            # This triggers the default capabilities tested before.
91            continue
92        if (sign or encrypt or authenticate) and not certify:
93            # The primary key always certifies.
94            continue
95
96        res = ctx.create_key(
97            make_uid(),
98            algorithm="rsa",
99            sign=sign,
100            encrypt=encrypt,
101            certify=certify,
102            authenticate=authenticate)
103        key = ctx.get_key(res.fpr, secret=True)
104        assert key.fpr == res.fpr
105        assert len(key.subkeys) == 1, \
106            "Expected no subkey for non-default capabilities"
107
108        p = key.subkeys[0]
109        assert sign == p.can_sign
110        assert encrypt == p.can_encrypt
111        assert certify == p.can_certify
112        assert authenticate == p.can_authenticate
113
114    # Check algorithm
115    res = ctx.create_key(make_uid(), algorithm="rsa")
116    key = ctx.get_key(res.fpr, secret=True)
117    assert key.fpr == res.fpr
118    for k in key.subkeys:
119        assert k.pubkey_algo == 1
120
121    # Check algorithm with size
122    res = ctx.create_key(make_uid(), algorithm="rsa1024")
123    key = ctx.get_key(res.fpr, secret=True)
124    assert key.fpr == res.fpr
125    for k in key.subkeys:
126        assert k.pubkey_algo == 1
127        assert k.length == 1024
128
129    # Check algorithm future-default
130    ctx.create_key(make_uid(), algorithm="future-default")
131
132    # Check passphrase protection
133    recipient = make_uid()
134    passphrase = "streng geheim"
135    res = ctx.create_key(recipient, passphrase=passphrase)
136    ciphertext, _, _ = ctx.encrypt(
137        b"hello there", recipients=[ctx.get_key(res.fpr)])
138
139    cb_called = False
140
141    def cb(*args):
142        global cb_called
143        cb_called = True
144        return passphrase
145
146    ctx.pinentry_mode = gpg.constants.PINENTRY_MODE_LOOPBACK
147    ctx.set_passphrase_cb(cb)
148
149    plaintext, _, _ = ctx.decrypt(ciphertext)
150    assert plaintext == b"hello there"
151    assert cb_called
152