aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Crute <mike@crute.us>2019-04-02 02:50:17 +0000
committerMike Crute <mike@crute.us>2019-04-02 03:24:37 +0000
commit82988c77fbbc893e5659e3085bbc32f0580c74d1 (patch)
tree4d01c314b546128e8437ebf8853707d302dc97e7
parenta8a144bc7faa148eb4295fcbab0d05f08371ea87 (diff)
downloadpydora-82988c77fbbc893e5659e3085bbc32f0580c74d1.tar.bz2
pydora-82988c77fbbc893e5659e3085bbc32f0580c74d1.tar.xz
pydora-82988c77fbbc893e5659e3085bbc32f0580c74d1.zip
Drop C blowfish cryptor
-rw-r--r--pandora/transport.py46
-rwxr-xr-xsetup.py39
-rw-r--r--tests/test_pandora/test_transport.py31
3 files changed, 16 insertions, 100 deletions
diff --git a/pandora/transport.py b/pandora/transport.py
index 0174eac..6f1a174 100644
--- a/pandora/transport.py
+++ b/pandora/transport.py
@@ -13,16 +13,12 @@ import random
13import time 13import time
14import json 14import json
15import base64 15import base64
16import blowfish
16import requests 17import requests
17from requests.adapters import HTTPAdapter 18from requests.adapters import HTTPAdapter
18 19
19from .errors import PandoraException 20from .errors import PandoraException
20 21
21try:
22 import blowfish
23except ImportError:
24 blowfish = None
25
26 22
27DEFAULT_API_HOST = "tuner.pandora.com/services/json/" 23DEFAULT_API_HOST = "tuner.pandora.com/services/json/"
28 24
@@ -272,40 +268,6 @@ class BlowfishCryptor(object):
272 return data[:-pad_size] 268 return data[:-pad_size]
273 269
274 270
275class CryptographyBlowfish(BlowfishCryptor):
276 """Cryptography Blowfish Cryptor
277
278 Uses the python cryptography library which wraps OpenSSL. Compatible with
279 both Python 2 and 3 but requires a native dependency.
280 """
281
282 def __init__(self, key):
283 from cryptography.hazmat.backends import default_backend
284 from cryptography.hazmat.primitives.ciphers import Cipher
285 from cryptography.hazmat.primitives.ciphers.modes import ECB
286 from cryptography.hazmat.primitives.ciphers.algorithms import Blowfish
287
288 self.cipher = Cipher(
289 Blowfish(key.encode("ascii")), ECB(), backend=default_backend())
290
291 def _make_bytearray(self, data):
292 return bytearray(len(data) + (self.block_size - 1))
293
294 def decrypt(self, data, strip_padding=True):
295 buf = self._make_bytearray(data)
296 dec = self.cipher.decryptor()
297 len_dec = dec.update_into(data, buf)
298 data = bytes(buf[:len_dec]) + dec.finalize()
299 return self._strip_padding(data) if strip_padding else data
300
301 def encrypt(self, data):
302 data = self._add_padding(data)
303 enc = self.cipher.encryptor()
304 buf = self._make_bytearray(data)
305 len_enc = enc.update_into(data, buf)
306 return bytes(buf[:len_enc]) + enc.finalize()
307
308
309class PurePythonBlowfish(BlowfishCryptor): 271class PurePythonBlowfish(BlowfishCryptor):
310 """Pure Python 3 Blowfish Cryptor 272 """Pure Python 3 Blowfish Cryptor
311 273
@@ -323,10 +285,6 @@ class PurePythonBlowfish(BlowfishCryptor):
323 return b"".join(self.cipher.encrypt_ecb(self._add_padding(data))) 285 return b"".join(self.cipher.encrypt_ecb(self._add_padding(data)))
324 286
325 287
326# Python 3 users can use pure-python mode, if possible prefer that as default
327_default_crypto = PurePythonBlowfish if blowfish else CryptographyBlowfish
328
329
330class Encryptor(object): 288class Encryptor(object):
331 """Pandora Blowfish Encryptor 289 """Pandora Blowfish Encryptor
332 290
@@ -334,7 +292,7 @@ class Encryptor(object):
334 API request and response. It handles the formats that the API expects. 292 API request and response. It handles the formats that the API expects.
335 """ 293 """
336 294
337 def __init__(self, in_key, out_key, crypto_class=_default_crypto): 295 def __init__(self, in_key, out_key, crypto_class=PurePythonBlowfish):
338 self.bf_out = crypto_class(out_key) 296 self.bf_out = crypto_class(out_key)
339 self.bf_in = crypto_class(in_key) 297 self.bf_in = crypto_class(in_key)
340 298
diff --git a/setup.py b/setup.py
index 62aec94..0e4c5fb 100755
--- a/setup.py
+++ b/setup.py
@@ -37,29 +37,6 @@ class TestsWithCoverage(test, object):
37 cov.html_report() 37 cov.html_report()
38 38
39 39
40requires = {
41 "setup_requires": [
42 "wheel",
43 "flake8>=3.3",
44 ],
45 "tests_require": [
46 "mock>=2,<3",
47 "coverage>=4.1,<5",
48 "cryptography>=2,<3",
49 ],
50 "install_requires": [
51 "requests>=2,<3",
52 ],
53}
54
55
56if sys.version_info.major == 3 and sys.version_info.minor >= 4:
57 requires["install_requires"].append("blowfish>=0.6.1,<1.0")
58else:
59 requires["install_requires"].append("cryptography>=2,<3")
60 requires["install_requires"].append("enum34")
61
62
63setup( 40setup(
64 name="pydora", 41 name="pydora",
65 version="2.0.0", 42 version="2.0.0",
@@ -79,6 +56,19 @@ setup(
79 "pydora-configure = pydora.configure:main", 56 "pydora-configure = pydora.configure:main",
80 ], 57 ],
81 }, 58 },
59 setup_requires=[
60 "wheel",
61 "flake8>=3.3",
62 ],
63 tests_require=[
64 "mock>=2,<3",
65 "coverage>=4.1,<5",
66 "cryptography>=2,<3",
67 ],
68 install_requires=[
69 "requests>=2,<3",
70 "blowfish>=0.6.1,<1.0",
71 ],
82 classifiers=[ 72 classifiers=[
83 "Development Status :: 5 - Production/Stable", 73 "Development Status :: 5 - Production/Stable",
84 "Environment :: Console", 74 "Environment :: Console",
@@ -91,6 +81,5 @@ setup(
91 "Programming Language :: Python :: 3.7", 81 "Programming Language :: Python :: 3.7",
92 "Topic :: Internet :: WWW/HTTP", 82 "Topic :: Internet :: WWW/HTTP",
93 "Topic :: Multimedia :: Sound/Audio :: Players", 83 "Topic :: Multimedia :: Sound/Audio :: Players",
94 ], 84 ]
95 **requires
96) 85)
diff --git a/tests/test_pandora/test_transport.py b/tests/test_pandora/test_transport.py
index 862a12f..96dd40e 100644
--- a/tests/test_pandora/test_transport.py
+++ b/tests/test_pandora/test_transport.py
@@ -281,26 +281,6 @@ class TestPurePythonBlowfishCryptor(TestCase, CommonCryptorTestCases):
281 self.cryptor.cipher = self.cipher 281 self.cryptor.cipher = self.cipher
282 282
283 283
284class TestCryptographyBlowfish(TestCase, CommonCryptorTestCases):
285
286 class FakeCipher(object):
287
288 def update_into(self, val, buf):
289 for i, v in enumerate(val):
290 buf[i] = v
291 return len(val)
292
293 def finalize(self):
294 return b""
295
296 def setUp(self):
297 self.cipher = Mock()
298 self.cipher.encryptor.return_value = self.FakeCipher()
299 self.cipher.decryptor.return_value = self.FakeCipher()
300 self.cryptor = t.CryptographyBlowfish("keys")
301 self.cryptor.cipher = self.cipher
302
303
304class TestEncryptor(TestCase): 284class TestEncryptor(TestCase):
305 285
306 ENCODED_JSON = "7b22666f6f223a22626172227d" 286 ENCODED_JSON = "7b22666f6f223a22626172227d"
@@ -335,14 +315,3 @@ class TestEncryptor(TestCase):
335 self.assertEqual( 315 self.assertEqual(
336 self.EXPECTED_TIME, 316 self.EXPECTED_TIME,
337 self.cryptor.decrypt_sync_time(self.ENCODED_TIME)) 317 self.cryptor.decrypt_sync_time(self.ENCODED_TIME))
338
339
340class TestDefaultStrategy(TestCase):
341
342 def test_blowfish_not_available(self):
343 del sys.modules["pandora.transport"]
344 sys.modules["blowfish"] = None
345
346 import pandora.transport as t
347 self.assertIsNone(t.blowfish)
348 self.assertIs(t._default_crypto, t.CryptographyBlowfish)