DEV Community

CloudFront ECDSA Signed URLs: 91% Faster Generation, 55% Shorter URLs

👋 Introduction

On September 9, 2025, Amazon CloudFront added support for ECDSA (Elliptic Curve Digital Signature Algorithm) keys in signed URLs. Previously limited to RSA-2048, CloudFront now supports ECDSA P-256 (prime256v1), enabling significantly faster signature generation and shorter URLs.

This article demonstrates implementing ECDSA signed URLs and compares performance with traditional RSA keys.

https://aws.amazon.com/about-aws/whats-new/2025/09/amazon-cloudfront-ecdsa-signed-urls/

📌 What's New

Key Changes

  • CloudFront signed URLs now support ECDSA (P-256) alongside RSA
  • Faster signature generation with lower CPU usage
  • Smaller signature size resulting in shorter URLs
  • Same security level as RSA with better performance

Expected Benefits

  • Performance: Faster signature generation for high-volume scenarios
  • Efficiency: Reduced CPU usage, ideal for resource-constrained environments
  • URL Length: Shorter URLs for SMS, QR codes, and other length-sensitive use cases

Implementation Guide

1. Generate Key Pairs

# Generate ECDSA P-256 private key
openssl ecparam -name prime256v1 -genkey -noout -out ecdsa-private.pem

# Generate public key
openssl ec -in ecdsa-private.pem -pubout -out ecdsa-public.pem

# For comparison, generate RSA keys
openssl genrsa -out rsa-private.pem 2048
openssl rsa -pubout -in rsa-private.pem -out rsa-public.pem
Enter fullscreen mode Exit fullscreen mode

2. Register Public Keys with CloudFront

# Register ECDSA public key
ECDSA_KEY_CONTENT=$(cat ecdsa-public.pem)
ECDSA_KEY_RESPONSE=$(aws cloudfront create-public-key \
    --public-key-config \
    Name="ecdsa-signing-key",CallerReference="$(date +%s)",EncodedKey="$ECDSA_KEY_CONTENT",Comment="ECDSA P-256 key for signed URLs")

ECDSA_KEY_ID=$(echo $ECDSA_KEY_RESPONSE | jq -r '.PublicKey.Id')
echo "ECDSA Key ID: $ECDSA_KEY_ID"
Enter fullscreen mode Exit fullscreen mode

3. Create Key Groups

# Create ECDSA key group
ECDSA_KEY_GROUP_RESPONSE=$(aws cloudfront create-key-group \
    --key-group-config \
    Name="ecdsa-key-group",Items="$ECDSA_KEY_ID",Comment="ECDSA key group")

ECDSA_KEY_GROUP_ID=$(echo $ECDSA_KEY_GROUP_RESPONSE | jq -r '.KeyGroup.Id')
Enter fullscreen mode Exit fullscreen mode

4. Configure CloudFront Distribution

⚠️ Important: Update your CloudFront distribution behavior settings.

  1. Go to your distribution's "Behaviors" tab
  2. Edit the relevant behavior
  3. Set "Restrict viewer access" to "Yes"
  4. Set "Trusted authorization type" to "Trusted key groups"
  5. Select your created key group

5. Generate Signed URLs

AWS CLI Limitation

⚠️ Important: As of September 9, 2025, the AWS CLI's cloudfront sign command doesn't support ECDSA keys and throws an error saying it's not an RSA key.

# aws --version
# aws-cli/2.29.0 
# This will fail with ECDSA keys
aws cloudfront sign --url https://example.com/file.jpg \
    --key-pair-id $ECDSA_KEY_ID \
    --private-key file://ecdsa-private.pem \
    --date-less-than "2025-09-10T12:09:03Z"
# Error: RSA private key not found in PEM.
Enter fullscreen mode Exit fullscreen mode

Python Implementation

Here's a working Python implementation for ECDSA signed URLs.

# ecdsa_signer.py
import sys
import time
from botocore.signers import CloudFrontSigner
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.serialization import load_pem_private_key
from cryptography.hazmat.backends import default_backend
import os
from datetime import datetime

