← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~cjwatson/lp-signing:log-message-hashes into lp-signing:master

 

Colin Watson has proposed merging ~cjwatson/lp-signing:log-message-hashes into lp-signing:master.

Commit message:
Log SHA-256 hashes of messages when signing them

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/lp-signing/+git/lp-signing/+merge/415561

Otherwise we have no way to trace back from logs to when a given message
was signed.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/lp-signing:log-message-hashes into lp-signing:master.
diff --git a/lp_signing/model/key.py b/lp_signing/model/key.py
index ebcfc6a..a7e627a 100644
--- a/lp_signing/model/key.py
+++ b/lp_signing/model/key.py
@@ -677,8 +677,10 @@ class Key(Storm):
                 f"Signature mode {mode.name} not supported with "
                 f"{self.key_type.name}")
         _log.info(
-            "Making %s signature of %s with %s key %s",
-            mode.name.lower(), message_name, self.key_type, self.fingerprint)
+            "Making %s signature of %s (SHA-256: %s) with %s key %s",
+            mode.name.lower(), message_name,
+            hashlib.sha256(message).hexdigest(), self.key_type,
+            self.fingerprint)
         with _gpg_context(tmp) as ctx:
             import_result = _gpg_key_import(ctx, self.getPrivateKey())
             if not getattr(import_result, "secret_imported", 0):
@@ -759,8 +761,9 @@ class Key(Storm):
                     f"{self.key_type.name}")
 
             _log.info(
-                "Making %s signature of %s with %s key %s",
-                mode.name.lower(), message_name, self.key_type,
+                "Making %s signature of %s (SHA-256: %s) with %s key %s",
+                mode.name.lower(), message_name,
+                hashlib.sha256(message).hexdigest(), self.key_type,
                 self.fingerprint)
             try:
                 _log_subprocess_run(cmd, check=True)
diff --git a/lp_signing/model/tests/test_key.py b/lp_signing/model/tests/test_key.py
index 7f7f743..3a49a28 100644
--- a/lp_signing/model/tests/test_key.py
+++ b/lp_signing/model/tests/test_key.py
@@ -15,6 +15,7 @@ from tempfile import TemporaryDirectory
 from fixtures import MockPatch
 from flask_storm import store
 import gpg
