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 27 28del absolute_import, print_function, unicode_literals 29 30alpha = "Alpha <alpha@invalid.example.net>" 31bravo = "Bravo <bravo@invalid.example.net>" 32 33with support.EphemeralContext() as ctx: 34 res = ctx.create_key(alpha, certify=True) 35 keys = list(ctx.keylist()) 36 assert len(keys) == 1, "Weird number of keys created" 37 key = keys[0] 38 assert key.fpr == res.fpr 39 assert len(key.subkeys) == 1, "Expected one primary key and no subkeys" 40 41 def get_subkey(fpr): 42 k = ctx.get_key(fpr) 43 for sk in k.subkeys: 44 if sk.fpr == fpr: 45 return sk 46 return None 47 48 # Check gpg.constants.create.NOEXPIRE... 49 res = ctx.create_subkey(key, expires=False) 50 subkey = get_subkey(res.fpr) 51 assert subkey.expires == 0, "Expected subkey not to expire" 52 assert subkey.can_encrypt, \ 53 "Default subkey capabilities do not include encryption" 54 55 t = 2 * 24 * 60 * 60 56 slack = 5 * 60 57 res = ctx.create_subkey(key, expires_in=t) 58 subkey = get_subkey(res.fpr) 59 assert abs(time.time() + t - subkey.expires) < slack, \ 60 "subkeys expiration time is off" 61 62 # Check capabilities 63 for sign, encrypt, authenticate \ 64 in itertools.product([False, True], 65 [False, True], 66 [False, True]): 67 # Filter some out 68 if not (sign or encrypt or authenticate): 69 # This triggers the default capabilities tested before. 70 continue 71 72 res = ctx.create_subkey( 73 key, sign=sign, encrypt=encrypt, authenticate=authenticate, 74 algorithm="rsa") 75 subkey = get_subkey(res.fpr) 76 assert sign == subkey.can_sign 77 assert encrypt == subkey.can_encrypt 78 assert authenticate == subkey.can_authenticate 79 80 # Check algorithm 81 res = ctx.create_subkey(key, algorithm="rsa") 82 subkey = get_subkey(res.fpr) 83 assert subkey.pubkey_algo == 1 84 85 # Check algorithm with size 86 res = ctx.create_subkey(key, algorithm="rsa1024") 87 subkey = get_subkey(res.fpr) 88 assert subkey.pubkey_algo == 1 89 assert subkey.length == 1024 90 91 # Check algorithm future-default 92 ctx.create_subkey(key, algorithm="future-default") 93 94 # Check passphrase protection. For this we create a new key 95 # so that we have a key with just one encryption subkey. 96 bravo_res = ctx.create_key(bravo, certify=True) 97 bravo_key = ctx.get_key(bravo_res.fpr) 98 assert len( 99 bravo_key.subkeys) == 1, "Expected one primary key and no subkeys" 100 101 passphrase = "streng geheim" 102 res = ctx.create_subkey(bravo_key, passphrase=passphrase) 103 ciphertext, _, _ = ctx.encrypt( 104 b"hello there", recipients=[ctx.get_key(bravo_res.fpr)]) 105 106 cb_called = False 107 108 def cb(*args): 109 global cb_called 110 cb_called = True 111 return passphrase 112 113 ctx.pinentry_mode = gpg.constants.PINENTRY_MODE_LOOPBACK 114 ctx.set_passphrase_cb(cb) 115 116 plaintext, _, _ = ctx.decrypt(ciphertext) 117 assert plaintext == b"hello there" 118 assert cb_called 119