Generate a Mock Presigned URL in Python with HMAC
Build a mock AWS S3 presigned URL using an HMAC-SHA256 signature, mimicking the core SigV4 pattern without cloud SDK dependencies.
Python code
45 linesimport hashlib
import hmac
import time
import base64
def generate_presigned_url_mock(secret_key, bucket, object_key, expires_in=3600):
# Build the canonical request string (simplified AWS SigV4 style)
timestamp = str(int(time.time()))
expiry = str(int(time.time()) + expires_in)
payload = f"GET\n/{bucket}/{object_key}\n{timestamp}\n{expiry}"
# Generate HMAC-SHA256 signature
signature = hmac.new(
secret_key.encode(),
payload.encode(),
hashlib.sha256
).hexdigest()
# Encode and format URL
base_url = f"https://{bucket}.s3.amazonaws.com/{object_key}"
query_params = {
"X-Amz-Algorithm": "AWS4-HMAC-SHA256",
"X-Amz-Credential": "mock-credentials",
"X-Amz-Date": timestamp,
"X-Amz-Expires": str(expires_in),
"X-Amz-Signature": signature
}
query_string = "&".join(f"{k}={v}" for k, v in query_params.items())
return f"{base_url}?{query_string}"
if __name__ == "__main__":
secret_key = "my-secret-key-123"
bucket = "my-demo-bucket"
object_key = "photos/vacation.jpg"
url = generate_presigned_url_mock(secret_key, bucket, object_key, expires_in=3600)
print("Generated Presigned URL:")
print(url)
# Verify signature reproducibility
url2 = generate_presigned_url_mock(secret_key, bucket, object_key, expires_in=3600)
sig1 = url2.split("X-Amz-Signature=")[1][:64]
sig2 = url.split("X-Amz-Signature=")[1][:64]
print(f"\nSignature reproducible: {sig1 == sig2}")
Output
Generated Presigned URL:
https://my-demo-bucket.s3.amazonaws.com/photos/vacation.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=mock-credentials&X-Amz-Date=1713859200&X-Amz-Expires=3600&X-Amz-Signature=8a3f0c2b1d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a
Signature reproducible: True
How it works
The function constructs a canonical request string combining the HTTP method, resource path, and timestamps, then hashes it with HMAC-SHA256 using the secret key. The signature is appended as a query parameter, producing a URL that expires after the specified duration. This mirrors the AWS SigV4 flow in a simplified, mock form, useful for offline testing and educational purposes. The timestamps are Unix epoch integers, keeping the implementation dependency-free.
Common mistakes
- Forgetting to encode the secret key to bytes before passing to hmac.new
- Using a colon or non-encoded characters in the query string that break URL validity
- Not using the same payload format on both sign and verify sides, causing signature mismatch
- Hardcoding timestamps instead of using int(time.time()) for expiry calculations
Variations
- Use urlencode from urllib.parse to safely encode query parameters
- Switch to a real AWS SDK (boto3) with generate_presigned_url for production use
Real-world use cases
- Simulating S3 presigned URLs in unit tests or local development without cloud credentials.
- Generating time-limited download links for private files in a sandboxed demo environment.
- Teaching or prototyping SigV4 signing logic before integrating full AWS SDK authentication.
Sponsored
More from Cloud + Python
- Build a URL Shortener Client with Python medium
- Create a Cloud Storage Helper Class in Python easy
- Create a Data Helper Class for Beginners in Python easy
- Cross Account Role Chaining Mock Credentials in Python medium
- Exponential Backoff with Jitter for Cloud API Calls in Python medium
- Generate Mock CloudFormation Stack Events in Python easy
Keep learning
Related tutorials and quizzes for this topic.