mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-16 04:35:18 +03:00
Initial commit - 611 cybersecurity skills across all subdomains
This commit is contained in:
@@ -0,0 +1,319 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Ed25519 Digital Signature Tool
|
||||
|
||||
Implements Ed25519 key generation, signing, verification, and a
|
||||
simple code signing system.
|
||||
|
||||
Requirements:
|
||||
pip install cryptography
|
||||
|
||||
Usage:
|
||||
python process.py generate --output ./keys
|
||||
python process.py sign --key ./keys/private.pem --input document.pdf
|
||||
python process.py verify --key ./keys/public.pem --input document.pdf --signature document.pdf.sig
|
||||
python process.py code-sign --key ./keys/private.pem --artifact ./build/app.zip
|
||||
python process.py benchmark
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import time
|
||||
import hashlib
|
||||
import argparse
|
||||
import logging
|
||||
import datetime
|
||||
import base64
|
||||
from pathlib import Path
|
||||
from typing import Dict, Optional, Tuple
|
||||
|
||||
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey, Ed25519PublicKey
|
||||
from cryptography.hazmat.primitives import serialization
|
||||
from cryptography.exceptions import InvalidSignature
|
||||
|
||||
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def generate_ed25519_keypair(
|
||||
output_dir: str, passphrase: Optional[str] = None
|
||||
) -> Dict:
|
||||
"""Generate an Ed25519 key pair."""
|
||||
private_key = Ed25519PrivateKey.generate()
|
||||
public_key = private_key.public_key()
|
||||
|
||||
output_path = Path(output_dir)
|
||||
output_path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
if passphrase:
|
||||
enc = serialization.BestAvailableEncryption(passphrase.encode())
|
||||
else:
|
||||
enc = serialization.NoEncryption()
|
||||
|
||||
private_pem = private_key.private_bytes(
|
||||
encoding=serialization.Encoding.PEM,
|
||||
format=serialization.PrivateFormat.PKCS8,
|
||||
encryption_algorithm=enc,
|
||||
)
|
||||
(output_path / "private.pem").write_bytes(private_pem)
|
||||
|
||||
public_pem = public_key.public_bytes(
|
||||
encoding=serialization.Encoding.PEM,
|
||||
format=serialization.PublicFormat.SubjectPublicKeyInfo,
|
||||
)
|
||||
(output_path / "public.pem").write_bytes(public_pem)
|
||||
|
||||
# Compute fingerprint
|
||||
public_raw = public_key.public_bytes(
|
||||
encoding=serialization.Encoding.Raw,
|
||||
format=serialization.PublicFormat.Raw,
|
||||
)
|
||||
fingerprint = hashlib.sha256(public_raw).hexdigest()
|
||||
|
||||
metadata = {
|
||||
"algorithm": "Ed25519",
|
||||
"public_key_hex": public_raw.hex(),
|
||||
"fingerprint_sha256": fingerprint,
|
||||
"created_at": datetime.datetime.utcnow().isoformat() + "Z",
|
||||
"private_key_path": str(output_path / "private.pem"),
|
||||
"public_key_path": str(output_path / "public.pem"),
|
||||
}
|
||||
(output_path / "key_metadata.json").write_text(json.dumps(metadata, indent=2))
|
||||
|
||||
logger.info(f"Ed25519 key pair generated in {output_dir}")
|
||||
logger.info(f"Fingerprint: {fingerprint}")
|
||||
return metadata
|
||||
|
||||
|
||||
def load_private_key(path: str, passphrase: Optional[str] = None) -> Ed25519PrivateKey:
|
||||
"""Load Ed25519 private key from PEM file."""
|
||||
data = Path(path).read_bytes()
|
||||
pwd = passphrase.encode() if passphrase else None
|
||||
key = serialization.load_pem_private_key(data, password=pwd)
|
||||
if not isinstance(key, Ed25519PrivateKey):
|
||||
raise TypeError("Key is not Ed25519")
|
||||
return key
|
||||
|
||||
|
||||
def load_public_key(path: str) -> Ed25519PublicKey:
|
||||
"""Load Ed25519 public key from PEM file."""
|
||||
data = Path(path).read_bytes()
|
||||
key = serialization.load_pem_public_key(data)
|
||||
if not isinstance(key, Ed25519PublicKey):
|
||||
raise TypeError("Key is not Ed25519")
|
||||
return key
|
||||
|
||||
|
||||
def sign_data(data: bytes, private_key: Ed25519PrivateKey) -> bytes:
|
||||
"""Sign data with Ed25519."""
|
||||
return private_key.sign(data)
|
||||
|
||||
|
||||
def verify_data(data: bytes, signature: bytes, public_key: Ed25519PublicKey) -> bool:
|
||||
"""Verify Ed25519 signature."""
|
||||
try:
|
||||
public_key.verify(signature, data)
|
||||
return True
|
||||
except InvalidSignature:
|
||||
return False
|
||||
|
||||
|
||||
def sign_file(key_path: str, input_path: str, passphrase: Optional[str] = None) -> Dict:
|
||||
"""Sign a file and save the signature."""
|
||||
private_key = load_private_key(key_path, passphrase)
|
||||
data = Path(input_path).read_bytes()
|
||||
|
||||
signature = sign_data(data, private_key)
|
||||
sig_path = input_path + ".sig"
|
||||
Path(sig_path).write_bytes(signature)
|
||||
|
||||
# Also save base64 signature for text-friendly contexts
|
||||
sig_b64_path = input_path + ".sig.b64"
|
||||
Path(sig_b64_path).write_text(base64.b64encode(signature).decode())
|
||||
|
||||
file_hash = hashlib.sha256(data).hexdigest()
|
||||
|
||||
logger.info(f"Signed {input_path} ({len(data)} bytes)")
|
||||
return {
|
||||
"file": input_path,
|
||||
"signature_file": sig_path,
|
||||
"signature_b64_file": sig_b64_path,
|
||||
"signature_hex": signature.hex(),
|
||||
"file_sha256": file_hash,
|
||||
"algorithm": "Ed25519",
|
||||
}
|
||||
|
||||
|
||||
def verify_file(key_path: str, input_path: str, sig_path: str) -> Dict:
|
||||
"""Verify a file's Ed25519 signature."""
|
||||
public_key = load_public_key(key_path)
|
||||
data = Path(input_path).read_bytes()
|
||||
signature = Path(sig_path).read_bytes()
|
||||
|
||||
# Handle base64 encoded signatures
|
||||
if len(signature) != 64:
|
||||
try:
|
||||
signature = base64.b64decode(signature)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
valid = verify_data(data, signature, public_key)
|
||||
logger.info(f"Verification: {'VALID' if valid else 'INVALID'}")
|
||||
|
||||
return {
|
||||
"file": input_path,
|
||||
"valid": valid,
|
||||
"file_sha256": hashlib.sha256(data).hexdigest(),
|
||||
"algorithm": "Ed25519",
|
||||
}
|
||||
|
||||
|
||||
def code_sign(key_path: str, artifact_path: str, passphrase: Optional[str] = None) -> Dict:
|
||||
"""Create a code signing manifest for an artifact."""
|
||||
private_key = load_private_key(key_path, passphrase)
|
||||
data = Path(artifact_path).read_bytes()
|
||||
|
||||
public_raw = private_key.public_key().public_bytes(
|
||||
encoding=serialization.Encoding.Raw,
|
||||
format=serialization.PublicFormat.Raw,
|
||||
)
|
||||
|
||||
manifest = {
|
||||
"artifact": Path(artifact_path).name,
|
||||
"size": len(data),
|
||||
"sha256": hashlib.sha256(data).hexdigest(),
|
||||
"sha512": hashlib.sha512(data).hexdigest(),
|
||||
"signer_public_key": public_raw.hex(),
|
||||
"signer_fingerprint": hashlib.sha256(public_raw).hexdigest(),
|
||||
"signed_at": datetime.datetime.utcnow().isoformat() + "Z",
|
||||
"algorithm": "Ed25519",
|
||||
}
|
||||
|
||||
manifest_json = json.dumps(manifest, indent=2, sort_keys=True).encode()
|
||||
signature = sign_data(manifest_json, private_key)
|
||||
|
||||
signed_manifest = {
|
||||
**manifest,
|
||||
"signature": base64.b64encode(signature).decode(),
|
||||
}
|
||||
|
||||
manifest_path = artifact_path + ".manifest.json"
|
||||
Path(manifest_path).write_text(json.dumps(signed_manifest, indent=2))
|
||||
|
||||
logger.info(f"Code signed: {artifact_path}")
|
||||
return signed_manifest
|
||||
|
||||
|
||||
def verify_code_signature(manifest_path: str, artifact_path: str) -> Dict:
|
||||
"""Verify a code signing manifest."""
|
||||
signed_manifest = json.loads(Path(manifest_path).read_text())
|
||||
signature = base64.b64decode(signed_manifest["signature"])
|
||||
|
||||
public_raw = bytes.fromhex(signed_manifest["signer_public_key"])
|
||||
public_key = Ed25519PublicKey.from_public_bytes(public_raw)
|
||||
|
||||
manifest_copy = {k: v for k, v in signed_manifest.items() if k != "signature"}
|
||||
manifest_json = json.dumps(manifest_copy, indent=2, sort_keys=True).encode()
|
||||
|
||||
sig_valid = verify_data(manifest_json, signature, public_key)
|
||||
|
||||
data = Path(artifact_path).read_bytes()
|
||||
hash_valid = hashlib.sha256(data).hexdigest() == signed_manifest["sha256"]
|
||||
|
||||
return {
|
||||
"artifact": artifact_path,
|
||||
"signature_valid": sig_valid,
|
||||
"hash_valid": hash_valid,
|
||||
"overall_valid": sig_valid and hash_valid,
|
||||
"signer_fingerprint": signed_manifest["signer_fingerprint"],
|
||||
}
|
||||
|
||||
|
||||
def benchmark():
|
||||
"""Benchmark Ed25519 operations."""
|
||||
print("=== Ed25519 Benchmark ===\n")
|
||||
|
||||
# Key generation
|
||||
count = 1000
|
||||
start = time.time()
|
||||
for _ in range(count):
|
||||
Ed25519PrivateKey.generate()
|
||||
elapsed = time.time() - start
|
||||
print(f"Key generation: {count / elapsed:.0f} keys/s ({elapsed / count * 1e6:.1f} us/key)")
|
||||
|
||||
# Signing
|
||||
key = Ed25519PrivateKey.generate()
|
||||
message = b"Benchmark message for Ed25519 signing performance test." * 10
|
||||
count = 5000
|
||||
start = time.time()
|
||||
for _ in range(count):
|
||||
key.sign(message)
|
||||
elapsed = time.time() - start
|
||||
print(f"Signing: {count / elapsed:.0f} sigs/s ({elapsed / count * 1e6:.1f} us/sig)")
|
||||
|
||||
# Verification
|
||||
public_key = key.public_key()
|
||||
signature = key.sign(message)
|
||||
count = 2000
|
||||
start = time.time()
|
||||
for _ in range(count):
|
||||
public_key.verify(signature, message)
|
||||
elapsed = time.time() - start
|
||||
print(f"Verification: {count / elapsed:.0f} verifs/s ({elapsed / count * 1e6:.1f} us/verify)")
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Ed25519 Digital Signature Tool")
|
||||
subparsers = parser.add_subparsers(dest="command")
|
||||
|
||||
gen = subparsers.add_parser("generate", help="Generate Ed25519 key pair")
|
||||
gen.add_argument("--output", "-o", default="./keys", help="Output directory")
|
||||
gen.add_argument("--passphrase", "-p", help="Passphrase for private key")
|
||||
|
||||
sig = subparsers.add_parser("sign", help="Sign a file")
|
||||
sig.add_argument("--key", required=True, help="Private key path")
|
||||
sig.add_argument("--input", "-i", required=True, help="File to sign")
|
||||
sig.add_argument("--passphrase", "-p", help="Key passphrase")
|
||||
|
||||
ver = subparsers.add_parser("verify", help="Verify signature")
|
||||
ver.add_argument("--key", required=True, help="Public key path")
|
||||
ver.add_argument("--input", "-i", required=True, help="File to verify")
|
||||
ver.add_argument("--signature", "-s", required=True, help="Signature file")
|
||||
|
||||
cs = subparsers.add_parser("code-sign", help="Code sign an artifact")
|
||||
cs.add_argument("--key", required=True, help="Private key path")
|
||||
cs.add_argument("--artifact", required=True, help="Artifact to sign")
|
||||
cs.add_argument("--passphrase", "-p", help="Key passphrase")
|
||||
|
||||
csv = subparsers.add_parser("code-verify", help="Verify code signature")
|
||||
csv.add_argument("--manifest", required=True, help="Manifest file path")
|
||||
csv.add_argument("--artifact", required=True, help="Artifact file path")
|
||||
|
||||
subparsers.add_parser("benchmark", help="Benchmark Ed25519 performance")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.command == "generate":
|
||||
result = generate_ed25519_keypair(args.output, args.passphrase)
|
||||
print(json.dumps(result, indent=2))
|
||||
elif args.command == "sign":
|
||||
result = sign_file(args.key, args.input, args.passphrase)
|
||||
print(json.dumps(result, indent=2))
|
||||
elif args.command == "verify":
|
||||
result = verify_file(args.key, args.input, args.signature)
|
||||
print(json.dumps(result, indent=2))
|
||||
elif args.command == "code-sign":
|
||||
result = code_sign(args.key, args.artifact, args.passphrase)
|
||||
print(json.dumps(result, indent=2))
|
||||
elif args.command == "code-verify":
|
||||
result = verify_code_signature(args.manifest, args.artifact)
|
||||
print(json.dumps(result, indent=2))
|
||||
elif args.command == "benchmark":
|
||||
benchmark()
|
||||
else:
|
||||
parser.print_help()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user