diff --git a/src/pyfed/utils/exceptions.py b/src/pyfed/utils/exceptions.py
new file mode 100644
index 0000000000000000000000000000000000000000..f9cbc9caf1978486ad446950910175384a3bec0f
--- /dev/null
+++ b/src/pyfed/utils/exceptions.py
@@ -0,0 +1,42 @@
+class ActivityPubException(Exception):
+    """Base exception for ActivityPub-related errors."""
+
+class ValidationError(ActivityPubException):
+    """Raised when validation fails."""
+
+class DeserializationError(ActivityPubException):
+    """Raised when deserialization fails."""
+
+class RemoteObjectFetchError(ActivityPubException):
+    """Raised when fetching a remote object fails."""
+
+class InvalidURLError(ValidationError):
+    """Raised when an invalid URL is provided."""
+
+class InvalidDateTimeError(ValidationError):
+    """Raised when an invalid date/time is provided."""
+
+class SignatureVerificationError(ActivityPubException):
+    """Raised when signature verification fails."""
+    pass
+
+class SignatureError(ActivityPubException):
+    """Raised when signature verification fails."""
+    pass
+
+class AuthenticationError(ActivityPubException):
+    """Raised when signature verification fails."""
+    pass
+
+class RateLimitExceeded(ActivityPubException):
+    """Raised when signature verification fails."""
+    pass
+
+class WebFingerError(ActivityPubException):
+    """Raised when signature verification fails."""
+    pass
+
+class SecurityError(ActivityPubException):
+    """Raised when signature verification fails."""
+    pass
+
diff --git a/src/pyfed/utils/logging.py b/src/pyfed/utils/logging.py
new file mode 100644
index 0000000000000000000000000000000000000000..31e4021a45cf0e1d6c8762c589a4b0f1d1db7f06
--- /dev/null
+++ b/src/pyfed/utils/logging.py
@@ -0,0 +1,36 @@
+import logging
+import sys
+from typing import Optional
+
+def configure_logging(level: Optional[str] = None):
+    """
+    Configure the logging system for the ActivityPub library.
+
+    Args:
+        level (Optional[str]): The logging level. If None, defaults to INFO.
+    """
+    if level is None:
+        level = logging.INFO
+    else:
+        level = getattr(logging, level.upper())
+
+    logging.basicConfig(
+        level=level,
+        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
+        handlers=[
+            logging.StreamHandler(sys.stdout),
+            logging.FileHandler('activitypub_library.log')
+        ]
+    )
+
+def get_logger(name: str) -> logging.Logger:
+    """
+    Get a logger with the specified name.
+
+    Args:
+        name (str): The name of the logger, typically __name__ of the module.
+
+    Returns:
+        logging.Logger: A configured logger instance.
+    """
+    return logging.getLogger(name)