Skip to content

Commit 297f9fc

Browse files
committed
Add frequency_within_block plugin and tests
Introduces the frequency_within_block statistical test plugin and its corresponding test suite. Updates documentation to reference the new plugin and makes minor improvements to linear_complexity and maurers_universal plugins and their tests.
1 parent 82b68ea commit 297f9fc

8 files changed

Lines changed: 616 additions & 66 deletions

docs/plugin-developer-guide.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,85 @@ Ek referans
9898

9999
Bu kılavuz, hızlı bir başlangıç sağlar. İleri seviye konu veya örnek isterseniz ayrı bir doküman eklenebilir.
100100

101+
## Yeni Test Eklentileri: frequency_within_block, maurers_universal, linear_complexity
102+
103+
Aşağıda proje içinde eklenmiş/ güncellenmiş üç test eklentisi için geliştirici notları bulunmaktadır. Her bölümde eklentinin amacı (NIST ile bağlantı), kabul edilen parametreler/varsayılanlar, döndürülen önemli metrikler ve kısa kullanım örneği yer alır.
104+
105+
### Frequency Test within a Block
106+
- Dosya: [`patternlab/plugins/frequency_within_block.py`](patternlab/plugins/frequency_within_block.py:1)
107+
- Amaç ve NIST bağlantısı: NIST SP 800‑22 içindeki "Frequency Test within a Block" yaklaşımına dayanır. Girdi bit dizisini M boyutlu bloklara ayırır ve her bloktaki 1 oranlarının beklenen 0.5 değerinden sapmasını chi-square benzeri bir istatistik ile değerlendirir.
108+
- Parametreler ve varsayılanlar:
109+
- `block_size` (int): açıkça verilirse kullanılır (M).
110+
- `default_block_size` (int, default 128): `block_size` verilmediğinde kullanılacak varsayılan.
111+
- `alpha` (float, default 0.01): anlamlılık seviyesi.
112+
- Seçme heuristiği: Eğer toplam bit sayısı n 100 ile tam bölünürse M = n // 100 seçilebilir.
113+
- Çıktı metrikleri (TestResult.metrics):
114+
- `block_count`, `block_size`, `total_bits`
115+
- `ones_counts`: blok başına 1 sayıları
116+
- `proportions`: blok başına 1 oranları
117+
- `chi_square`
118+
- Kullanım örneği:
119+
```python
120+
# python
121+
from patternlab.plugins.frequency_within_block import FrequencyWithinBlockTest
122+
from patternlab.plugin_api import BytesView
123+
124+
plugin = FrequencyWithinBlockTest()
125+
data = BytesView(b'\xff\x00\xaa') # örnek
126+
result = plugin.run(data, {"block_size": 8, "alpha": 0.01})
127+
print(result.p_value, result.metrics["chi_square"])
128+
```
129+
130+
### Maurer's Universal Test (güncellenmiş)
131+
- Dosya: [`patternlab/plugins/maurers_universal.py`](patternlab/plugins/maurers_universal.py:1)
132+
- Amaç ve NIST bağlantısı: NIST SP 800‑22'de tanımlanan Maurer’s Universal Statistical Test'e uyumlu bir uygulamadır. Desenlerin tekrar uzaklıklarının log2 ortalaması üzerinden dizinin beklenen sıkılık/karmaşıklığını ölçer.
133+
- Parametreler ve varsayılanlar:
134+
- `L` (int, default 6): blok uzunluğu (NIST önerisi 6..16 arası).
135+
- `Q` (int, default 10 * 2**L): başlatma (init) blok sayısı.
136+
- `min_blocks` (int): toplam blok sayısı için minimum gereksinim; varsayılan Q + 1000 (NIST gereksinimine uyum).
137+
- `alpha` (float, default 0.01)
138+
- Önemli davranışlar:
139+
- Yetersiz blok sayısında test "skipped" (atlandı) olarak döner ve sebebi açıkça belirtilir.
140+
- NIST referans ortalama ve varyans tablosu (L=6..16) kullanılır.
141+
- Çıktı metrikleri:
142+
- `L`, `blocks` (toplam blok), `init_Q`, `processed_blocks` (K), `fn` (ortalama log2 mesafe), `expected`, `variance`, `z_score`, `total_bits`
143+
- Kullanım örneği:
144+
```python
145+
# python
146+
from patternlab.plugins.maurers_universal import MaurersUniversalTest
147+
from patternlab.plugin_api import BytesView
148+
149+
plugin = MaurersUniversalTest()
150+
data = BytesView(open("test.bin","rb").read())
151+
res = plugin.run(data, {"L": 6})
152+
if isinstance(res, dict) and res.get("status") == "skipped":
153+
print("Skipped:", res["reason"])
154+
else:
155+
print(res.p_value, res.metrics["fn"])
156+
```
157+
158+
### Linear Complexity (güncellenmiş)
159+
- Dosya: [`patternlab/plugins/linear_complexity.py`](patternlab/plugins/linear_complexity.py:1)
160+
- Amaç ve NIST bağlantısı: Berlekamp–Massey algoritması ile bit dizisinin GF(2) üzerindeki lineer kompleksitesini hesaplar. NIST SP 800‑22'deki lineer kompleksite testine benzer istatistikler ve yaklaşık p-değerleri sunar; proje içinde diagnostic amaçlı kullanılabilir.
161+
- Parametreler ve varsayılanlar:
162+
- `alpha` (float, default 0.01)
163+
- Girdi uzunluğu n==0 ise test hata/uyarı içeren bir TestResult döndürür.
164+
- Hesaplama ve çıktı:
165+
- `linear_complexity` (L), `n` (bit uzunluğu)
166+
- Ayrıca NIST‑tarzı yaklaşık `mu`, `sigma`, `T`, `z`, `p_value_backend` (hangi yöntemin kullanıldığı)
167+
- P-değeri için SciPy varsa `scipy.stats.norm` kullanılır, yoksa `math.erfc` fallback.
168+
- Kullanım örneği:
169+
```python
170+
# python
171+
from patternlab.plugins.linear_complexity import LinearComplexityTest
172+
from patternlab.plugin_api import BytesView
173+
174+
plugin = LinearComplexityTest()
175+
res = plugin.run(BytesView(b'\xff\x00\x0f'), {})
176+
print(res.metrics["linear_complexity"], res.p_value)
177+
```
178+
179+
Bu eklemeler geliştirici rehberi içinde yeni eklentilerin hızlı anlaşılması ve doğru parametrelerle kullanılabilmesi için tasarlanmıştır. Aşağıdaki bölümde (örnek eklenti) orijinal içerik korunmuştur.
101180
## Örnek: Tam Bir Test Eklentisi
102181

