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
|
"""
<Program Name>
check_public_interfaces_gpg.py
<Author>
Lukas Puehringer <lukas.puehringer@nyu.edu>
<Started>
Feb 26, 2020.
<Copyright>
See LICENSE for licensing information.
<Purpose>
Check that the public facing '_gpg.functions' module remains importable if
gnupg is not installed, and that each function presents meaningful
user-feedback.
Further check that gpg signature verification works even without gpg.
NOTE: the filename is purposefully check_ rather than test_ so that test
discovery doesn't find this test module and the test cases within are only
run when explicitly invoked.
"""
import unittest
from securesystemslib._gpg.constants import NO_GPG_MSG, have_gpg
from securesystemslib._gpg.functions import (
create_signature,
export_pubkey,
export_pubkeys,
verify_signature,
)
from securesystemslib.exceptions import UnsupportedLibraryError
from securesystemslib.signer import GPGKey, GPGSigner, Signer
class TestPublicInterfacesGPG(unittest.TestCase):
@classmethod
def setUpClass(cls):
assert not have_gpg(), (
"please remove GnuPG from your environment to run this test case"
)
def test_gpg_functions(self):
"""Signing, key export and util functions must raise on missing gpg."""
# Hand-crafting a GPG public key and loading a signer works w/o gpg, but
# signing fails (see below).
mock_public_key = GPGKey(
"aa",
"rsa",
"pgp+rsa-pkcsv1.5",
{"public": {"key": "value"}},
)
signer = Signer.from_priv_key_uri("gnupg:?id=abcd", mock_public_key)
# Run commands that require gpg and assert error plus message
for fn, args in (
(create_signature, ("bar",)),
(export_pubkey, ("f00",)),
(export_pubkeys, (["f00"],)),
(GPGSigner.import_, ("keyid",)),
(signer.sign, (b"data",)),
):
with self.assertRaises(UnsupportedLibraryError) as ctx:
fn(*args)
self.assertEqual(NO_GPG_MSG, str(ctx.exception))
def test_gpg_verify(self):
"""Signature verification does not require gpg to be installed on the host.
To prove it, we run basic verification tests for rsa, dsa and eddsa with
pre-generated/exported signatures and keys. More thorough testing is
available in test_gpg.py
"""
data = b"deadbeef"
key_signature_pairs = [
# RSA
(
{
"method": "pgp+rsa-pkcsv1.5",
"type": "rsa",
"hashes": ["pgp+SHA2"],
"creation_time": 1519661780,
"keyid": "c5a0abe6ec19d0d65f85e2c39be9df5131d924e9",
"keyval": {
"private": "",
"public": {
"e": "010001",
"n": "c152fc1f1535a6d3c1e8c0dece7f0a1d09324466e10e4ea51d5d7223ab125c1743393eebca73ccb1022d44c379fae30ef63b263d0a793882a7332ef06f28a4b9ae777f5d2d8d289167e86c162df1b9a9e127acb26803688556ecb08492d071f06caf88cea95571354349d8ef131eff03b0d259fae30ebf8dac9ab5acd6f26f4770fe2f30fcd0a3c54f03463a3094aa6524e39027a625108f04e12475da248fb3b536df61b0f6e2954739b8828c61171f66f8e176823e1c887e65fa0aec081013b2a50ed60515f7e3b3291ca443e1222b9b625005dba045a7208188fb88d436d473f6340348953e891354c7a5734bf64e6274e196db3074a7ce3607960baacb1b",
},
},
},
{
"keyid": "c5a0abe6ec19d0d65f85e2c39be9df5131d924e9",
"other_headers": "04000108001d162104c5a0abe6ec19d0d65f85e2c39be9df5131d924e905025e56444b",
"signature": "bc4490901bd6edfe0ec49e0358c0a7ef37fc229824ca75dd4f163205745c78baaa2ca5cda79be259a5ac8323b4c1a1ee18fab0a8cc90eeafeb3eb1221d4bafb55510f34cf99e7ac121874f3c01152d6d8953c661c3e5147a387fffaee672318ed39c49fa02c80fa806956695f2fdfe0429a61639e7fb544f1531100eb02b7a140ffa284746fa1620e8461e4af5f93594f8aed6d34a33d51b265bae90ea8bedccb7497594003eb46516bddb1778a4fadd02cbb227e1931eeb5ef445fb9745f85cfbebfa169c3ae7d15e2ca75b15dd020877c9a968ff853993a06420d3c3ff158800014f21e558103cd4e7e84cf5e320ebf7c525e0eab9ab22ad4af02c7ad48b5e",
},
),
# DSA
(
{
"method": "pgp+dsa-fips-180-2",
"type": "dsa",
"hashes": ["pgp+SHA2"],
"creation_time": 1510870182,
"keyid": "c242a830daaf1c2bef604a9ef033a3a3e267b3b1",
"keyval": {
"private": "",
"public": {
"y": "2dd50b2292441444581f9a0b7d8d7f88b573fc451f5e7207c324694232c22e171b508f6842ae9babc56fe4e586a22086188b4827b7aba8c7bff4a4ac9aa80c835420b1afba4ab4f1b1c0ef894437903a9f4c56ebef037804a99925c9a153b8a16c1562f297755aeaa20fa02ab32aa5366e052b6baa9a934356d4f5fc218785018dd12b2c8e6d605d2afb36cb06a9cced9ea1f5f82798d635de264ef0eb59590c4a4b2fdf2369a36f95614804c7aa5966ba9597404ba2d2c6881959112de52de4b6d4f1e2c8a59ddaadb08a59ac8334118f15aa01593e851024905ea6d884c3a545af6fdd03c8d2b54da1d35e710ef75a2b4775bb78c50b28d1e2fb48416dc941",
"p": "fca3276cd78c20e3c73ae2398674046039f5d90f41e3ede9bc99f94000d145693522671fba481d22e0a9b31e695d198da5e62f4ffb4db5dc64076d0f2d7d03ce953fc7846a6d4e17a10bf1dcd17167f7aff761b59fa2180e7fcd2ca527c03c50c78665b5539bf2b45648b6d23f31f37999e6a7b4e0876ddad7ec783b8eec7e1fb14733e74b6b0b105cbdc5a7de8e094657f2146ce43a3177581cb022a4e2ce6678a3364a56e02090559a6dfd81d91ca3b7c6afd4fcfc66fd88339d217062462f51c5c91d6eccfafb32065be68e6b91ec837c59a51baebeca1c70fd3891c9bbb67f7d920f9153fc4d2ca03f88a27b70df1684709f99ad18707189b015441b2bfb",
"g": "7f7252ae1824baf2be5fc8f431a1978683a38d4a22cc2bcdc01ccd1f5eee47a964aa57639a618cfb1b10707b4d09ff11a448e83ba70123573f2d49a599f5313a74463e5bb3ca3d6172a00f02b01065ce312501e1797f7b57e606947c44bd839fde8d43269f1fb74af6cedf4db7fabf0b2357ed09d56381ac769ef5a8af1b4450e0c88b64ee1cab9fadeb31b7be6207b7e17008a33a7613831f70a123d59279dcbc2238f46eeaa8097795b7805f1b837ef3b8e807164e186fae9fa3ff510213096bf54040eac545a6a5b47c910e6cf7e306e1f46723f14b02cd9e0b0ff2a56c3b2604869431ab3263d61bf5068bee36c880c7bf2c746dcae5d0d7b2fff244ef43",
"q": "84779eeae0238d7a9a030a639bf01a0f9ef517a5d950599c19a4e54fbbf23219",
},
},
},
{
"keyid": "c242a830daaf1c2bef604a9ef033a3a3e267b3b1",
"other_headers": "04001108001d162104c242a830daaf1c2bef604a9ef033a3a3e267b3b105025e5644d1",
"signature": "3044022009e95f952f64f559852fb6b321173f3cb142a5dbe0c84d709d55026ab945582802203144ee0f4c2cb70fa00ca6942c847208b96811271445ed85c75ebebdb609b174",
},
),
# EDDSA
(
{
"method": "pgp+eddsa-ed25519",
"type": "eddsa",
"hashes": ["pgp+SHA2"],
"creation_time": 1572269200,
"keyid": "4e630f84838bf6f7447b830b22692f5fea9e2dd2",
"keyval": {
"private": "",
"public": {
"q": "716e57b8c5d4397a4194f80bd43af2e07691db7ee58d2473ceb56cef1eda7569"
},
},
},
{
"keyid": "4e630f84838bf6f7447b830b22692f5fea9e2dd2",
"other_headers": "04001608001d1621044e630f84838bf6f7447b830b22692f5fea9e2dd205025e564505",
"signature": "70ba3fe785bccac105b837b6b27cc8d5ddd0159c3f640bbac026b744e0b10839bf4ea53e786074d32f9617389a4fe3356ec1c4a19045c5c02821563786e1d10d",
},
),
]
for key, sig in key_signature_pairs:
self.assertTrue(verify_signature(sig, key, data))
GPGSigner._key_from_legacy_dict(key).verify_signature(
GPGSigner._sig_from_legacy_dict(sig), data
)
if __name__ == "__main__":
unittest.main(verbosity=1, buffer=True)
|