|
|
@@ -43,6 +43,15 @@ class SignatureVendor:
|
|
|
"""
|
|
|
self.config = config
|
|
|
|
|
|
+ @classmethod
|
|
|
+ def available(cls) -> bool:
|
|
|
+ """Check if this signature vendor is available.
|
|
|
+
|
|
|
+ Returns:
|
|
|
+ True if the vendor's dependencies are available, False otherwise
|
|
|
+ """
|
|
|
+ return True # Base class is always available
|
|
|
+
|
|
|
def sign(self, data: bytes, keyid: str | None = None) -> bytes:
|
|
|
"""Sign data with a key.
|
|
|
|
|
|
@@ -100,6 +109,17 @@ class GPGSignatureVendor(SignatureVendor):
|
|
|
except KeyError:
|
|
|
pass
|
|
|
|
|
|
+ @classmethod
|
|
|
+ def available(cls) -> bool:
|
|
|
+ """Check if the gpg Python package is available.
|
|
|
+
|
|
|
+ Returns:
|
|
|
+ True if gpg package can be imported, False otherwise
|
|
|
+ """
|
|
|
+ import importlib.util
|
|
|
+
|
|
|
+ return importlib.util.find_spec("gpg") is not None
|
|
|
+
|
|
|
def sign(self, data: bytes, keyid: str | None = None) -> bytes:
|
|
|
"""Sign data with a GPG key.
|
|
|
|
|
|
@@ -213,6 +233,17 @@ class GPGCliSignatureVendor(SignatureVendor):
|
|
|
else:
|
|
|
self.gpg_command = "gpg"
|
|
|
|
|
|
+ @classmethod
|
|
|
+ def available(cls) -> bool:
|
|
|
+ """Check if the gpg command is available.
|
|
|
+
|
|
|
+ Returns:
|
|
|
+ True if gpg command is in PATH, False otherwise
|
|
|
+ """
|
|
|
+ import shutil
|
|
|
+
|
|
|
+ return shutil.which("gpg") is not None
|
|
|
+
|
|
|
def sign(self, data: bytes, keyid: str | None = None) -> bytes:
|
|
|
"""Sign data with a GPG key using the command-line tool.
|
|
|
|
|
|
@@ -360,6 +391,17 @@ class X509SignatureVendor(SignatureVendor):
|
|
|
else:
|
|
|
self.gpgsm_command = "gpgsm"
|
|
|
|
|
|
+ @classmethod
|
|
|
+ def available(cls) -> bool:
|
|
|
+ """Check if the gpgsm command is available.
|
|
|
+
|
|
|
+ Returns:
|
|
|
+ True if gpgsm command is in PATH, False otherwise
|
|
|
+ """
|
|
|
+ import shutil
|
|
|
+
|
|
|
+ return shutil.which("gpgsm") is not None
|
|
|
+
|
|
|
def sign(self, data: bytes, keyid: str | None = None) -> bytes:
|
|
|
"""Sign data with an X.509 certificate using gpgsm.
|
|
|
|
|
|
@@ -515,6 +557,17 @@ class SSHSigSignatureVendor(SignatureVendor):
|
|
|
except KeyError:
|
|
|
pass
|
|
|
|
|
|
+ @classmethod
|
|
|
+ def available(cls) -> bool:
|
|
|
+ """Check if the sshsig Python package is available.
|
|
|
+
|
|
|
+ Returns:
|
|
|
+ True if sshsig package can be imported, False otherwise
|
|
|
+ """
|
|
|
+ import importlib.util
|
|
|
+
|
|
|
+ return importlib.util.find_spec("sshsig") is not None
|
|
|
+
|
|
|
def sign(self, data: bytes, keyid: str | None = None) -> bytes:
|
|
|
"""Sign data with an SSH key.
|
|
|
|
|
|
@@ -677,6 +730,17 @@ class SSHCliSignatureVendor(SignatureVendor):
|
|
|
except KeyError:
|
|
|
pass
|
|
|
|
|
|
+ @classmethod
|
|
|
+ def available(cls) -> bool:
|
|
|
+ """Check if the ssh-keygen command is available.
|
|
|
+
|
|
|
+ Returns:
|
|
|
+ True if ssh-keygen command is in PATH, False otherwise
|
|
|
+ """
|
|
|
+ import shutil
|
|
|
+
|
|
|
+ return shutil.which("ssh-keygen") is not None
|
|
|
+
|
|
|
def sign(self, data: bytes, keyid: str | None = None) -> bytes:
|
|
|
"""Sign data with an SSH key using ssh-keygen.
|
|
|
|