Digital signature creation and verification operations for data integrity and authenticity, supporting multiple signature formats and comprehensive verification.
Create digital signatures for data integrity and authenticity verification with support for clear-text signing, detached signatures, and binary signatures.
def sign(self, message, **kwargs):
"""
Sign a message string.
Parameters:
- message (str): Data to sign
- keyid (str): Key ID or fingerprint to sign with
- passphrase (str): Passphrase for the signing key
- clearsign (bool): Create clear-text signature (default: True)
- detach (bool): Create detached signature
- binary (bool): Create binary signature
- extra_args (list): Additional GPG arguments
Returns:
Sign: Result object with signed data and signature information
"""
def sign_file(self, fileobj_or_path, keyid=None, passphrase=None,
clearsign=True, detach=False, binary=False, output=None,
extra_args=None):
"""
Sign a file or file-like object.
Parameters:
- fileobj_or_path (str|file): File path or file-like object to sign
- keyid (str): Key ID to sign with
- passphrase (str): Passphrase for the signing key
- clearsign (bool): Create clear-text signature
- detach (bool): Create detached signature file
- binary (bool): Create binary signature
- output (str): Output file path for signature
- extra_args (list): Additional GPG arguments
Returns:
Sign: Result object with signing status and signature data
"""Verify digital signatures to confirm data integrity and authenticity with comprehensive verification information.
def verify(self, data, **kwargs):
"""
Verify signature on data string.
Parameters:
- data (str): Signed data to verify
- extra_args (list): Additional GPG arguments
Returns:
Verify: Result object with verification status and signer information
"""
def verify_file(self, fileobj_or_path, data_filename=None,
close_file=True, extra_args=None):
"""
Verify signature on a file.
Parameters:
- fileobj_or_path (str|file): File path or file-like object with signature
- data_filename (str): Path to data file (for detached signatures)
- close_file (bool): Whether to close file after verification
- extra_args (list): Additional GPG arguments
Returns:
Verify: Result object with verification details
"""
def verify_data(self, sig_filename, data, extra_args=None):
"""
Verify detached signature against data in memory.
Parameters:
- sig_filename (str): Path to detached signature file
- data (str): Data to verify against signature
- extra_args (list): Additional GPG arguments
Returns:
Verify: Result object with verification status
"""class Sign(StatusHandler):
type: str # Signature type ('signature', 'clearsign', 'detached')
data: str # Signed data (for clear-text and attached signatures)
fingerprint: str # Signing key fingerprint
timestamp: str # Signature timestamp
what: str # What was signed
hash_algo: str # Hash algorithm used
class Verify(StatusHandler):
valid: bool # True if signature is valid
fingerprint: str # Signer's key fingerprint
signature_id: str # Unique signature identifier
username: str # Signer's user ID
key_id: str # Signing key ID
trust_level: int # Trust level (0-4)
trust_text: str # Human-readable trust level
creation_date: str # Signature creation date
sig_timestamp: str # Signature timestamp
expire_timestamp: str # Signature expiration
pubkey_fingerprint: str # Public key fingerprint
# Additional verification details
key_status: str # Key status ('GOODSIG', 'BADSIG', 'ERRSIG', etc.)
summary: int # Summary flags
status: str # Verification status messageimport gnupg
gpg = gnupg.GPG()
# Clear-text signing (readable text with signature)
message = "This document needs to be signed for authenticity."
signed = gpg.sign(message,
keyid='signer@example.com',
passphrase='signing_passphrase')
if signed.status == 'signature created':
print("Signing successful")
print(str(signed)) # Clear-text signed message
else:
print(f"Signing failed: {signed.status}")# Create detached signature (signature in separate data)
message = "Important document content"
signature = gpg.sign(message,
keyid='signer@example.com',
passphrase='signing_passphrase',
detach=True,
clearsign=False)
print("Original message:", message)
print("Detached signature:", str(signature))
# Verify detached signature
# (message and signature are separate)
verified = gpg.verify_data(signature, message)# Sign a file with clear-text signature
result = gpg.sign_file(
'/path/to/document.txt',
keyid='signer@example.com',
passphrase='signing_passphrase',
output='/path/to/document.txt.asc'
)
# Create detached signature file
result = gpg.sign_file(
'/path/to/document.pdf',
keyid='signer@example.com',
passphrase='signing_passphrase',
detach=True,
output='/path/to/document.pdf.sig'
)
# Binary signature
result = gpg.sign_file(
'/path/to/data.bin',
keyid='signer@example.com',
passphrase='signing_passphrase',
binary=True,
output='/path/to/data.bin.gpg'
)# Verify clear-text signed message
signed_message = """-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
This is the message content.
-----BEGIN PGP SIGNATURE-----
iQEzBAEBCAAdFiEE...
-----END PGP SIGNATURE-----"""
verified = gpg.verify(signed_message)
if verified.valid:
print("Signature is valid!")
print(f"Signed by: {verified.username}")
print(f"Key fingerprint: {verified.fingerprint}")
print(f"Created: {verified.creation_date}")
print(f"Trust level: {verified.trust_text}")
else:
print(f"Signature verification failed: {verified.status}")# Verify file signature
result = gpg.verify_file('/path/to/signed_document.asc')
if result.valid:
print("File signature valid")
print(f"Signer: {result.username}")
print(f"Key ID: {result.key_id}")
print(f"Trust: {result.trust_text}")
# Check trust level programmatically
if result.trust_level >= 3: # Marginal trust or better
print("Signer is trusted")
else:
print("Warning: Signer trust level is low")
else:
print(f"Invalid signature: {result.status}")
# Verify detached signature against data file
data_verified = gpg.verify_data(
'/path/to/document.pdf.sig', # Signature file
open('/path/to/document.pdf', 'rb').read() # Original data
)def verify_document(gpg_instance, signed_data):
"""Comprehensive document verification with detailed reporting."""
result = gpg_instance.verify(signed_data)
verification_report = {
'valid': result.valid,
'signer': result.username,
'fingerprint': result.fingerprint,
'created': result.creation_date,
'trust_level': result.trust_level,
'trust_text': result.trust_text,
'key_status': result.key_status,
'warnings': []
}
# Analyze verification results
if not result.valid:
verification_report['warnings'].append(f"Invalid signature: {result.status}")
return verification_report
# Check trust level
if result.trust_level < 2:
verification_report['warnings'].append("Signer has very low trust level")
elif result.trust_level < 3:
verification_report['warnings'].append("Signer has low trust level")
# Check key status
if result.key_status == 'EXPKEYSIG':
verification_report['warnings'].append("Signature made with expired key")
elif result.key_status == 'REVKEYSIG':
verification_report['warnings'].append("Signature made with revoked key")
# Check signature age (example: warn if older than 1 year)
from datetime import datetime, timedelta
try:
sig_date = datetime.strptime(result.creation_date, '%Y-%m-%d')
if datetime.now() - sig_date > timedelta(days=365):
verification_report['warnings'].append("Signature is over 1 year old")
except:
pass # Date parsing failed
return verification_report
# Usage
report = verify_document(gpg, signed_message)
print(f"Valid: {report['valid']}")
print(f"Signer: {report['signer']}")
for warning in report['warnings']:
print(f"Warning: {warning}")# Some messages may have multiple signatures
# Each signature is verified independently
def verify_all_signatures(gpg_instance, multi_signed_data):
"""Handle data with potentially multiple signatures."""
results = []
# GPG will verify all signatures in the data
result = gpg_instance.verify(multi_signed_data)
# Process primary signature
if hasattr(result, 'signature_id'):
results.append({
'valid': result.valid,
'signer': result.username,
'fingerprint': result.fingerprint,
'signature_id': result.signature_id
})
# Note: For multiple signatures, you may need to parse
# the GPG output or use additional verification calls
return resultsdef robust_verify(gpg_instance, signed_data):
"""Robust verification with comprehensive error handling."""
try:
result = gpg_instance.verify(signed_data)
if result.valid:
return {
'status': 'valid',
'signer': result.username,
'fingerprint': result.fingerprint,
'trust': result.trust_text
}
else:
# Analyze why verification failed
if 'no public key' in result.status.lower():
return {
'status': 'missing_key',
'message': 'Public key not in keyring',
'key_id': getattr(result, 'key_id', 'unknown')
}
elif 'bad signature' in result.status.lower():
return {
'status': 'bad_signature',
'message': 'Signature does not match data'
}
else:
return {
'status': 'verification_failed',
'message': result.status,
'stderr': result.stderr
}
except Exception as e:
return {
'status': 'error',
'message': f'Verification error: {str(e)}'
}
# Usage with error handling
verification_result = robust_verify(gpg, signed_document)
if verification_result['status'] == 'valid':
print(f"Valid signature from {verification_result['signer']}")
elif verification_result['status'] == 'missing_key':
print(f"Need to import key: {verification_result['key_id']}")
else:
print(f"Verification issue: {verification_result['message']}")