Kekik 1.5.2__tar.gz → 1.5.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of Kekik might be problematic. Click here for more details.
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/Sifreleme/AESManager.py +16 -1
- kekik-1.5.4/Kekik/Sifreleme/CryptoJS.py +99 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/Sifreleme/HexCodec.py +2 -6
- kekik-1.5.4/Kekik/Sifreleme/NaysHash.py +66 -0
- kekik-1.5.4/Kekik/Sifreleme/StringCodec.py +40 -0
- kekik-1.5.4/Kekik/Sifreleme/__init__.py +8 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik.egg-info/PKG-INFO +1 -1
- {kekik-1.5.2 → kekik-1.5.4}/Kekik.egg-info/SOURCES.txt +2 -1
- {kekik-1.5.2 → kekik-1.5.4}/PKG-INFO +1 -1
- {kekik-1.5.2 → kekik-1.5.4}/setup.py +1 -1
- kekik-1.5.2/Kekik/Sifreleme/AtobRtt.py +0 -16
- kekik-1.5.2/Kekik/Sifreleme/CryptoJS.py +0 -87
- kekik-1.5.2/Kekik/Sifreleme/__init__.py +0 -7
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/BIST.py +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/Domain2IP.py +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/Nesne.py +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/Sifreleme/Packer.py +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/__init__.py +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/cli.py +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/csv2dict.py +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/dict2csv.py +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/dict2json.py +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/dosya2set.py +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/dosya_indir.py +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/hwid_kontrol.py +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/kisi_ver/__init__.py +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/kisi_ver/biyografiler.py +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/kisi_ver/isimler.py +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/kisi_ver/soyisimler.py +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/link_islemleri.py +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/list2html.py +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/liste_fetis.py +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/mail_gonder.py +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/okunabilir_byte.py +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/proxy_ver.py +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/qr_ver.py +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/ses_fetis.py +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/slugify.py +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/terminal_baslik.py +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/txt_fetis.py +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/unicode_tr.py +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik/zaman_donustur.py +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik.egg-info/dependency_links.txt +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik.egg-info/entry_points.txt +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik.egg-info/requires.txt +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/Kekik.egg-info/top_level.txt +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/LICENSE +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/MANIFEST.in +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/README.md +0 -0
- {kekik-1.5.2 → kekik-1.5.4}/setup.cfg +0 -0
|
@@ -63,4 +63,19 @@ class AESManager:
|
|
|
63
63
|
cipher = AES.new(key, AES.MODE_CBC, iv)
|
|
64
64
|
decrypted = unpad(cipher.decrypt(b64decode(data["ct"])), AES.block_size)
|
|
65
65
|
|
|
66
|
-
return decrypted.decode("utf-8")
|
|
66
|
+
return decrypted.decode("utf-8")
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
# veri = r'''
|
|
71
|
+
# $(document).ready(function() {
|
|
72
|
+
# bePlayer('S3JScTBsNzMyYlFSMHg4NG5vQXNjUT09', '{"ct":"SjkWeIotWbL6TmnwyhkeLy6wAWvEG1pz8R0g+IsLN6P1vo9WvXuiqqDal5g6FXW3Td+Q+1DIGQAt3sNxydOAr4p3uFxxpVPUwIMwLWzw+5m0ED0tno1KU0\/rCXRwq6ATvmrIqSr+qb95hY0wjm3gfjPsxDn4vJ1fcdiRwrfC38MjfKyJFN3\/n\/xLvNT4vgQJTYTEmNOzFZgEIhsSRFiW1\/8nQCaS\/8Xkw0ySUqLvzSMsVf2SSgXyESxyksn3+kz9KqEI+mQpJFUcLSBz8VKXly+tEcYGpTQChzceyudkZcEGvppKheBAarEQ6e3eR9d04gQcFpEaV+QmHODvI1Ql\/pJ1FSAh9F5ZDtF00XDSLZbIEt00PWRkgfc3kxuNQzcC1C6BULNdoGwHbvo5W6uUsMwxG+sn+EH7B7jWtyhx5VHKpIfkyrjC10+K\/hG29bkS3YNSTaDxJnTa3jj1usbwwMX0A7wApIlce4rEVgWpO5y1ZuiJ+tEE3kH1InUzT1jfY4Y0KrZ5X+p2nrQhJrDOxfDy\/GhaidNmmpfuzF6Iniko6sCGa0QRbhVB8ZbrC9qFB\/sk47ZOP1IHPY\/jCh4BTFMDCy1Qx1\/PbVLZzNLHju\/cLYRzS0vJp5aqkwg\/QNCo1q5HrxXL32lMLNOcWPRDqyZaMpiYP+LzJPVndLsqGlfKJWETuKonEqc4r4M0Eu\/bTji\/S7zQ7bvEPuT3PyIRWXDffuNSX6+nqWFD8LM\/iNyc1cC3bMi+p0TR3YZu1MlIvxjYPK0lYtDvd+vaYgCotFm0lLsqg5cuw3pGb8jnEfM1VzEqDcBvBTkRKrxIao\/WWdvGf1MCmTsr+nVH0sT8PTrh6XcoG7hV\/+y8XCsEj2LKWtDtfK+RxSztteXYUUUI9NVtCvjlW\/b8+h6u+B\/CNLtrwoDQzKhTVZ1rZbe\/TP+HR7SkMXYqyAX3qqiyi9s+TrcqkxdbAHzkjr0q2DshtUeipcL5HVrdxL28iXqtYMT\/ytsRCQHpnswNGqW+D47VAYtDl4VafSaNGUMPfu6nq4k0\/FrxtYkts4lE9YUkueQHip8eOFO8dxTp8O7+Civt88C45wEjBHqaiN+n6wm1+3xUy2hKX0PD4gvlPuUeoHDbm\/HLUlPYmGw5cCEAskuJRXdW+gnFB6XzVIKrF7OUtd2yLqSLhnWcSFkMJoPDuIezn1D60pMi8LlJKb1HXwbPRRcqh00\/bFNdmodGpwybcaeegvRaCJbDqd6fmQUxG1ir9o5O8st2\/oJ9\/HivYvxi\/sicZYNzFtuZFGC\/ubPK5Ld9RsJb\/RQ9rkTZzhkBnmM=","iv":"2fedfd8ae68165490f274b521d5a3291","s":"74a525e8e5746772"}');
|
|
73
|
+
# });
|
|
74
|
+
# '''
|
|
75
|
+
|
|
76
|
+
# be_player = search(r"bePlayer\('([^']+)',\s*'(\{[^\}]+\})'\);", veri).groups()
|
|
77
|
+
# be_player_pass = be_player[0]
|
|
78
|
+
# be_player_data = be_player[1]
|
|
79
|
+
|
|
80
|
+
# encrypted = AESManager.decrypt(be_player_data, be_player_pass).replace("\\", "")
|
|
81
|
+
# print(json.loads(encrypted))
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# ! Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
from Crypto.Cipher import AES
|
|
4
|
+
from Crypto.Random import get_random_bytes
|
|
5
|
+
import hashlib, base64
|
|
6
|
+
|
|
7
|
+
class CryptoJS:
|
|
8
|
+
"""
|
|
9
|
+
Paroladan türetilmiş anahtar ile AES/CBC/PKCS7Padding şifreleme ve şifre çözme işlemleri için bir sınıf.
|
|
10
|
+
CryptoJS AES yöntemine uygundur.
|
|
11
|
+
! » https://gist.github.com/thackerronak/554c985c3001b16810af5fc0eb5c358f
|
|
12
|
+
"""
|
|
13
|
+
KEY_SIZE = 32
|
|
14
|
+
IV_SIZE = 16
|
|
15
|
+
HASH_CIPHER = "AES/CBC/PKCS7Padding"
|
|
16
|
+
AES_MODE = AES.MODE_CBC
|
|
17
|
+
KDF_DIGEST = "md5"
|
|
18
|
+
APPEND = b"Salted__"
|
|
19
|
+
|
|
20
|
+
@staticmethod
|
|
21
|
+
def evp_kdf(password, salt, key_size=32, iv_size=16, iterations=1, hash_algorithm="md5"):
|
|
22
|
+
"""Paroladan Anahtar ve IV oluşturmak için bir KDF fonksiyonu."""
|
|
23
|
+
target_key_size = key_size + iv_size
|
|
24
|
+
derived_bytes = b""
|
|
25
|
+
block = None
|
|
26
|
+
|
|
27
|
+
while len(derived_bytes) < target_key_size:
|
|
28
|
+
hasher = hashlib.new(hash_algorithm)
|
|
29
|
+
if block:
|
|
30
|
+
hasher.update(block)
|
|
31
|
+
|
|
32
|
+
hasher.update(password)
|
|
33
|
+
hasher.update(salt)
|
|
34
|
+
block = hasher.digest()
|
|
35
|
+
|
|
36
|
+
for _ in range(1, iterations):
|
|
37
|
+
block = hashlib.new(hash_algorithm, block).digest()
|
|
38
|
+
|
|
39
|
+
derived_bytes += block
|
|
40
|
+
|
|
41
|
+
return derived_bytes[:key_size], derived_bytes[key_size:key_size + iv_size]
|
|
42
|
+
|
|
43
|
+
@staticmethod
|
|
44
|
+
def encrypt(password, plain_text):
|
|
45
|
+
"""Verilen metni AES/CBC/PKCS7Padding şifreleme yöntemi ile şifreler."""
|
|
46
|
+
salt = CryptoJS.generate_salt(8)
|
|
47
|
+
key, iv = CryptoJS.evp_kdf(password.encode("utf-8"), salt, key_size=CryptoJS.KEY_SIZE, iv_size=CryptoJS.IV_SIZE)
|
|
48
|
+
|
|
49
|
+
cipher = AES.new(key, CryptoJS.AES_MODE, iv)
|
|
50
|
+
cipher_text = cipher.encrypt(CryptoJS._pad(plain_text.encode("utf-8")))
|
|
51
|
+
|
|
52
|
+
# Create CryptoJS-like encrypted output
|
|
53
|
+
encrypted_data = CryptoJS.APPEND + salt + cipher_text
|
|
54
|
+
|
|
55
|
+
return base64.b64encode(encrypted_data).decode("utf-8")
|
|
56
|
+
|
|
57
|
+
@staticmethod
|
|
58
|
+
def decrypt(password, cipher_text):
|
|
59
|
+
"""Verilen şifreli metni AES/CBC/PKCS7Padding şifreleme yöntemi ile çözer."""
|
|
60
|
+
ct_bytes = base64.b64decode(cipher_text)
|
|
61
|
+
salt = ct_bytes[8:16]
|
|
62
|
+
cipher_text_bytes = ct_bytes[16:]
|
|
63
|
+
|
|
64
|
+
key, iv = CryptoJS.evp_kdf(password.encode("utf-8"), salt, key_size=CryptoJS.KEY_SIZE, iv_size=CryptoJS.IV_SIZE)
|
|
65
|
+
|
|
66
|
+
cipher = AES.new(key, CryptoJS.AES_MODE, iv)
|
|
67
|
+
plain_text = cipher.decrypt(cipher_text_bytes)
|
|
68
|
+
|
|
69
|
+
return CryptoJS._unpad(plain_text).decode("utf-8")
|
|
70
|
+
|
|
71
|
+
@staticmethod
|
|
72
|
+
def _pad(s):
|
|
73
|
+
"""Veriyi AES blok boyutuna göre doldurur (PKCS7)."""
|
|
74
|
+
block_size = AES.block_size
|
|
75
|
+
padding = block_size - len(s) % block_size
|
|
76
|
+
|
|
77
|
+
return s + bytes([padding] * padding)
|
|
78
|
+
|
|
79
|
+
@staticmethod
|
|
80
|
+
def _unpad(s):
|
|
81
|
+
"""Dolguyu kaldırır (PKCS7)."""
|
|
82
|
+
return s[:-ord(s[-1:])]
|
|
83
|
+
|
|
84
|
+
@staticmethod
|
|
85
|
+
def generate_salt(length):
|
|
86
|
+
"""Belirtilen uzunlukta rastgele bir tuz oluşturur."""
|
|
87
|
+
return get_random_bytes(length)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
# veri = r'''
|
|
92
|
+
# <script type="text/javascript">var bytes = CryptoJS.AES.decrypt("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");document.write(bytes.toString(CryptoJS.enc.Utf8));</script>
|
|
93
|
+
# '''
|
|
94
|
+
|
|
95
|
+
# cryptData = re.search(r"CryptoJS\.AES\.decrypt\(\"(.*)\",\"", veri).group(1)
|
|
96
|
+
# cryptPass = re.search(r"\",\"(.*)\"\);", veri).group(1)
|
|
97
|
+
|
|
98
|
+
# decrypted = CryptoJS.decrypt(cryptPass, cryptData)
|
|
99
|
+
# print(decrypted)
|
|
@@ -3,9 +3,7 @@
|
|
|
3
3
|
class HexCodec:
|
|
4
4
|
@staticmethod
|
|
5
5
|
def encode(utf8_string: str) -> str:
|
|
6
|
-
"""
|
|
7
|
-
UTF-8 stringini kaçış dizileriyle birlikte hex stringine dönüştürür.
|
|
8
|
-
"""
|
|
6
|
+
"""UTF-8 stringini kaçış dizileriyle birlikte hex stringine dönüştürür."""
|
|
9
7
|
byte_data = utf8_string.encode("utf-8")
|
|
10
8
|
hex_string = byte_data.hex()
|
|
11
9
|
escaped_hex = "\\x".join(hex_string[i:i+2] for i in range(0, len(hex_string), 2))
|
|
@@ -14,9 +12,7 @@ class HexCodec:
|
|
|
14
12
|
|
|
15
13
|
@staticmethod
|
|
16
14
|
def decode(escaped_hex: str) -> str:
|
|
17
|
-
"""
|
|
18
|
-
Kaçış dizileri içeren bir hex stringini UTF-8 formatındaki stringe dönüştürür.
|
|
19
|
-
"""
|
|
15
|
+
"""Kaçış dizileri içeren bir hex stringini UTF-8 formatındaki stringe dönüştürür."""
|
|
20
16
|
hex_string = escaped_hex.replace("\\x", "")
|
|
21
17
|
byte_data = bytes.fromhex(hex_string)
|
|
22
18
|
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
from Crypto.Cipher import AES
|
|
4
|
+
from Crypto.Util.Padding import unpad
|
|
5
|
+
from hmac import new as hmac
|
|
6
|
+
from hashlib import sha256
|
|
7
|
+
from base64 import b64decode, b64encode
|
|
8
|
+
from json import dumps
|
|
9
|
+
|
|
10
|
+
class NaysHash:
|
|
11
|
+
"""
|
|
12
|
+
HMAC-SHA256 hash üretimi ve API token'ı oluşturma işlemleri için bir sınıf.
|
|
13
|
+
Şifreleme ve hash işlemlerinde kullanılan anahtarlar ve yöntemler hakkında bilgi sağlar.
|
|
14
|
+
# ! https://gist.github.com/keyiflerolsun/e91c6d6f19e79b5cd4cbc73833f74e72
|
|
15
|
+
"""
|
|
16
|
+
def __init__(self, default_key:str="+KbPdSgVkYp3s6v9y=B&E)H@McQfThWm", application_key:str="y3o2R7UZg13nVqFAg+B9IVj61M62CLJSw0kPoy3RBJ9kISt0MSU9BBDy7SBUL7MK") -> None:
|
|
17
|
+
# HMAC için kullanılacak anahtarı deşifrele
|
|
18
|
+
self.hmac_key = self.decrypt_aes_cbc_pkcs7(
|
|
19
|
+
encrypted_text = application_key,
|
|
20
|
+
secret_key = default_key
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
def decrypt_aes_cbc_pkcs7(self, encrypted_text:str, secret_key:str) -> str:
|
|
24
|
+
# Şifrelenmiş metni ve anahtarı bayt dizisine çevir
|
|
25
|
+
encrypted_text_bytes = b64decode(encrypted_text.encode("utf-8"))
|
|
26
|
+
key_bytes = secret_key.encode("utf-8")
|
|
27
|
+
|
|
28
|
+
# İlk vektörü (IV) ve şifre çözücüyü (cipher) oluştur
|
|
29
|
+
iv = key_bytes[:16]
|
|
30
|
+
cipher = AES.new(key_bytes, AES.MODE_CBC, iv)
|
|
31
|
+
|
|
32
|
+
# Metni deşifre et
|
|
33
|
+
decrypted_bytes = unpad(cipher.decrypt(encrypted_text_bytes), AES.block_size)
|
|
34
|
+
return decrypted_bytes.decode("utf-8")
|
|
35
|
+
|
|
36
|
+
def generate_hash_with_hmac256(self, msg:str):
|
|
37
|
+
# Verilen mesaj için HMAC-SHA256 hash oluştur
|
|
38
|
+
hmac256_hash = hmac(
|
|
39
|
+
key = self.hmac_key.encode("utf-8"),
|
|
40
|
+
msg = msg.encode("utf-8"),
|
|
41
|
+
digestmod = sha256
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
return b64encode(hmac256_hash.digest()).decode("utf-8")
|
|
45
|
+
|
|
46
|
+
def generate_xtoken(self, endpoint:str, payload:dict, timestamp:int) -> str:
|
|
47
|
+
# API isteği için "xtoken" oluştur
|
|
48
|
+
return self.generate_hash_with_hmac256(
|
|
49
|
+
f"{endpoint}{dumps(payload, ensure_ascii=False, sort_keys=False)}{timestamp}".replace(" ", "")
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
# print(NaysHash().generate_xtoken(
|
|
55
|
+
# timestamp = 1695076755128,
|
|
56
|
+
# endpoint = "/customer-citizen-info-v3",
|
|
57
|
+
# payload = {
|
|
58
|
+
# "birthDay" : 31,
|
|
59
|
+
# "birthMonth" : 1,
|
|
60
|
+
# "birthYear" : 1990,
|
|
61
|
+
# "citizenId" : "11111111111",
|
|
62
|
+
# "customerName" : "merhaba",
|
|
63
|
+
# "customerSurname" : "dünya",
|
|
64
|
+
# "explicitConsentSigned" : True
|
|
65
|
+
# },
|
|
66
|
+
# ))
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# ! Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
import base64
|
|
4
|
+
|
|
5
|
+
class StringCodec:
|
|
6
|
+
"""
|
|
7
|
+
Base64 ve ROT13 kodlama/çözme işlemleri için bir sınıf.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
@staticmethod
|
|
11
|
+
def atob(encoded_string: str) -> str:
|
|
12
|
+
"""Base64 kodlu bir stringi çözer ve UTF-8 string olarak döndürür."""
|
|
13
|
+
return base64.b64decode(encoded_string).decode("utf-8")
|
|
14
|
+
|
|
15
|
+
@staticmethod
|
|
16
|
+
def btoa(plain_text: str) -> str:
|
|
17
|
+
"""Bir stringi Base64 formatında kodlar."""
|
|
18
|
+
return base64.b64encode(plain_text.encode("utf-8")).decode("utf-8")
|
|
19
|
+
|
|
20
|
+
@staticmethod
|
|
21
|
+
def rtt(input_string: str) -> str:
|
|
22
|
+
"""Verilen stringin ROT13 kodlamasını uygular veya çözer."""
|
|
23
|
+
def rot13_char(char):
|
|
24
|
+
if "a" <= char <= "z":
|
|
25
|
+
return chr((ord(char) - ord("a") + 13) % 26 + ord("a"))
|
|
26
|
+
elif "A" <= char <= "Z":
|
|
27
|
+
return chr((ord(char) - ord("A") + 13) % 26 + ord("A"))
|
|
28
|
+
return char
|
|
29
|
+
|
|
30
|
+
return "".join(rot13_char(char) for char in input_string)
|
|
31
|
+
|
|
32
|
+
@staticmethod
|
|
33
|
+
def decode(encoded_string: str) -> str:
|
|
34
|
+
"""Önce ROT13 uygular, ardından Base64 çözer."""
|
|
35
|
+
return StringCodec.atob(StringCodec.rtt(encoded_string))
|
|
36
|
+
|
|
37
|
+
@staticmethod
|
|
38
|
+
def encode(plain_text: str) -> str:
|
|
39
|
+
"""Önce Base64 kodlar, ardından ROT13 uygular."""
|
|
40
|
+
return StringCodec.rtt(StringCodec.btoa(plain_text))
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
from .StringCodec import StringCodec
|
|
4
|
+
from .AESManager import AESManager
|
|
5
|
+
from .Packer import Packer
|
|
6
|
+
from .CryptoJS import CryptoJS
|
|
7
|
+
from .HexCodec import HexCodec
|
|
8
|
+
from .NaysHash import NaysHash
|
|
@@ -33,10 +33,11 @@ Kekik.egg-info/entry_points.txt
|
|
|
33
33
|
Kekik.egg-info/requires.txt
|
|
34
34
|
Kekik.egg-info/top_level.txt
|
|
35
35
|
Kekik/Sifreleme/AESManager.py
|
|
36
|
-
Kekik/Sifreleme/AtobRtt.py
|
|
37
36
|
Kekik/Sifreleme/CryptoJS.py
|
|
38
37
|
Kekik/Sifreleme/HexCodec.py
|
|
38
|
+
Kekik/Sifreleme/NaysHash.py
|
|
39
39
|
Kekik/Sifreleme/Packer.py
|
|
40
|
+
Kekik/Sifreleme/StringCodec.py
|
|
40
41
|
Kekik/Sifreleme/__init__.py
|
|
41
42
|
Kekik/kisi_ver/__init__.py
|
|
42
43
|
Kekik/kisi_ver/biyografiler.py
|
|
@@ -6,7 +6,7 @@ from io import open
|
|
|
6
6
|
setup(
|
|
7
7
|
# ? Genel Bilgiler
|
|
8
8
|
name = "Kekik",
|
|
9
|
-
version = "1.5.
|
|
9
|
+
version = "1.5.4",
|
|
10
10
|
url = "https://github.com/keyiflerolsun/Kekik",
|
|
11
11
|
description = "İşlerimizi kolaylaştıracak fonksiyonların el altında durduğu kütüphane..",
|
|
12
12
|
keywords = ["Kekik", "KekikAkademi", "keyiflerolsun"],
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# ! Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
-
|
|
3
|
-
import base64
|
|
4
|
-
|
|
5
|
-
def atob(s:str) -> str:
|
|
6
|
-
return base64.b64decode(s).decode("utf-8")
|
|
7
|
-
|
|
8
|
-
def rtt(s:str) -> str:
|
|
9
|
-
def rot13_char(c):
|
|
10
|
-
if "a" <= c <= "z":
|
|
11
|
-
return chr((ord(c) - ord("a") + 13) % 26 + ord("a"))
|
|
12
|
-
elif "A" <= c <= "Z":
|
|
13
|
-
return chr((ord(c) - ord("A") + 13) % 26 + ord("A"))
|
|
14
|
-
return c
|
|
15
|
-
|
|
16
|
-
return "".join(rot13_char(c) for c in s)
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
# ! Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
-
|
|
3
|
-
from Crypto.Cipher import AES
|
|
4
|
-
from Crypto.Random import get_random_bytes
|
|
5
|
-
import hashlib, base64
|
|
6
|
-
|
|
7
|
-
class CryptoJS:
|
|
8
|
-
"""
|
|
9
|
-
Paroladan türetilmiş anahtar ile AES/CBC/PKCS7Padding şifreleme ve şifre çözme işlemleri için bir sınıf.
|
|
10
|
-
CryptoJS AES yöntemine uygundur.
|
|
11
|
-
! » https://gist.github.com/thackerronak/554c985c3001b16810af5fc0eb5c358f
|
|
12
|
-
"""
|
|
13
|
-
KEY_SIZE = 32
|
|
14
|
-
IV_SIZE = 16
|
|
15
|
-
HASH_CIPHER = "AES/CBC/PKCS7Padding"
|
|
16
|
-
AES_MODE = AES.MODE_CBC
|
|
17
|
-
KDF_DIGEST = "md5"
|
|
18
|
-
APPEND = b"Salted__"
|
|
19
|
-
|
|
20
|
-
@staticmethod
|
|
21
|
-
def evp_kdf(password, salt, key_size=32, iv_size=16, iterations=1, hash_algorithm="md5"):
|
|
22
|
-
"""Paroladan Anahtar ve IV oluşturmak için bir KDF fonksiyonu."""
|
|
23
|
-
target_key_size = key_size + iv_size
|
|
24
|
-
derived_bytes = b""
|
|
25
|
-
block = None
|
|
26
|
-
|
|
27
|
-
while len(derived_bytes) < target_key_size:
|
|
28
|
-
hasher = hashlib.new(hash_algorithm)
|
|
29
|
-
if block:
|
|
30
|
-
hasher.update(block)
|
|
31
|
-
|
|
32
|
-
hasher.update(password)
|
|
33
|
-
hasher.update(salt)
|
|
34
|
-
block = hasher.digest()
|
|
35
|
-
|
|
36
|
-
for _ in range(1, iterations):
|
|
37
|
-
block = hashlib.new(hash_algorithm, block).digest()
|
|
38
|
-
|
|
39
|
-
derived_bytes += block
|
|
40
|
-
|
|
41
|
-
return derived_bytes[:key_size], derived_bytes[key_size:key_size + iv_size]
|
|
42
|
-
|
|
43
|
-
@staticmethod
|
|
44
|
-
def encrypt(password, plain_text):
|
|
45
|
-
"""Verilen metni AES/CBC/PKCS7Padding şifreleme yöntemi ile şifreler."""
|
|
46
|
-
salt = CryptoJS.generate_salt(8)
|
|
47
|
-
key, iv = CryptoJS.evp_kdf(password.encode("utf-8"), salt, key_size=CryptoJS.KEY_SIZE, iv_size=CryptoJS.IV_SIZE)
|
|
48
|
-
|
|
49
|
-
cipher = AES.new(key, CryptoJS.AES_MODE, iv)
|
|
50
|
-
cipher_text = cipher.encrypt(CryptoJS._pad(plain_text.encode("utf-8")))
|
|
51
|
-
|
|
52
|
-
# Create CryptoJS-like encrypted output
|
|
53
|
-
encrypted_data = CryptoJS.APPEND + salt + cipher_text
|
|
54
|
-
|
|
55
|
-
return base64.b64encode(encrypted_data).decode("utf-8")
|
|
56
|
-
|
|
57
|
-
@staticmethod
|
|
58
|
-
def decrypt(password, cipher_text):
|
|
59
|
-
"""Verilen şifreli metni AES/CBC/PKCS7Padding şifreleme yöntemi ile çözer."""
|
|
60
|
-
ct_bytes = base64.b64decode(cipher_text)
|
|
61
|
-
salt = ct_bytes[8:16]
|
|
62
|
-
cipher_text_bytes = ct_bytes[16:]
|
|
63
|
-
|
|
64
|
-
key, iv = CryptoJS.evp_kdf(password.encode("utf-8"), salt, key_size=CryptoJS.KEY_SIZE, iv_size=CryptoJS.IV_SIZE)
|
|
65
|
-
|
|
66
|
-
cipher = AES.new(key, CryptoJS.AES_MODE, iv)
|
|
67
|
-
plain_text = cipher.decrypt(cipher_text_bytes)
|
|
68
|
-
|
|
69
|
-
return CryptoJS._unpad(plain_text).decode("utf-8")
|
|
70
|
-
|
|
71
|
-
@staticmethod
|
|
72
|
-
def _pad(s):
|
|
73
|
-
"""Veriyi AES blok boyutuna göre doldurur (PKCS7)."""
|
|
74
|
-
block_size = AES.block_size
|
|
75
|
-
padding = block_size - len(s) % block_size
|
|
76
|
-
|
|
77
|
-
return s + bytes([padding] * padding)
|
|
78
|
-
|
|
79
|
-
@staticmethod
|
|
80
|
-
def _unpad(s):
|
|
81
|
-
"""Dolguyu kaldırır (PKCS7)."""
|
|
82
|
-
return s[:-ord(s[-1:])]
|
|
83
|
-
|
|
84
|
-
@staticmethod
|
|
85
|
-
def generate_salt(length):
|
|
86
|
-
"""Belirtilen uzunlukta rastgele bir tuz oluşturur."""
|
|
87
|
-
return get_random_bytes(length)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|