103182
Aşağıda proje içinde doğrudan kullanılabilecek minimal, test edilebilir bir TestPlugin örneği bulunmaktadır. Bu dosyayı [`patternlab/plugins/my_test.py`](patternlab/plugins/my_test.py:1) olarak ekleyebilirsiniz.

docs/test-reference.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,82 @@ Linear Complexity (diagnostic)
111111
- NIST SP 800‑22'de linear complexity testindeki gibi L için normalize istatistik ve p-değeri hesaplanabilir; kod mevcut haliyle genelde diagnostic sonuç döndürüyor (p_value=1.0 ile uyumluluk amacıyla).
112112
- SciPy bağımlılığı: yok tipik olarak (algoritma doğrudan bit düzeyinde çalışır).
113113

114+
## Frequency Test within a Block (frequency_within_block.py)
115+
- Dosya: [`patternlab/plugins/frequency_within_block.py`](patternlab/plugins/frequency_within_block.py:1)
116+
- Amaç ve NIST bağlantısı: NIST SP 800‑22'deki "Frequency Test within a Block" yaklaşımına dayanır. Girdi bit dizisini M-boyutlu bloklara ayırıp her bloktaki 1 oranlarının 0.5'ten sapmasını chi-square benzeri bir istatistik ile değerlendirir. Block Frequency ile benzer amaç taşır ancak implementasyon ve parametre seçimi farklılıkları olabilir.
117+
- Parametreler / varsayılanlar:
118+
- `block_size` (int): açıkça verilirse kullanılır (M).
119+
- `default_block_size` (int, default 128): `block_size` yoksa kullanılır.
120+
- `alpha` (float, default 0.01)
121+
- Seçme heuristiği: eğer toplam bit sayısı n % 100 == 0 ise otomatik olarak M = n // 100 seçilebilir.
122+
- Çıktı metrikleri:
123+
- `block_count`, `block_size`, `total_bits`
124+
- `ones_counts` (blok başına 1 sayıları), `proportions` (blok başına 1 oranları)
125+
- `chi_square`
126+
- Kullanım örneği:
127+
```python
128+
# python
129+
from patternlab.plugins.frequency_within_block import FrequencyWithinBlockTest
130+
from patternlab.plugin_api import BytesView
131+
132+
plugin = FrequencyWithinBlockTest()
133+
res = plugin.run(BytesView(b'\xff\x00\xaa'), {"block_size": 8, "alpha": 0.01})
134+
print(res.test_name, res.p_value, res.metrics["chi_square"])
135+
```
136+
137+
## Maurer's Universal Test (maurers_universal.py)
138+
- Dosya: [`patternlab/plugins/maurers_universal.py`](patternlab/plugins/maurers_universal.py:1)
139+
- Amaç ve NIST bağlantısı: NIST SP 800‑22'de tanımlanan Maurer’s Universal Statistical Test ile uyumlu bir uygulamadır. Desen tekrar uzaklıklarının log2 ortalaması üzerinden dizinin sıkılık/karmaşıklık ölçülür.
140+
- Parametreler / varsayılanlar:
141+
- `L` (int, default 6): blok uzunluğu (NIST önerisi 6..16).
142+
- `Q` (int, default 10 * 2**L): başlatma (init) blok sayısı.
143+
- `min_blocks` (int, default Q + 1000): toplam blok sayısı için minimum gereksinim; eksik ise test "skipped" döner.
144+
- `alpha` (float, default 0.01)
145+
- Önemli davranışlar:
146+
- L=6..16 aralığındaki referans ortalama/varyans tablosu kullanılır. Yetersiz veri durumunda `{"status":"skipped", "reason": ...}` döner.
147+
- İşlem blokları Q sonrası K = block_count - Q ile hesaplanır; fn = ortalama log2 mesafe, z ve p-value NIST eşdeğer formüllerine göre hesaplanır.
148+
- Çıktı metrikleri:
149+
- `L`, `blocks` (toplam blok), `init_Q`, `processed_blocks` (K), `fn`, `expected`, `variance`, `z_score`, `total_bits`
150+
- Kullanım örneği:
151+
```python
152+
# python
153+
from patternlab.plugins.maurers_universal import MaurersUniversalTest
154+
from patternlab.plugin_api import BytesView
155+
156+
plugin = MaurersUniversalTest()
157+
res = plugin.run(BytesView(open("test.bin","rb").read()), {"L": 6})
158+
if isinstance(res, dict) and res.get("status") == "skipped":
159+
print("Skipped:", res["reason"])
160+
else:
161+
print(res.test_name, res.p_value, res.metrics["fn"])
162+
```
163+
164+
## Linear Complexity (güncellenmiş)
165+
- Dosya: [`patternlab/plugins/linear_complexity.py`](patternlab/plugins/linear_complexity.py:1)
166+
- Amaç ve NIST bağlantısı: Berlekamp–Massey ile bit dizisinin GF(2) üzerindeki lineer kompleksitesini hesaplar. NIST SP 800‑22'deki linear complexity testine benzer istatistiksel normalize etme ve p-değeri hesaplamaları uygulanır (yaklaşmalar).
167+
- Parametreler / varsayılanlar:
168+
- `alpha` (float, default 0.01)
169+
- Girdi uzunluğu n == 0 ise TestResult içinde error bilgisi döner ve passed=False.
170+
- Hesaplama özeti:
171+
- Berlekamp–Massey algoritması ile L hesaplanır.
172+
- Yaklaşık beklenen değer mu ve varyans sigma NIST-tarzı formüllerden türetilir:
173+
- $$\mu = \frac{n}{2} + \frac{9 + (-1)^{n+1}}{36}$$
174+
- $$\sigma \approx \sqrt{\frac{n}{4}}$$
175+
- Normalize istatistik: $$T = (-1)^n (L - \mu) + \tfrac{2}{9}$$, $$z = T / \sigma$$
176+
- İki taraflı p-değeri SciPy varsa `scipy.stats.norm` ile, yoksa `math.erfc` ile hesaplanır.
177+
- Çıktı metrikleri:
178+
- `linear_complexity` (L), `n`, `mu`, `sigma`, `T`, `z`, `p_value_backend`
179+
- Kullanım örneği:
180+
```python
181+
# python
182+
from patternlab.plugins.linear_complexity import LinearComplexityTest
183+
from patternlab.plugin_api import BytesView
184+
185+
plugin = LinearComplexityTest()
186+
res = plugin.run(BytesView(b'\xff\x00\x0f'), {})
187+
print(res.metrics["linear_complexity"], res.p_value)
188+
```
189+
114190
Binary Matrix Rank
115191
- Dosya: [`patternlab/plugins/binary_matrix_rank.py`](patternlab/plugins/binary_matrix_rank.py:1)
116192
- Amaç: Bit dizisini m×m matrislere ayırıp GF(2) rank dağılımının beklenen dağılıma göre sapmasını test eder.

0 commit comments

Comments
 (0)