+from talisker.testing import TestContext
 from testtools import TestCase
 from testtools.matchers import (
     AfterPreprocessing,
@@ -504,12 +505,14 @@ class TestKey(TestCase):
 
     def test_sign_uefi_attached(self):
         key = factory.create_key(KeyType.UEFI)
+        message = b"test data"
         fake_sbsign = FakeSBSign(b"test signed data")
         self.processes_fixture.add(fake_sbsign)
-        self.assertEqual(
-            b"test signed data",
-            key.sign("t.efi", b"test data", SignatureMode.ATTACHED))
-        self.assertEqual(b"test data", fake_sbsign.message_bytes)
+        with TestContext() as ctx:
+            self.assertEqual(
+                b"test signed data",
+                key.sign("t.efi", message, SignatureMode.ATTACHED))
+        self.assertEqual(message, fake_sbsign.message_bytes)
         sbsign_args = [
             "sbsign", "--key", EndsWith("uefi.key"),
             "--cert", EndsWith("uefi.crt"), EndsWith("t.efi"),
@@ -517,6 +520,13 @@ class TestKey(TestCase):
         self.assertThat(
             self.processes_fixture.procs,
             MatchesListwise([RanCommand(sbsign_args)]))
+        message_sha256 = hashlib.sha256(message).hexdigest()
+        ctx.assert_log(
+            level="info",
+            message=(
+                f"Making attached signature of t.efi "
+                f"(SHA-256: {message_sha256}) with UEFI key "
+                f"{key.fingerprint}"))
 
     def test_sign_uefi_detached_unsupported(self):
         key = factory.create_key(KeyType.UEFI)
@@ -538,12 +548,14 @@ class TestKey(TestCase):
 
     def test_sign_kmod_detached(self):
         key = factory.create_key(KeyType.KMOD)
+        message = b"test data"
         fake_kmodsign = FakeKmodSign(b"test signed data")
         self.processes_fixture.add(fake_kmodsign)
-        self.assertEqual(
-            b"test signed data",
-            key.sign("t.ko", b"test data", SignatureMode.DETACHED))
-        self.assertEqual(b"test data", fake_kmodsign.message_bytes)
+        with TestContext() as ctx:
+            self.assertEqual(
+                b"test signed data",
+                key.sign("t.ko", message, SignatureMode.DETACHED))
+        self.assertEqual(message, fake_kmodsign.message_bytes)
         kmodsign_args = [
             "kmodsign", "-D", "sha512",
             EndsWith("kmod.key"), EndsWith("kmod.crt"),
@@ -552,6 +564,13 @@ class TestKey(TestCase):
         self.assertThat(
             self.processes_fixture.procs,
             MatchesListwise([RanCommand(kmodsign_args)]))
+        message_sha256 = hashlib.sha256(message).hexdigest()
+        ctx.assert_log(
+            level="info",
+            message=(
+                f"Making detached signature of t.ko "
+                f"(SHA-256: {message_sha256}) with Kmod key "
+                f"{key.fingerprint}"))
 
     def test_sign_kmod_clear_unsupported(self):
         key = factory.create_key(KeyType.KMOD)
@@ -567,12 +586,14 @@ class TestKey(TestCase):
 
     def test_sign_opal_detached(self):
         key = factory.create_key(KeyType.OPAL)
+        message = b"test data"
         fake_kmodsign = FakeKmodSign(b"test signed data")
         self.processes_fixture.add(fake_kmodsign)
-        self.assertEqual(
-            b"test signed data",
-            key.sign("t.opal", b"test data", SignatureMode.DETACHED))
-        self.assertEqual(b"test data", fake_kmodsign.message_bytes)
+        with TestContext() as ctx:
+            self.assertEqual(
+                b"test signed data",
+                key.sign("t.opal", message, SignatureMode.DETACHED))
+        self.assertEqual(message, fake_kmodsign.message_bytes)
         kmodsign_args = [
             "kmodsign", "-D", "sha512",
             EndsWith("opal.key"), EndsWith("opal.crt"),
@@ -581,6 +602,13 @@ class TestKey(TestCase):
         self.assertThat(
             self.processes_fixture.procs,
             MatchesListwise([RanCommand(kmodsign_args)]))
+        message_sha256 = hashlib.sha256(message).hexdigest()
+        ctx.assert_log(
+            level="info",
+            message=(
+                f"Making detached signature of t.opal "
+                f"(SHA-256: {message_sha256}) with OPAL key "
+                f"{key.fingerprint}"))
 
     def test_sign_opal_clear_unsupported(self):
         key = factory.create_key(KeyType.OPAL)
@@ -596,12 +624,14 @@ class TestKey(TestCase):
 
     def test_sign_sipl_detached(self):
         key = factory.create_key(KeyType.SIPL)
+        message = b"test data"
         fake_kmodsign = FakeKmodSign(b"test signed data")
         self.processes_fixture.add(fake_kmodsign)
-        self.assertEqual(
-            b"test signed data",
-            key.sign("t.sipl", b"test data", SignatureMode.DETACHED))
-        self.assertEqual(b"test data", fake_kmodsign.message_bytes)
+        with TestContext() as ctx:
+            self.assertEqual(
+                b"test signed data",
+                key.sign("t.sipl", message, SignatureMode.DETACHED))
+        self.assertEqual(message, fake_kmodsign.message_bytes)
         kmodsign_args = [
             "kmodsign", "-D", "sha512",
             EndsWith("sipl.key"), EndsWith("sipl.crt"),
@@ -610,6 +640,13 @@ class TestKey(TestCase):
         self.assertThat(
             self.processes_fixture.procs,
             MatchesListwise([RanCommand(kmodsign_args)]))
+        message_sha256 = hashlib.sha256(message).hexdigest()
+        ctx.assert_log(
+            level="info",
+            message=(
+                f"Making detached signature of t.sipl "
+                f"(SHA-256: {message_sha256}) with SIPL key "
+                f"{key.fingerprint}"))
 
     def test_sign_sipl_clear_unsupported(self):
         key = factory.create_key(KeyType.SIPL)
@@ -619,12 +656,14 @@ class TestKey(TestCase):
 
     def test_sign_fit_attached(self):
         key = factory.create_key(KeyType.FIT)
+        message = b"test data"
         fake_mkimage = FakeMkimage(b"test signed data")
         self.processes_fixture.add(fake_mkimage)
-        self.assertEqual(
-            b"test signed data",
-            key.sign("t.fit", b"test data", SignatureMode.ATTACHED))
-        self.assertEqual(b"test data", fake_mkimage.message_bytes)
+        with TestContext() as ctx:
+            self.assertEqual(
+                b"test signed data",
+                key.sign("t.fit", message, SignatureMode.ATTACHED))
+        self.assertEqual(message, fake_mkimage.message_bytes)
         mkimage_args = [
             "mkimage", "-F", "-k", Not(Is(None)), "-r",
             EndsWith("t.fit.signed"),
@@ -632,6 +671,13 @@ class TestKey(TestCase):
         self.assertThat(
             self.processes_fixture.procs,
             MatchesListwise([RanCommand(mkimage_args)]))
+        message_sha256 = hashlib.sha256(message).hexdigest()
+        ctx.assert_log(
+            level="info",
+            message=(
+                f"Making attached signature of t.fit "
+                f"(SHA-256: {message_sha256}) with FIT key "
+                f"{key.fingerprint}"))
 
     def test_sign_fit_detached_unsupported(self):
         key = factory.create_key(KeyType.FIT)
@@ -649,37 +695,64 @@ class TestKey(TestCase):
         key = Key.generate(
             KeyType.OPENPGP, "~signing-owner/ubuntu/testing",
             openpgp_key_algorithm=OpenPGPKeyAlgorithm.RSA, length=1024)
+        message = b"test data"
         mock_sign = self.useFixture(MockPatch(
             "gpg.Context.sign", return_value=(b"test signed data", None))).mock
-        self.assertEqual(
-            b"test signed data",
-            key.sign("t.gpg", b"test data", SignatureMode.ATTACHED))
+        with TestContext() as ctx:
+            self.assertEqual(
+                b"test signed data",
+                key.sign("t.gpg", message, SignatureMode.ATTACHED))
         mock_sign.assert_called_once_with(
-            b"test data", mode=gpg.constants.SIG_MODE_NORMAL)
+            message, mode=gpg.constants.SIG_MODE_NORMAL)
+        message_sha256 = hashlib.sha256(message).hexdigest()
+        ctx.assert_log(
+            level="info",
+            message=(
+                f"Making attached signature of t.gpg "
+                f"(SHA-256: {message_sha256}) with OpenPGP key "
+                f"{key.fingerprint}"))
 
     def test_sign_openpgp_detached(self):
         key = Key.generate(
             KeyType.OPENPGP, "~signing-owner/ubuntu/testing",
             openpgp_key_algorithm=OpenPGPKeyAlgorithm.RSA, length=1024)
+        message = b"test data"
         mock_sign = self.useFixture(MockPatch(
             "gpg.Context.sign", return_value=(b"test signed data", None))).mock
-        self.assertEqual(
-            b"test signed data",
-            key.sign("t.gpg", b"test data", SignatureMode.DETACHED))
+        with TestContext() as ctx:
+            self.assertEqual(
+                b"test signed data",
+                key.sign("t.gpg", message, SignatureMode.DETACHED))
         mock_sign.assert_called_once_with(
-            b"test data", mode=gpg.constants.SIG_MODE_DETACH)
+            message, mode=gpg.constants.SIG_MODE_DETACH)
+        message_sha256 = hashlib.sha256(message).hexdigest()
+        ctx.assert_log(
+            level="info",
+            message=(
+                f"Making detached signature of t.gpg "
+                f"(SHA-256: {message_sha256}) with OpenPGP key "
+                f"{key.fingerprint}"))
 
     def test_sign_openpgp_clear(self):
         key = Key.generate(
             KeyType.OPENPGP, "~signing-owner/ubuntu/testing",
             openpgp_key_algorithm=OpenPGPKeyAlgorithm.RSA, length=1024)
+        message = b"test data"
         mock_sign = self.useFixture(MockPatch(
             "gpg.Context.sign", return_value=(b"test signed data", None))).mock
-        self.assertEqual(
-            b"test signed data",
-            key.sign("t.gpg", b"test data", SignatureMode.CLEAR))
+        with TestContext() as ctx:
+            self.assertEqual(
+                b"test signed data",
+                key.sign("t.gpg", message, SignatureMode.CLEAR))
         mock_sign.assert_called_once_with(
-            b"test data", mode=gpg.constants.SIG_MODE_CLEAR)
+            message, mode=gpg.constants.SIG_MODE_CLEAR)
+        message_sha256 = hashlib.sha256(message).hexdigest()
+        ctx.assert_log(
+            level="info",
+            message=(
+                f"Making clear signature of t.gpg "
+                f"(SHA-256: {message_sha256}) with OpenPGP key "
+                f"{key.fingerprint}"))
 
     def test_sign_cv2_kernel_attached_unsupported(self):
         key = factory.create_key(KeyType.CV2_KERNEL)
@@ -689,12 +762,14 @@ class TestKey(TestCase):
 
     def test_sign_cv2_kernel_detached(self):
         key = factory.create_key(KeyType.CV2_KERNEL)
+        message = b"test data"
         fake_openssl_sign = FakeOpenSSLSign(b"test signed data")
         self.processes_fixture.add(fake_openssl_sign)
-        self.assertEqual(
-            b"test signed data",
-            key.sign("t.cv2_kernel", b"test data", SignatureMode.DETACHED))
-        self.assertEqual(b"test data", fake_openssl_sign.message_bytes)
+        with TestContext() as ctx:
+            self.assertEqual(
+                b"test signed data",
+                key.sign("t.cv2_kernel", message, SignatureMode.DETACHED))
+        self.assertEqual(message, fake_openssl_sign.message_bytes)
         openssl_sign_args = [
             "openssl", "dgst", "-sha256", "-sign", EndsWith("cv2_kernel.priv"),
             "-out", EndsWith("t.cv2_kernel.sig"), EndsWith("t.cv2_kernel"),
@@ -702,6 +777,13 @@ class TestKey(TestCase):
         self.assertThat(
             self.processes_fixture.procs,
             MatchesListwise([RanCommand(openssl_sign_args)]))
+        message_sha256 = hashlib.sha256(message).hexdigest()
+        ctx.assert_log(
+            level="info",
+            message=(
+                f"Making detached signature of t.cv2_kernel "
+                f"(SHA-256: {message_sha256}) with CV2 Kernel key "
+                f"{key.fingerprint}"))
 
     def test_sign_cv2_kernel_clear_unsupported(self):
         key = factory.create_key(KeyType.CV2_KERNEL)
@@ -717,12 +799,14 @@ class TestKey(TestCase):
 
     def test_sign_android_kernel_detached(self):
         key = factory.create_key(KeyType.ANDROID_KERNEL)
+        message = b"test data"
         fake_openssl_sign = FakeOpenSSLSign(b"test signed data")
         self.processes_fixture.add(fake_openssl_sign)
-        self.assertEqual(
-            b"test signed data",
-            key.sign("t.android_kernel", b"test data", SignatureMode.DETACHED))
-        self.assertEqual(b"test data", fake_openssl_sign.message_bytes)
+        with TestContext() as ctx:
+            self.assertEqual(
+                b"test signed data",
+                key.sign("t.android_kernel", message, SignatureMode.DETACHED))
+        self.assertEqual(message, fake_openssl_sign.message_bytes)
         openssl_sign_args = [
             "openssl", "dgst", "-sha256", "-sign",
             EndsWith("android_kernel.key"),
@@ -732,6 +816,13 @@ class TestKey(TestCase):
         self.assertThat(
             self.processes_fixture.procs,
             MatchesListwise([RanCommand(openssl_sign_args)]))
+        message_sha256 = hashlib.sha256(message).hexdigest()
+        ctx.assert_log(
+            level="info",
+            message=(
+                f"Making detached signature of t.android_kernel "
+                f"(SHA-256: {message_sha256}) with Android Kernel key "
+                f"{key.fingerprint}"))
 
     def test_sign_android_kernel_clear_unsupported(self):
         key = factory.create_key(KeyType.ANDROID_KERNEL)