-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4ca9642
commit cd2c1ad
Showing
1 changed file
with
20 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -55,10 +55,23 @@ def decrypt_cryptojs_aes_stores(data): | |
_cr = b"".join(int.to_bytes(i, length=4, byteorder="big", signed=True) for i in json.loads(_cr)["words"]) | ||
password = hashlib.pbkdf2_hmac("sha1", _cs.encode("utf8"), _cr, 1, dklen=32).hex() | ||
else: | ||
try: | ||
password_key = next(key for key in data.keys() if key not in ["context", "plugins"]) | ||
except: | ||
# Currently assume one extra key in dict, which is password. Print error if | ||
# more extra keys detected. | ||
new_keys = [k for k in data.keys() if k not in ["context", "plugins"]] | ||
l = len(new_keys) | ||
if l == 0: | ||
return None | ||
elif l == 1 and isinstance(data[new_keys[0]], str): | ||
password_key = new_keys[0] | ||
else: | ||
msg = "Yahoo has again changed data format, yfinance now unsure which key(s) is for decryption:" | ||
k = new_keys[0] | ||
k_str = k if len(k) < 32 else k[:32-3]+"..." | ||
msg += f" '{k_str}'->{type(data[k])}" | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
ValueRaider
Author
Collaborator
|
||
for i in range(1, len(new_keys)): | ||
msg += f" , '{k_str}'->{type(data[k])}" | ||
raise Exception(msg) | ||
password_key = new_keys[0] | ||
password = data[password_key] | ||
|
||
encrypted_stores = b64decode(encrypted_stores) | ||
|
@@ -105,7 +118,10 @@ def EVPKDF(password, salt, keySize=32, ivSize=16, iterations=1, hashAlgorithm="m | |
key, iv = key_iv[:keySize], key_iv[keySize:final_length] | ||
return key, iv | ||
|
||
key, iv = EVPKDF(password, salt, keySize=32, ivSize=16, iterations=1, hashAlgorithm="md5") | ||
try: | ||
key, iv = EVPKDF(password, salt, keySize=32, ivSize=16, iterations=1, hashAlgorithm="md5") | ||
except: | ||
raise Exception("yfinance failed to decrypt Yahoo data response") | ||
|
||
if usePycryptodome: | ||
cipher = AES.new(key, AES.MODE_CBC, iv=iv) | ||
|
That's not quite how their "protection" works. They basically load https://s.yimg.com/uc/finance/dd-site/js/main.__hash__.modern.js which does decryption.
Here is the diff:
Have no idea what they come up with next. It's not quite dynamic (yet). I see 2 ways of how to approach current situation:
At the moment, I see that they use the both methods (rollout shards maybe).
Maybe I make a patch on the weekend if someone else does not implement this by that.
P.S. Yahoo guys, if you read this, please stop wasting your time on this, this is simple stupid - it's a JS, source is available, it can be reverse engineered anyways. Yes, you break stuff for ppl for a few days, but you put a lot of effort into this. It's better to return the API you had, I bet there are many ppl who would like to keep paying a small fee instead of dancing with tambourine.