def ecdsa_signer(message):
    with open("ecdsa-private.pem", "rb") as key_file:
        private_key = load_pem_private_key(
            key_file.read(), password=None, backend=default_backend()
        )
    return private_key.sign(message, ec.ECDSA(hashes.SHA1()))

def generate_signed_url(url, key_pair_id, date_less_than):
    start_time = time.time()

    cf_signer = CloudFrontSigner(key_pair_id, ecdsa_signer)
    signed_url = cf_signer.generate_presigned_url(
        url,
        date_less_than=datetime.fromisoformat(date_less_than.replace("Z", "+00:00")),
    )

    processing_time_ms = (time.time() - start_time) * 1000
    print(f"ECDSA processing time: {processing_time_ms:.2f}ms", file=sys.stderr)

    return signed_url

if __name__ == "__main__":
    url = sys.argv[1] if len(sys.argv) > 1 else "https://example.com/file.jpg"
    expiry_time = sys.argv[2] if len(sys.argv) > 2 else "2025-09-10T12:09:03Z"
    key_pair_id = os.environ.get("ECDSA_KEY_ID")

    signed_url = generate_signed_url(url, key_pair_id, expiry_time)
    print(signed_url)
Enter fullscreen mode Exit fullscreen mode

Performance Comparison

I ran performance tests comparing RSA and ECDSA signature generation.

Results Summary

Test Runs RSA Average ECDSA Average Improvement RSA StdDev ECDSA StdDev
1 36.47ms 3.04ms 91.7% 0.00ms 0.00ms
10 35.93ms 3.00ms 91.6% 2.54ms 0.31ms
20 33.54ms 2.60ms 92.2% 0.98ms 0.21ms
100 34.39ms 2.91ms 91.5% 1.33ms 0.58ms

Key Findings

  • Performance: ECDSA is ~12x faster than RSA (91% improvement)
  • URL Length: 55.1% shorter URLs (RSA: 448 chars → ECDSA: 201 chars)
  • Consistency: Lower standard deviation shows more stable performance

Real URL Examples

RSA Signed URL (448 characters):

https://example.com/private-files/uploadtest.jpg?Expires=1757511063&Signature=TNGmM2jrc5GRTalKgYhdZla1uaR~gOiX4HevKDMBbe5JkecwxGe0VoCqXB5KnCPgetRbbBE6JCtOdCYiTwGYxKpByOBJTMaS5Z3H9rqhln~wqQ0KZ-q5-lqvEPsxXlbBXbzJ0MDwNgzcCcu3GavsYGiceFr0veGw5RuYNLSs49HdFUKtdk~7wpI~bjdHzLDSaxoTKtIz0HDgii~VTPP769X~aOmG7~W0hm23nBP4WcTDe6Z8YvDRr61TqjixkNYrh4FiuUFFVuA2Tn0FUuaxcU5qVhtcl0ng8QqoyHUwWFju65h6g0TUM2iueJudQtV-CcoYf-UHlVOGQ39pnG9HxQ__&Key-Pair-Id=ZZZZZZZZZZZZZ
Enter fullscreen mode Exit fullscreen mode

ECDSA Signed URL (201 characters):

https://example.com/private-files/uploadtest.jpg?Expires=1757511063&Signature=MEQCIBO~LD6qEaVjiwGFFF233dOB~XJvi7SPhubaN0FjFsigAiBlLZAYz9sCp6aY93bE9z0SuZDhEH3Pw8uL-9rPODVbQw__&Key-Pair-Id=WWWWWWWWWWWWWW
Enter fullscreen mode Exit fullscreen mode

When to Use ECDSA

ECDSA is particularly beneficial for:

  • High-volume URL generation: APIs generating many signed URLs
  • Mobile/IoT devices: Resource-constrained environments
  • URL length constraints: SMS, QR codes, social media
  • Real-time applications: Where response time is critical

Conclusion

CloudFront's ECDSA support delivers significant performance improvements and URL size reductions. For high-load systems or resource-constrained environments, ECDSA provides substantial benefits while maintaining the same security level as RSA.

The 91% performance improvement and 53% URL size reduction make ECDSA a compelling choice for modern applications requiring efficient signed URL generation.

Resources


Have you tried ECDSA signed URLs in your CloudFront setup? Share your experience in the comments!

Top comments (0)