2222# pip install -U bcrypt kececinumbers blake3 pycryptodome xxhash argon2-cffi pandas numpy cryptography ipywidgets ipython scipy
2323# conda install -c conda-forge kececinumbers bcrypt blake3 pycryptodome xxhash argon2-cffi pandas numpy cryptography pandas ipywidgets ipython scipy
2424# pip install xxhash: # xxh32 collision riski yüksek (64-bit için ~yüz milyonlarda %0.03)
25+
26+ * 0.3.7. qKHA256: quantum random
27+
2528"""
2629
2730from __future__ import annotations
2831
2932import argon2 # pip install argon2-cffi # conda install conda-forge::argon2-cffi
3033import bcrypt
3134from blake3 import blake3
35+ from collections import defaultdict
36+ from contextlib import contextmanager
37+ from dataclasses import dataclass
38+ from datetime import datetime
39+ from decimal import getcontext
40+ from functools import lru_cache
41+ from hmac import compare_digest # , compare_digicmp
3242from Crypto .Cipher import ChaCha20 # pip install -U pycryptodome # conda install conda-forge::pycryptodome
3343from Crypto .Hash import SHAKE256
3444from cryptography .hazmat .primitives import hashes
4959import platform
5060import random
5161import re
62+ import requests
5263from scipy .stats import chi2 , norm
5364import secrets
5465import sqlite3
5970import time
6071import traceback
6172import uuid
62- from collections import defaultdict
63- from contextlib import contextmanager
64- from dataclasses import dataclass
65- from datetime import datetime
66- from decimal import getcontext
67- from functools import lru_cache
68- from hmac import compare_digest # , compare_digicmp
6973from typing import TYPE_CHECKING , Any , Callable , ClassVar , Dict , List , Literal , NamedTuple , Optional , overload , Tuple , Union , cast
7074# pip install xxhash: # xxh32 collision riski yüksek (64-bit için ~yüzmilyonlarda %0.03)
7175import xxhash
7276
77+ from . import __version__ # paket __init__.py'de tanımlı
78+
79+
7380
7481
7582def silent_kn ():
@@ -248,7 +255,7 @@ def is_jupyter():
248255 from . import __version__
249256except ImportError :
250257 # Dosya doğrudan çalıştırıldığında (Örn: python kha256.py) fallback
251- __version__ = "0.2.9 "
258+ __version__ = "0.3.7 "
252259
253260
254261# Version information
@@ -257,7 +264,7 @@ def is_jupyter():
257264__license__ = "AGPL-3.0-or-later"
258265__status__ = "Pre-Production"
259266__certificate__ = "KHA256-PA-2025-001"
260- req_kececinumbers = "1.0.1 "
267+ req_kececinumbers = "1.0.5 "
261268
262269# KeçeciNumbers check - made API compatible
263270KHA_AVAILABLE = True
@@ -1444,7 +1451,8 @@ class KHA256:
14441451 def __init__ (self ):
14451452 self ._salt_length = 32
14461453 self ._metrics = {"hash_count" : 0 , "total_time_ms" : 0.0 , "memory_hard_count" : 0 }
1447- self ._version = "2.5.0"
1454+ #self._version = "0.3.7"
1455+ self ._version = __version__ # __init__.py'den al
14481456
14491457 def hash (
14501458 self ,
@@ -1542,9 +1550,189 @@ def version(self) -> str:
15421550 def metrics (self ) -> Dict [str , Any ]:
15431551 return self ._metrics .copy ()
15441552
1553+ def get_quantum_bytes (length : int , verbose : bool = False ) -> Tuple [bytes , str ]:
1554+ """
1555+ ANU kuantum rastgele sayı API'sinden 'length' byte üretir.
1556+ Ham uint16 değerlerini big-endian 2 byte olarak birleştirir.
1557+ """
1558+ CHUNK_SIZE = 1000 # API maksimum 1000 öğe döner
1559+ needed_u16 = (length + 1 ) // 2 # kaç uint16 gerektiği
1560+ all_bytes = bytearray ()
1561+
1562+ for i in range (0 , needed_u16 , CHUNK_SIZE ):
1563+ chunk = min (CHUNK_SIZE , needed_u16 - i )
1564+ url = f"https://qrng.anu.edu.au/API/jsonI.php?length={ chunk } &type=uint16"
1565+ try :
1566+ resp = requests .get (url , timeout = 15 )
1567+ if resp .status_code == 200 :
1568+ data = resp .json ().get ("data" , [])
1569+ if len (data ) >= chunk :
1570+ for val in data [:chunk ]:
1571+ all_bytes .extend (val .to_bytes (2 , 'big' ))
1572+ if verbose :
1573+ print (f"✅ Kuantum API: { len (data [:chunk ])* 2 } byte alındı" )
1574+ else :
1575+ if verbose :
1576+ print ("⚠️ API yetersiz veri döndü, fallback'e geçiliyor." )
1577+ return _fallback_bytes (length , verbose ), "fallback"
1578+ else :
1579+ if verbose :
1580+ print (f"⚠️ API hatası { resp .status_code } " )
1581+ return _fallback_bytes (length , verbose ), "fallback"
1582+ except Exception as e :
1583+ if verbose :
1584+ print (f"⚠️ API bağlantı hatası: { e } " )
1585+ return _fallback_bytes (length , verbose ), "fallback"
1586+
1587+ # Tam olarak length byte döndür (fazlalık varsa kes)
1588+ return bytes (all_bytes [:length ]), "api"
1589+
1590+ def _fallback_bytes (length : int , verbose : bool = False ) -> bytes :
1591+ if verbose :
1592+ print ("↳ secrets.token_bytes ile devam ediliyor." )
1593+ return secrets .token_bytes (length )
1594+
1595+ class qKHA256 :
1596+ """
1597+ qKHA-256 - Quantum KHA-256
1598+ ==========================================
1599+ ✓ Hiçbir standart hash'ten kod alınmamıştır
1600+ ✓ Tüm sabitler matematiksel irrasyonellerden üretilmiştir
1601+ ✓ Perfect avalanche hedefi: 128.00/128.00
1602+ ✓ HMAC desteği
1603+ ✓ real quantum random
1604+ ==========================================
1605+ """
1606+
1607+ __slots__ = ("_salt_length" , "_metrics" , "_version" )
1608+
1609+ def __init__ (self ):
1610+ self ._salt_length = 32
1611+ self ._metrics = {"hash_count" : 0 , "total_time_ms" : 0.0 , "memory_hard_count" : 0 }
1612+ self ._version = __version__ # __init__.py'den al
1613+
1614+ def _generate_salt (self , quantum : bool = True , verbose : bool = False ) -> bytes :
1615+ """Kuantum (varsa) ya da sistem random ile salt üret."""
1616+ if quantum :
1617+ salt_bytes , source = get_quantum_bytes (self ._salt_length , verbose = verbose )
1618+ if source == "api" :
1619+ return salt_bytes
1620+ # fallback olmuşsa da döner, yukarıda fallback zaten secrets ile yapılıyor
1621+ # quantum False ise ya da üretim başarısız olup fallback döndüyse
1622+ return secrets .token_bytes (self ._salt_length )
1623+
1624+ def hash (
1625+ self ,
1626+ data : Union [str , bytes ],
1627+ salt : Optional [bytes ] = None ,
1628+ * ,
1629+ deterministic : bool = False ,
1630+ memory_hard : bool = False ,
1631+ memory_mb : int = 1 ,
1632+ quantum : bool = True , # yeni parametre
1633+ verbose : bool = False # kuantum API durumunu görmek için
1634+ ) -> str :
1635+ start = time .perf_counter ()
1636+ data_bytes = data .encode ("utf-8" ) if isinstance (data , str ) else data
1637+
1638+ if deterministic :
1639+ if salt is None :
1640+ raise ValueError ("Deterministic modda salt gerekli!" )
1641+ result = DeterministicHash .hash (data_bytes + salt ).hex ()
1642+ self ._update_metrics (start )
1643+ return result
1644+
1645+ if memory_hard :
1646+ if salt is None :
1647+ salt = self ._generate_salt (quantum = quantum , verbose = verbose )
1648+ result = MemoryHardHash (memory_mb ).hash (data_bytes , salt )
1649+ self ._update_metrics (start )
1650+ self ._metrics ["memory_hard_count" ] += 1
1651+ return result
1652+
1653+ if salt is None :
1654+ salt = self ._generate_salt (quantum = quantum , verbose = verbose )
1655+
1656+ # Pre-processing
1657+ prepared = bytearray (data_bytes )
1658+ for i in range (len (prepared )):
1659+ prepared [i ] ^= salt [i % len (salt )]
1660+ prepared [i ] = KHAUtils .rotl8 (prepared [i ], ROT_PRE )
1661+ prepared [i ] ^= (i * int (PI )) & 0xFF
1662+
1663+ result = CoreHash .hash (bytes (prepared ), salt )
1664+
1665+ final = bytearray (result )
1666+ for i in range (len (final )):
1667+ final [i ] ^= salt [i % len (salt )]
1668+ final [i ] ^= data_bytes [i % len (data_bytes )]
1669+ final [i ] = KHAUtils .rotl8 (final [i ], ROT_POST )
1670+ final [i ] ^= TransformFunctions .chaos (i ) & 0xFF
1671+
1672+ self ._update_metrics (start )
1673+ return bytes (final ).hex ()
1674+
1675+ def hmac (self , key : bytes , message : Union [str , bytes ]) -> str :
1676+ """
1677+ KHA-256 HMAC (Hash-based Message Authentication Code)
1678+ """
1679+ msg_bytes = message .encode ("utf-8" ) if isinstance (message , str ) else message
1680+
1681+ # Key padding - HMAC standardı
1682+ if len (key ) > 64 :
1683+ key = DeterministicHash .hash (key )
1684+ if len (key ) < 64 :
1685+ key = key + b"\x00 " * (64 - len (key ))
1686+
1687+ # HMAC: hash(o_key_pad || hash(i_key_pad || message))
1688+ o_key_pad = bytes (x ^ 0x5C for x in key [:64 ])
1689+ i_key_pad = bytes (x ^ 0x36 for x in key [:64 ])
1690+
1691+ # Deterministic mod kullan (salt yok)
1692+ inner_hash = self .hash (i_key_pad + msg_bytes , b"" , deterministic = True )
1693+ outer_hash = self .hash (
1694+ o_key_pad + bytes .fromhex (inner_hash ), b"" , deterministic = True
1695+ )
1696+
1697+ return outer_hash
1698+
1699+ def verify (
1700+ self , data : Union [str , bytes ], hash_str : str , salt : bytes , ** kwargs
1701+ ) -> bool :
1702+ """Hash doğrulama"""
1703+ computed = self .hash (data , salt , ** kwargs )
1704+ return compare_digest (computed .encode (), hash_str .encode ())
1705+
1706+ def _update_metrics (self , start : float ):
1707+ elapsed = (time .perf_counter () - start ) * 1000
1708+ self ._metrics ["hash_count" ] += 1
1709+ self ._metrics ["total_time_ms" ] += elapsed
1710+
1711+ @property
1712+ def version (self ) -> str :
1713+ return self ._version
1714+
1715+ @property
1716+ def metrics (self ) -> Dict [str , Any ]:
1717+ return self ._metrics .copy ()
1718+
1719+ ## 3. Kullanım örneği
1720+ qhasher = qKHA256 ()
1721+
1722+ # Kuantum salt ile hash (varsayılan)
1723+ h1 = qhasher .hash ("merhaba dünya" , verbose = True )
1724+
1725+ # Klasik güvenli random ile hash
1726+ h2 = qhasher .hash ("merhaba dünya" , quantum = False )
1727+
1728+ # Doğrulama
1729+ salt = secrets .token_bytes (32 )
1730+ h3 = qhasher .hash ("veri" , salt = salt , quantum = True )
1731+ assert qhasher .verify ("veri" , h3 , salt , quantum = True )
1732+
15451733
15461734# ============================================================================
1547- # 8. STREAMING HASH SINIFI - KESİN ÇÖZÜM (ARTIK ÇALIŞIYOR!)
1735+ # 8. STREAMING HASH SINIFI
15481736# ============================================================================
15491737
15501738
0 commit comments