Browse files

Merge branch 'seandst-develop' into develop

This replaces M2Crypto with rsa to sign urls
in CloudFront, fixes #1214.

* seandst-develop:
  Removed overeager seek
  Unconditional 'else' was causing breakage
  Changed Distribution._sign_string over to use rsa
  Cleaning up some trailing whitespace
  • Loading branch information...
2 parents 71780dd + 5ee626a commit e0d267c593e063795ea0fb76741e2aeb1875808c @jamesls jamesls committed Jan 8, 2013
Showing with 24 additions and 25 deletions.
  1. +23 −25 boto/cloudfront/
  2. +1 −0 requirements.txt
@@ -49,23 +49,23 @@ def __init__(self, connection=None, origin=None, enabled=False,
:param enabled: Whether the distribution is enabled to accept
end user requests for content.
:type enabled: bool
:param caller_reference: A unique number that ensures the
request can't be replayed. If no
caller_reference is provided, boto
will generate a type 4 UUID for use
as the caller reference.
:type enabled: str
:param cnames: A CNAME alias you want to associate with this
distribution. You can have up to 10 CNAME aliases
per distribution.
:type enabled: array of str
:param comment: Any comments you want to include about the
:type comment: str
:param trusted_signers: Specifies any AWS accounts you want to
permit to create signed URLs for private
content. If you want the distribution to
@@ -74,7 +74,7 @@ def __init__(self, connection=None, origin=None, enabled=False,
distribution to use basic URLs, leave
this None.
:type trusted_signers: :class`boto.cloudfront.signers.TrustedSigners`
:param default_root_object: Designates a default root object.
Only include a DefaultRootObject value
if you are going to assign a default
@@ -86,7 +86,7 @@ def __init__(self, connection=None, origin=None, enabled=False,
this should contain a LoggingInfo object; otherwise
it should contain None.
:type logging: :class`boto.cloudfront.logging.LoggingInfo`
self.connection = connection
self.origin = origin
@@ -278,7 +278,7 @@ class StreamingDistributionSummary(DistributionSummary):
def get_distribution(self):
return self.connection.get_streaming_distribution_info(
class Distribution:
def __init__(self, connection=None, config=None, domain_name='',
@@ -400,11 +400,11 @@ def _get_bucket(self):
return self._bucket
raise NotImplementedError('Unable to get_objects on CustomOrigin')
def get_objects(self):
Return a list of all content objects in this distribution.
:rtype: list of :class:`boto.cloudfront.object.Object`
:return: The content objects
@@ -640,32 +640,30 @@ def _custom_policy(resource, expires=None, valid_after=None, ip_address=None):
def _sign_string(message, private_key_file=None, private_key_string=None):
- Signs a string for use with Amazon CloudFront. Requires the M2Crypto
- library be installed.
+ Signs a string for use with Amazon CloudFront.
+ Requires the rsa library be installed.
- from M2Crypto import EVP
+ import rsa
except ImportError:
- raise NotImplementedError("Boto depends on the python M2Crypto "
+ raise NotImplementedError("Boto depends on the python rsa "
"library to generate signed URLs for "
# Make sure only one of private_key_file and private_key_string is set
if private_key_file and private_key_string:
raise ValueError("Only specify the private_key_file or the private_key_string not both")
if not private_key_file and not private_key_string:
raise ValueError("You must specify one of private_key_file or private_key_string")
- # if private_key_file is a file object read the key string from there
+ # If private_key_file is a file, read its contents. Otherwise, open it and then read it
if isinstance(private_key_file, file):
private_key_string =
- # Now load key and calculate signature
- if private_key_string:
- key = EVP.load_key_string(private_key_string)
- else:
- key = EVP.load_key(private_key_file)
- key.reset_context(md='sha1')
- key.sign_init()
- key.sign_update(str(message))
- signature = key.sign_final()
+ elif private_key_file:
+ with open(private_key_file, 'r') as file_handle:
+ private_key_string =
+ # Sign it!
+ private_key = rsa.PrivateKey.load_pkcs1(private_key_string)
+ signature = rsa.sign(str(message), private_key, 'SHA-1')
return signature
@@ -743,5 +741,5 @@ def update(self, enabled=None, cnames=None, comment=None):
def delete(self):
self.connection.delete_streaming_distribution(, self.etag)
@@ -2,6 +2,7 @@ mock==1.0.1

0 comments on commit e0d267c

Please sign in to comment.