Stosować Signed Cookies
Gdy używam CloudFront z wielu prywatnych adresów URL, wolę używać Signed Cookies gdy wszystkie restrictions są spełnione. Nie przyspiesza to generowania podpisanych plików cookie, ale zmniejsza liczbę żądań podpisywania, które mają wynosić jeden na użytkownika, dopóki nie wygasną.
Tuning RSA Generation Podpis
mogę sobie wyobrazić, może masz wymagania, które czynią podpisanych ciasteczek jako niepoprawną opcję. W tym przypadku próbowałem przyspieszyć proces podpisywania, porównując moduł RSA używany z boto i cryptography. Dwie dodatkowe opcje to: m2crypto i pycrypto, ale do tego przykładu użyję kryptografii.
Aby przetestować wydajność podpisywania adresów URL za pomocą różnych modułów, zmniejszyłem metodę _sign_string w celu usunięcia logiki z wyjątkiem podpisania ciągu znaków, a następnie utworzenia nowej klasy Distribution
. Następnie wziąłem klucz prywatny i przykładowy adres URL z boto tests, aby przetestować.
Wyniki pokazują, że kryptografia jest szybsza, ale nadal wymaga blisko 1 ms na każde żądanie podpisania. Wyniki te są przekrzywione na wyższym poziomie przez użycie przez iPythona zmiennych o zakresie w czasie.
timeit -n10000 rsa_distribution.create_signed_url(url, message, expire_time)
10000 loops, best of 3: 6.01 ms per loop
timeit -n10000 cryptography_distribution.create_signed_url(url, message, expire_time)
10000 loops, best of 3: 644 µs per loop
Pełen skrypt:
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
import rsa
from boto.cloudfront.distribution import Distribution
from textwrap import dedent
# The private key provided in the Boto tests
pk_key = dedent("""
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDA7ki9gI/lRygIoOjV1yymgx6FYFlzJ+z1ATMaLo57nL57AavW
hb68HYY8EA0GJU9xQdMVaHBogF3eiCWYXSUZCWM/+M5+ZcdQraRRScucmn6g4EvY
2K4W2pxbqH8vmUikPxir41EeBPLjMOzKvbzzQy9e/zzIQVREKSp/7y1mywIDAQAB
AoGABc7mp7XYHynuPZxChjWNJZIq+A73gm0ASDv6At7F8Vi9r0xUlQe/v0AQS3yc
N8QlyR4XMbzMLYk3yjxFDXo4ZKQtOGzLGteCU2srANiLv26/imXA8FVidZftTAtL
viWQZBVPTeYIA69ATUYPEq0a5u5wjGyUOij9OWyuy01mbPkCQQDluYoNpPOekQ0Z
WrPgJ5rxc8f6zG37ZVoDBiexqtVShIF5W3xYuWhW5kYb0hliYfkq15cS7t9m95h3
1QJf/xI/AkEA1v9l/WN1a1N3rOK4VGoCokx7kR2SyTMSbZgF9IWJNOugR/WZw7HT
njipO3c9dy1Ms9pUKwUF46d7049ck8HwdQJARgrSKuLWXMyBH+/l1Dx/I4tXuAJI
rlPyo+VmiOc7b5NzHptkSHEPfR9s1OK0VqjknclqCJ3Ig86OMEtEFBzjZQJBAKYz
470hcPkaGk7tKYAgP48FvxRsnzeooptURW5E+M+PQ2W9iDPPOX9739+Xi02hGEWF
B0IGbQoTRFdE4VVcPK0CQQCeS84lODlC0Y2BZv2JxW3Osv/WkUQ4dslfAQl1T303
7uwwr7XTroMv8dIFQIPreoPhRKmd/SbJzbiKfS/4QDhU
-----END RSA PRIVATE KEY-----""")
# Initializing keys in a global context
cryptography_private_key = serialization.load_pem_private_key(
pk_key,
password=None,
backend=default_backend())
# Instantiate a signer object using PKCS 1v 15, this is not recommended but required for Amazon
def sign_with_cryptography(message):
signer = cryptography_private_key.signer(
padding.PKCS1v15(),
hashes.SHA1())
signer.update(message)
return signer.finalize()
# Initializing the key in a global context
rsa_private_key = rsa.PrivateKey.load_pkcs1(pk_key)
def sign_with_rsa(message):
signature = rsa.sign(str(message), rsa_private_key, 'SHA-1')
return signature
# All this information comes from the Boto tests.
url = "http://d604721fxaaqy9.cloudfront.net/horizon.jpg?large=yes&license=yes"
expected_url = "http://d604721fxaaqy9.cloudfront.net/horizon.jpg?large=yes&license=yes&Expires=1258237200&Signature=Nql641NHEUkUaXQHZINK1FZ~SYeUSoBJMxjdgqrzIdzV2gyEXPDNv0pYdWJkflDKJ3xIu7lbwRpSkG98NBlgPi4ZJpRRnVX4kXAJK6tdNx6FucDB7OVqzcxkxHsGFd8VCG1BkC-Afh9~lOCMIYHIaiOB6~5jt9w2EOwi6sIIqrg_&Key-Pair-Id=PK123456789754"
message = "PK123456789754"
expire_time = 1258237200
class CryptographyDistribution(Distribution):
def _sign_string(
self,
message,
private_key_file=None,
private_key_string=None):
return sign_with_cryptography(message)
class RSADistribution(Distribution):
def _sign_string(
self,
message,
private_key_file=None,
private_key_string=None):
return sign_with_rsa(message)
cryptography_distribution = CryptographyDistribution()
rsa_distribution = RSADistribution()
cryptography_url = cryptography_distribution.create_signed_url(
url,
message,
expire_time)
rsa_url = rsa_distribution.create_signed_url(
url,
message,
expire_time)
assert cryptography_url == rsa_url == expected_url, "URLs do not match"
Wnioski
Chociaż moduł kryptograficzny działa lepiej w tym teście, polecam próbuje znaleźć sposób, aby wykorzystać podpisane ciasteczka, ale mam nadzieję, że ten informacje są przydatne.
Myśląc o tym dzisiaj, osobiście. Czy mierzysz dosłownie tylko generowanie podpisu, czy zadania takie jak ładowanie klucza, przygotowywanie zasad itp.? – abathur
@abathur, Zmierzyłem zarówno czas generowania podpisu (RSA) (klucz jest już buforowany po stronie serwera, a polityka jest już skonfigurowana), jak i czas dla obsługi całego żądania (w tym niektóre niestandardowe logiki). Tak więc na moim komputerze było to ~ 25ms do generowania sygnatur i ~ 30ms do przetworzenia całego żądania. – MLister
@MLister: czy możesz podać fragment kodu pokazujący linie, których używasz do obliczania podpisu RSA przykładowego adresu URL? – Peque