oscura 0.3.0__py3-none-any.whl → 0.4.0__py3-none-any.whl
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.
- oscura/__init__.py +1 -7
- oscura/acquisition/__init__.py +147 -0
- oscura/acquisition/file.py +255 -0
- oscura/acquisition/hardware.py +186 -0
- oscura/acquisition/saleae.py +340 -0
- oscura/acquisition/socketcan.py +315 -0
- oscura/acquisition/streaming.py +38 -0
- oscura/acquisition/synthetic.py +229 -0
- oscura/acquisition/visa.py +376 -0
- oscura/analyzers/__init__.py +3 -0
- oscura/analyzers/digital/clock.py +9 -1
- oscura/analyzers/digital/edges.py +1 -1
- oscura/analyzers/digital/timing.py +41 -11
- oscura/analyzers/side_channel/__init__.py +52 -0
- oscura/analyzers/side_channel/power.py +690 -0
- oscura/analyzers/side_channel/timing.py +369 -0
- oscura/analyzers/signal_integrity/sparams.py +1 -1
- oscura/automotive/__init__.py +4 -2
- oscura/automotive/can/patterns.py +3 -1
- oscura/automotive/can/session.py +277 -78
- oscura/automotive/can/state_machine.py +5 -2
- oscura/builders/__init__.py +9 -11
- oscura/builders/signal_builder.py +99 -191
- oscura/core/exceptions.py +5 -1
- oscura/loaders/__init__.py +1 -0
- oscura/loaders/chipwhisperer.py +393 -0
- oscura/loaders/touchstone.py +1 -1
- oscura/session/session.py +54 -46
- oscura/sessions/__init__.py +70 -0
- oscura/sessions/base.py +323 -0
- oscura/sessions/blackbox.py +640 -0
- oscura/sessions/generic.py +189 -0
- {oscura-0.3.0.dist-info → oscura-0.4.0.dist-info}/METADATA +86 -5
- {oscura-0.3.0.dist-info → oscura-0.4.0.dist-info}/RECORD +37 -21
- {oscura-0.3.0.dist-info → oscura-0.4.0.dist-info}/WHEEL +0 -0
- {oscura-0.3.0.dist-info → oscura-0.4.0.dist-info}/entry_points.txt +0 -0
- {oscura-0.3.0.dist-info → oscura-0.4.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"""Generic analysis session implementation.
|
|
2
|
+
|
|
3
|
+
This module provides GenericSession - a concrete implementation of AnalysisSession
|
|
4
|
+
for general-purpose signal analysis. It wraps the existing session.Session class
|
|
5
|
+
to provide the unified AnalysisSession interface while maintaining backward
|
|
6
|
+
compatibility.
|
|
7
|
+
|
|
8
|
+
Example:
|
|
9
|
+
>>> from oscura.sessions import GenericSession
|
|
10
|
+
>>> from oscura.acquisition import FileSource
|
|
11
|
+
>>>
|
|
12
|
+
>>> # Create generic session
|
|
13
|
+
>>> session = GenericSession(name="Debug Session")
|
|
14
|
+
>>> session.add_recording("capture1", FileSource("signal1.wfm"))
|
|
15
|
+
>>> session.add_recording("capture2", FileSource("signal2.wfm"))
|
|
16
|
+
>>>
|
|
17
|
+
>>> # Compare recordings
|
|
18
|
+
>>> diff = session.compare("capture1", "capture2")
|
|
19
|
+
>>> print(f"Similarity: {diff.similarity_score:.2%}")
|
|
20
|
+
>>>
|
|
21
|
+
>>> # Analyze
|
|
22
|
+
>>> results = session.analyze() # Generic waveform analysis
|
|
23
|
+
|
|
24
|
+
Pattern:
|
|
25
|
+
GenericSession is the default session type for non-domain-specific
|
|
26
|
+
analysis. Use domain-specific sessions (CANSession, SerialSession, etc.)
|
|
27
|
+
when working within a specific protocol or analysis domain.
|
|
28
|
+
|
|
29
|
+
Migration:
|
|
30
|
+
The existing oscura.session.Session class continues to work unchanged.
|
|
31
|
+
GenericSession provides the new AnalysisSession interface while
|
|
32
|
+
delegating to the existing Session implementation internally.
|
|
33
|
+
|
|
34
|
+
References:
|
|
35
|
+
Architecture Plan Phase 0.3: AnalysisSession Generic Implementation
|
|
36
|
+
src/oscura/session/session.py: Legacy Session class
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
from __future__ import annotations
|
|
40
|
+
|
|
41
|
+
from pathlib import Path
|
|
42
|
+
from typing import Any
|
|
43
|
+
|
|
44
|
+
from oscura.sessions.base import AnalysisSession
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class GenericSession(AnalysisSession):
|
|
48
|
+
"""Generic analysis session for general-purpose signal analysis.
|
|
49
|
+
|
|
50
|
+
Provides the unified AnalysisSession interface for non-domain-specific
|
|
51
|
+
analysis. This is the default session type when you don't need CAN,
|
|
52
|
+
Serial, or other specialized functionality.
|
|
53
|
+
|
|
54
|
+
Example:
|
|
55
|
+
>>> from oscura.sessions import GenericSession
|
|
56
|
+
>>> from oscura.acquisition import FileSource
|
|
57
|
+
>>>
|
|
58
|
+
>>> session = GenericSession()
|
|
59
|
+
>>> session.add_recording("test1", FileSource("capture1.wfm"))
|
|
60
|
+
>>> session.add_recording("test2", FileSource("capture2.wfm"))
|
|
61
|
+
>>>
|
|
62
|
+
>>> # Compare traces
|
|
63
|
+
>>> diff = session.compare("test1", "test2")
|
|
64
|
+
>>> print(f"Changed: {diff.changed_bytes} samples")
|
|
65
|
+
>>>
|
|
66
|
+
>>> # Generic analysis
|
|
67
|
+
>>> results = session.analyze()
|
|
68
|
+
>>> print(results["num_recordings"])
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
def analyze(self) -> dict[str, Any]:
|
|
72
|
+
"""Perform generic waveform analysis on all recordings.
|
|
73
|
+
|
|
74
|
+
Analyzes all loaded recordings and provides summary statistics,
|
|
75
|
+
basic waveform measurements, and comparison results.
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
Dictionary with analysis results:
|
|
79
|
+
- num_recordings: Number of recordings
|
|
80
|
+
- recordings: List of recording names
|
|
81
|
+
- summary: Summary statistics for each recording
|
|
82
|
+
|
|
83
|
+
Example:
|
|
84
|
+
>>> session = GenericSession()
|
|
85
|
+
>>> session.add_recording("sig", FileSource("capture.wfm"))
|
|
86
|
+
>>> results = session.analyze()
|
|
87
|
+
>>> print(results["summary"]["sig"]["mean"])
|
|
88
|
+
"""
|
|
89
|
+
import numpy as np
|
|
90
|
+
|
|
91
|
+
results: dict[str, Any] = {
|
|
92
|
+
"num_recordings": len(self.recordings),
|
|
93
|
+
"recordings": self.list_recordings(),
|
|
94
|
+
"summary": {},
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
# Analyze each recording
|
|
98
|
+
from oscura.core.types import IQTrace
|
|
99
|
+
|
|
100
|
+
for name in self.list_recordings():
|
|
101
|
+
trace = self.get_recording(name)
|
|
102
|
+
|
|
103
|
+
# Handle IQTrace separately
|
|
104
|
+
if isinstance(trace, IQTrace):
|
|
105
|
+
raise TypeError("IQTrace analysis not yet supported in GenericSession")
|
|
106
|
+
|
|
107
|
+
# Basic statistics
|
|
108
|
+
summary = {
|
|
109
|
+
"num_samples": len(trace.data),
|
|
110
|
+
"sample_rate": trace.metadata.sample_rate,
|
|
111
|
+
"duration": len(trace.data) / trace.metadata.sample_rate,
|
|
112
|
+
"mean": float(np.mean(trace.data)),
|
|
113
|
+
"std": float(np.std(trace.data)),
|
|
114
|
+
"min": float(np.min(trace.data)),
|
|
115
|
+
"max": float(np.max(trace.data)),
|
|
116
|
+
"rms": float(np.sqrt(np.mean(trace.data**2))),
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
results["summary"][name] = summary
|
|
120
|
+
|
|
121
|
+
# If multiple recordings, add comparisons
|
|
122
|
+
if len(self.recordings) >= 2:
|
|
123
|
+
results["comparisons"] = {}
|
|
124
|
+
names = self.list_recordings()
|
|
125
|
+
for i in range(len(names)):
|
|
126
|
+
for j in range(i + 1, len(names)):
|
|
127
|
+
comparison_key = f"{names[i]}_vs_{names[j]}"
|
|
128
|
+
comp_result = self.compare(names[i], names[j])
|
|
129
|
+
results["comparisons"][comparison_key] = {
|
|
130
|
+
"similarity": comp_result.similarity_score,
|
|
131
|
+
"changed_samples": comp_result.changed_bytes,
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return results
|
|
135
|
+
|
|
136
|
+
def export_results(self, format: str, path: str | Path) -> None:
|
|
137
|
+
"""Export analysis results to file.
|
|
138
|
+
|
|
139
|
+
Extends base export with additional formats for generic analysis.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
format: Export format ("report", "json", "csv").
|
|
143
|
+
path: Output file path.
|
|
144
|
+
|
|
145
|
+
Raises:
|
|
146
|
+
ValueError: If format not supported.
|
|
147
|
+
|
|
148
|
+
Example:
|
|
149
|
+
>>> session.export_results("report", "analysis.txt")
|
|
150
|
+
>>> session.export_results("json", "results.json")
|
|
151
|
+
"""
|
|
152
|
+
path = Path(path)
|
|
153
|
+
|
|
154
|
+
if format == "json":
|
|
155
|
+
# Export as JSON
|
|
156
|
+
import json
|
|
157
|
+
|
|
158
|
+
results = self.analyze()
|
|
159
|
+
|
|
160
|
+
with open(path, "w") as f:
|
|
161
|
+
json.dump(results, f, indent=2)
|
|
162
|
+
|
|
163
|
+
elif format == "csv":
|
|
164
|
+
# Export summary as CSV
|
|
165
|
+
import csv
|
|
166
|
+
|
|
167
|
+
results = self.analyze()
|
|
168
|
+
|
|
169
|
+
with open(path, "w", newline="") as f:
|
|
170
|
+
if not results["summary"]:
|
|
171
|
+
return # No data to export
|
|
172
|
+
|
|
173
|
+
# Get fieldnames from first recording
|
|
174
|
+
first_rec = next(iter(results["summary"].values()))
|
|
175
|
+
fieldnames = ["recording"] + list(first_rec.keys())
|
|
176
|
+
|
|
177
|
+
writer = csv.DictWriter(f, fieldnames=fieldnames)
|
|
178
|
+
writer.writeheader()
|
|
179
|
+
|
|
180
|
+
for name, summary in results["summary"].items():
|
|
181
|
+
row = {"recording": name, **summary}
|
|
182
|
+
writer.writerow(row)
|
|
183
|
+
|
|
184
|
+
else:
|
|
185
|
+
# Fall back to base implementation (text report)
|
|
186
|
+
super().export_results(format, path)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
__all__ = ["GenericSession"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: oscura
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Unified hardware reverse engineering framework. Extract all information from any system through signals and data. Unknown protocol discovery, state machine extraction, CRC recovery, security analysis. 16+ protocols, IEEE-compliant measurements.
|
|
5
5
|
Project-URL: Homepage, https://github.com/oscura-re/oscura
|
|
6
6
|
Project-URL: Documentation, https://github.com/oscura-re/oscura/tree/main/docs
|
|
@@ -57,6 +57,8 @@ Requires-Dist: pytest-timeout<3.0.0,>=2.3.0; extra == 'all'
|
|
|
57
57
|
Requires-Dist: pytest<10.0.0,>=8.0; extra == 'all'
|
|
58
58
|
Requires-Dist: python-can<5.0.0,>=4.4.0; extra == 'all'
|
|
59
59
|
Requires-Dist: python-pptx<1.0.0,>=0.6.21; extra == 'all'
|
|
60
|
+
Requires-Dist: pyvisa-py<1.0.0,>=0.7.0; extra == 'all'
|
|
61
|
+
Requires-Dist: pyvisa<2.0.0,>=1.13.0; extra == 'all'
|
|
60
62
|
Requires-Dist: pywavelets<2.0.0,>=1.0.0; extra == 'all'
|
|
61
63
|
Requires-Dist: reportlab<6.0.0,>=4.4.7; extra == 'all'
|
|
62
64
|
Requires-Dist: rigolwfm<2.0.0,>=1.0.0; extra == 'all'
|
|
@@ -82,6 +84,9 @@ Requires-Dist: pytest-timeout<3.0.0,>=2.3.0; extra == 'dev'
|
|
|
82
84
|
Requires-Dist: pytest<10.0.0,>=8.0; extra == 'dev'
|
|
83
85
|
Requires-Dist: types-pyyaml<7.0.0,>=6.0; extra == 'dev'
|
|
84
86
|
Requires-Dist: yamllint<2.0.0,>=1.35; extra == 'dev'
|
|
87
|
+
Provides-Extra: hardware
|
|
88
|
+
Requires-Dist: pyvisa-py<1.0.0,>=0.7.0; extra == 'hardware'
|
|
89
|
+
Requires-Dist: pyvisa<2.0.0,>=1.13.0; extra == 'hardware'
|
|
85
90
|
Provides-Extra: hdf5
|
|
86
91
|
Requires-Dist: h5py<4.0.0,>=3.0.0; extra == 'hdf5'
|
|
87
92
|
Provides-Extra: jupyter
|
|
@@ -127,11 +132,15 @@ Description-Content-Type: text/markdown
|
|
|
127
132
|
|
|
128
133
|
Oscura is a hardware reverse engineering framework for security researchers, right-to-repair advocates, defense analysts, and commercial intelligence teams. From oscilloscope captures to complete system understanding.
|
|
129
134
|
|
|
130
|
-
**Reverse Engineering**: Unknown protocol discovery • State machine extraction • CRC/checksum recovery • Proprietary device replication • Security vulnerability analysis
|
|
135
|
+
**Reverse Engineering**: Unknown protocol discovery • State machine extraction • CRC/checksum recovery • Proprietary device replication • Security vulnerability analysis • Black-box protocol analysis
|
|
131
136
|
|
|
132
|
-
**Signal Analysis**: IEEE-compliant measurements (181/1241/1459/2414) • Comprehensive protocol decoding (16+ protocols) • Spectral analysis • Timing characterization
|
|
137
|
+
**Signal Analysis**: IEEE-compliant measurements (181/1241/1459/2414) • Comprehensive protocol decoding (16+ protocols) • Spectral analysis • Timing characterization • Side-channel analysis (DPA/CPA/timing attacks)
|
|
133
138
|
|
|
134
|
-
**
|
|
139
|
+
**Unified Acquisition**: File-based • Hardware sources (SocketCAN, Saleae, PyVISA - Phase 2) • Synthetic generation • Polymorphic Source protocol
|
|
140
|
+
|
|
141
|
+
**Interactive Sessions**: Domain-specific analysis sessions • BlackBoxSession for protocol RE • Differential analysis • Field hypothesis generation • Protocol specification export
|
|
142
|
+
|
|
143
|
+
**Built For**: Exploitation • Replication • Defense analysis • Commercial intelligence • Right-to-repair • Cryptographic research
|
|
135
144
|
|
|
136
145
|
---
|
|
137
146
|
|
|
@@ -155,6 +164,8 @@ cd oscura
|
|
|
155
164
|
|
|
156
165
|
## Quick Start
|
|
157
166
|
|
|
167
|
+
### Signal Analysis
|
|
168
|
+
|
|
158
169
|
```python
|
|
159
170
|
import oscura as osc
|
|
160
171
|
|
|
@@ -171,6 +182,57 @@ decoder = UARTDecoder(baud_rate=115200)
|
|
|
171
182
|
messages = decoder.decode(trace)
|
|
172
183
|
```
|
|
173
184
|
|
|
185
|
+
### Black-Box Protocol Reverse Engineering
|
|
186
|
+
|
|
187
|
+
```python
|
|
188
|
+
from oscura.sessions import BlackBoxSession
|
|
189
|
+
from oscura.acquisition import FileSource
|
|
190
|
+
|
|
191
|
+
# Create analysis session
|
|
192
|
+
session = BlackBoxSession(name="IoT Device RE")
|
|
193
|
+
|
|
194
|
+
# Add recordings from different stimuli
|
|
195
|
+
session.add_recording("idle", FileSource("idle.bin"))
|
|
196
|
+
session.add_recording("button_press", FileSource("button.bin"))
|
|
197
|
+
|
|
198
|
+
# Differential analysis
|
|
199
|
+
diff = session.compare("idle", "button_press")
|
|
200
|
+
print(f"Changed bytes: {diff.changed_bytes}")
|
|
201
|
+
|
|
202
|
+
# Generate protocol specification
|
|
203
|
+
spec = session.generate_protocol_spec()
|
|
204
|
+
print(f"Detected {len(spec['fields'])} protocol fields")
|
|
205
|
+
|
|
206
|
+
# Export Wireshark dissector
|
|
207
|
+
session.export_results("dissector", "protocol.lua")
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### CAN Protocol Analysis
|
|
211
|
+
|
|
212
|
+
```python
|
|
213
|
+
from oscura.automotive.can import CANSession
|
|
214
|
+
from oscura.acquisition import FileSource
|
|
215
|
+
|
|
216
|
+
# Create session
|
|
217
|
+
session = CANSession(name="Vehicle Analysis")
|
|
218
|
+
|
|
219
|
+
# Add recordings from CAN bus captures
|
|
220
|
+
session.add_recording("idle", FileSource("idle.blf"))
|
|
221
|
+
session.add_recording("accelerate", FileSource("accelerate.blf"))
|
|
222
|
+
|
|
223
|
+
# Analyze traffic
|
|
224
|
+
analysis = session.analyze()
|
|
225
|
+
print(f"Messages: {analysis['inventory']['total_messages']}")
|
|
226
|
+
print(f"Unique IDs: {len(analysis['inventory']['message_ids'])}")
|
|
227
|
+
|
|
228
|
+
# Compare recordings
|
|
229
|
+
diff = session.compare("idle", "accelerate")
|
|
230
|
+
print(f"Changed IDs: {len(diff.details['changed_ids'])}")
|
|
231
|
+
|
|
232
|
+
# Export DBC file
|
|
233
|
+
session.export_dbc("vehicle.dbc")
|
|
234
|
+
```
|
|
235
|
+
|
|
174
236
|
---
|
|
175
237
|
|
|
176
238
|
## Learn by Example
|
|
@@ -285,9 +347,28 @@ uv sync --all-extras
|
|
|
285
347
|
|
|
286
348
|
## Documentation
|
|
287
349
|
|
|
288
|
-
|
|
350
|
+
### Getting Started
|
|
351
|
+
|
|
352
|
+
- **[Quick Start Guide](docs/guides/quick-start.md)** - Begin here
|
|
353
|
+
- **[Demos](demos/)** - Working examples for every feature
|
|
354
|
+
- **[Migration Guide](docs/migration/v0-to-v1.md)** - Upgrade from older versions
|
|
355
|
+
|
|
356
|
+
### User Guides
|
|
357
|
+
|
|
358
|
+
- **[Black-Box Protocol Analysis](docs/guides/blackbox-analysis.md)** - Unknown protocol reverse engineering
|
|
359
|
+
- **[Hardware Acquisition](docs/guides/hardware-acquisition.md)** - Direct hardware integration (Phase 2)
|
|
360
|
+
- **[Side-Channel Analysis](docs/guides/side-channel-analysis.md)** - Power/timing/EM attacks
|
|
361
|
+
- **[Workflows](docs/guides/workflows.md)** - Complete analysis workflows
|
|
362
|
+
|
|
363
|
+
### API Reference
|
|
364
|
+
|
|
289
365
|
- **[API Reference](docs/api/)** - Complete API documentation
|
|
366
|
+
- **[Session Management](docs/api/session-management.md)** - Interactive analysis sessions
|
|
290
367
|
- **[CLI Reference](docs/cli.md)** - Command line usage
|
|
368
|
+
|
|
369
|
+
### Development
|
|
370
|
+
|
|
371
|
+
- **[Architecture](docs/architecture/)** - Design principles and patterns
|
|
291
372
|
- **[Testing Guide](docs/testing/)** - Test suite architecture
|
|
292
373
|
- **[CHANGELOG](CHANGELOG.md)** - Version history
|
|
293
374
|
|
|
@@ -1,21 +1,29 @@
|
|
|
1
|
-
oscura/__init__.py,sha256=
|
|
1
|
+
oscura/__init__.py,sha256=IvoCA0vsnvD_yPvwtMWi4qX4q5FhsY7uiQFKghU85wQ,18313
|
|
2
2
|
oscura/__main__.py,sha256=l1rnaD-tpI1W3cp1VHGhSdq9NDqw6Gxjf_gnqXf-zzE,11786
|
|
3
3
|
oscura/convenience.py,sha256=o8f1Im8WpakGXRz8D4bV-XSNkzpgnVjsyVxnaxZ-dg4,14612
|
|
4
4
|
oscura/exceptions.py,sha256=Ywyi7IhEG9XmbceCxAcLGKAddAOdP9Ph1ZT2NioMQCU,1606
|
|
5
5
|
oscura/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
-
oscura/
|
|
6
|
+
oscura/acquisition/__init__.py,sha256=JAQt5FXsGiKPkqHuyWJoGVnGf1ElSRXqGxJdjcDLLho,4834
|
|
7
|
+
oscura/acquisition/file.py,sha256=nrOWunIGxUaF-B946ZKwME4f-8jbWhp3z3BadvCuUw0,8426
|
|
8
|
+
oscura/acquisition/hardware.py,sha256=-BrIi0aLoVBTVIh5gdTvYY5OrDPIv06wxrx28GJw7j8,6598
|
|
9
|
+
oscura/acquisition/saleae.py,sha256=D61v7_k-zZzor-jiYHFwjd-u8VFo93spQ3_m7Jhk_Dc,11438
|
|
10
|
+
oscura/acquisition/socketcan.py,sha256=ifs7Chv-pk4LLYTvfe4-9xS2-vbe4efqVd1azIYLexE,10575
|
|
11
|
+
oscura/acquisition/streaming.py,sha256=P57M8S33DGIeoDUSBHm3bzoKfNIDZkYE4dODPNeJy78,1191
|
|
12
|
+
oscura/acquisition/synthetic.py,sha256=VXhz5W0gzwE3_Ezo7hADwfFoTV5pOixpPCVNPMngNAo,7823
|
|
13
|
+
oscura/acquisition/visa.py,sha256=phUwdlbphvNhSCaRgIXuPb8YDP0jR4eqY-OuJXCgRCo,12272
|
|
14
|
+
oscura/analyzers/__init__.py,sha256=LE-KFYoVePYsiPIy2NDNB2OrzbtqYezdCu9xqqPxgrY,985
|
|
7
15
|
oscura/analyzers/measurements.py,sha256=ng5Qt2jyAvfKw3JQbJY_JNUqAOJEZwPo3UWa0xSg5Xk,697
|
|
8
16
|
oscura/analyzers/validation.py,sha256=vHSKmLThwcU0j5Dat9QPbWImw_dqUGaZk_Ul6XbJ958,20376
|
|
9
17
|
oscura/analyzers/digital/__init__.py,sha256=CrZxLveYI-nZ7INCZg-4zp8UP_uQRpMmX2vljzudJ6s,4228
|
|
10
18
|
oscura/analyzers/digital/bus.py,sha256=Wf3QUKNSxzXaWItR1rdf32kELayywrIg0TC-OhKEub0,22717
|
|
11
|
-
oscura/analyzers/digital/clock.py,sha256=
|
|
19
|
+
oscura/analyzers/digital/clock.py,sha256=2WihQyf2fUlKTDAOKrhQSStiuUw711CvR6bMbkiliAc,26088
|
|
12
20
|
oscura/analyzers/digital/correlation.py,sha256=_D-pmymVU1rTemSUfg_MklXCo03VkfAFcxSTLAV6jcY,23689
|
|
13
|
-
oscura/analyzers/digital/edges.py,sha256
|
|
21
|
+
oscura/analyzers/digital/edges.py,sha256=-Mlyh_SFkqs7L2n11bfYlv8bHD-jrfV6UByhXS1DLp0,20018
|
|
14
22
|
oscura/analyzers/digital/extraction.py,sha256=wBOPZi3H1llCHsq36txz_jkEO--Sj6pbsxPZXXGk5_c,12144
|
|
15
23
|
oscura/analyzers/digital/quality.py,sha256=bMXpmAhs15tjyiWW0Ao5aZcK_8AvEKyo_E3rtxDrFlo,27413
|
|
16
24
|
oscura/analyzers/digital/signal_quality.py,sha256=Ssb1MkUfqjiENJJFOslkTX8Ef6C65HFCM_Ra20Bvp4k,30130
|
|
17
25
|
oscura/analyzers/digital/thresholds.py,sha256=CrGgO1rtzkUOnYb40UT3_uD_0qVA853lGL2WNL95qv4,22428
|
|
18
|
-
oscura/analyzers/digital/timing.py,sha256=
|
|
26
|
+
oscura/analyzers/digital/timing.py,sha256=eOo1jk-FfUd3tkqDndPTz-JO5tnfW9w4dEI-klgW-QU,34862
|
|
19
27
|
oscura/analyzers/eye/__init__.py,sha256=SRW0Ir-1RWLwoaenk6FZhGOIWPkuhevYTPt_-8thPw0,974
|
|
20
28
|
oscura/analyzers/eye/diagram.py,sha256=T3QwuZ3nvlHzSkmjp47ariRlt3FnfsK6yh3WsPszhmI,13307
|
|
21
29
|
oscura/analyzers/eye/metrics.py,sha256=QDwtMxiBPSXbUCyFnTiAgWllbVCrcI4xEo6teZc3Cm8,17210
|
|
@@ -65,10 +73,13 @@ oscura/analyzers/protocols/spi.py,sha256=gl0LVpZVI22tr7h5D1OAdDtlY_krb7CdNCNP10D
|
|
|
65
73
|
oscura/analyzers/protocols/swd.py,sha256=NAInX2bZyZFCM03CLjjxraYTV7cCGOzcl_OEXU21qZE,10155
|
|
66
74
|
oscura/analyzers/protocols/uart.py,sha256=6bf9EFHjHjkSeTxBq8b6GRlp1xWlBh65HuUcmWxWAEA,12188
|
|
67
75
|
oscura/analyzers/protocols/usb.py,sha256=jBjmqfqnwys6Zvd7Ku-zZRNlOVZB7xKPmocM2NynGg4,14541
|
|
76
|
+
oscura/analyzers/side_channel/__init__.py,sha256=XGD7uvvL6Mf2FO6VU5fbBTtfARA-WGXa-rvHAbjNBxc,1361
|
|
77
|
+
oscura/analyzers/side_channel/power.py,sha256=036A5ygwGVa5jqOFoOWm1bV-x63FrztyCS8cIEc68wo,17995
|
|
78
|
+
oscura/analyzers/side_channel/timing.py,sha256=loNKa5dgWu9sFTsKCNt087vqYCjBIVVQn3lzQBb3pQc,12128
|
|
68
79
|
oscura/analyzers/signal_integrity/__init__.py,sha256=RXt5K79WFsy3NvJuNjVxWCf0r6Z8kOIBvJSBBw4X2Y8,1410
|
|
69
80
|
oscura/analyzers/signal_integrity/embedding.py,sha256=LV-8TwSfCfFe-TavXXKOw7eIeigxkvKeJktyQiqcZXg,8036
|
|
70
81
|
oscura/analyzers/signal_integrity/equalization.py,sha256=cVomry8n-U5pS8F2LKuEdZBwmi1wfbQo2vyWettn2A0,9906
|
|
71
|
-
oscura/analyzers/signal_integrity/sparams.py,sha256=
|
|
82
|
+
oscura/analyzers/signal_integrity/sparams.py,sha256=TK4o-IOfnVVbfycBgJ0XhTgBYxHcBNdFbmC9TXhfMJs,8303
|
|
72
83
|
oscura/analyzers/spectral/__init__.py,sha256=YeUKiUOtN3LkWjPmjiG55OWMldSaBJ4BE4OSem7sdm0,850
|
|
73
84
|
oscura/analyzers/spectral/chunked.py,sha256=KS1Jtv_o9vripQVH3CeaTBx-Lq4AAU-eOXF9_En3rc4,8551
|
|
74
85
|
oscura/analyzers/spectral/chunked_fft.py,sha256=VKslVgXv7xuSuVVx-Fk2eh255AG6D0D-hQFzAbz1Hk4,18593
|
|
@@ -99,7 +110,7 @@ oscura/api/fluent.py,sha256=Bvo1yVqqn3nmVWaoPv4C-YtYszBhHmdW8m5NdyhWEEo,15373
|
|
|
99
110
|
oscura/api/operators.py,sha256=To4PZUrwInD43T7i2Sy8YD04eLoRsmrD6XYePuExUX8,13853
|
|
100
111
|
oscura/api/optimization.py,sha256=5R6rPByVsyxla6oq4SjxjxEp9Uplog4owzsIuFcVoR0,11875
|
|
101
112
|
oscura/api/profiling.py,sha256=vkYinleXrznWdd0OT5zIJN_PW289GQE_ODmR9DaCcQ0,10567
|
|
102
|
-
oscura/automotive/__init__.py,sha256=
|
|
113
|
+
oscura/automotive/__init__.py,sha256=3Wt44lFmx_zzyC1_IeukEpEnUagyM8TT0mWUnTpXb4s,2538
|
|
103
114
|
oscura/automotive/visualization.py,sha256=2ILQjzNwCwj6zZ4MEsBS-QLwYFKMO0_0xDsbv3gEXu0,10692
|
|
104
115
|
oscura/automotive/can/__init__.py,sha256=0WCLgE6juqQF_mTO716tWzfziOcM6cjshdb957G0edw,1283
|
|
105
116
|
oscura/automotive/can/analysis.py,sha256=0z6MycxuJGusqDQhYEpHnGRmDw3OMf5yDbS8zI6GJO0,11251
|
|
@@ -108,9 +119,9 @@ oscura/automotive/can/correlation.py,sha256=B7MXSz_uzce-dSkwON4ssmFzC53hYc6GupZW
|
|
|
108
119
|
oscura/automotive/can/discovery.py,sha256=E4Z-zc8cOP_yUklhVp2tBLOIw2I9KU4mLoSb37VsgTk,11237
|
|
109
120
|
oscura/automotive/can/message_wrapper.py,sha256=xCyHLMvvTiloifWXELoeuN6Qz_vrLL8iPjxZG1FvJYY,12640
|
|
110
121
|
oscura/automotive/can/models.py,sha256=fGnCt8FBKURKAz295s2duUas--w2rVfJpMEZ4O9uPvA,12046
|
|
111
|
-
oscura/automotive/can/patterns.py,sha256=
|
|
112
|
-
oscura/automotive/can/session.py,sha256=
|
|
113
|
-
oscura/automotive/can/state_machine.py,sha256=
|
|
122
|
+
oscura/automotive/can/patterns.py,sha256=XkiBnxaL20Zbpt9aK7dS8BGXQtbNe8PoyTyZNsj-BLY,13960
|
|
123
|
+
oscura/automotive/can/session.py,sha256=bLbDuKw2uuGvIr25E0njYJGWw1urRVhWVMckVUL2EI4,24577
|
|
124
|
+
oscura/automotive/can/state_machine.py,sha256=yeHwydg5RegCPg_zvzS7lLZX-JfBdfMySUcNgMszuIY,10407
|
|
114
125
|
oscura/automotive/can/stimulus_response.py,sha256=y_oN297KypsFewjM6kvjGII0-7Ubpz2RZBPr8pjW-Gc,16543
|
|
115
126
|
oscura/automotive/dbc/__init__.py,sha256=7s36h4LQrJKKkO3ICHeuVCoYVx8jGnHT_wKcJgOsQFQ,380
|
|
116
127
|
oscura/automotive/dbc/generator.py,sha256=EqJKJikAK2Neaff2H9AGb8ZnseE8m4lFAFRMXEIwjsY,5616
|
|
@@ -138,8 +149,8 @@ oscura/batch/aggregate.py,sha256=NBc1RmSGbSRUdpuZG_3wy-vSkGlegGRSj_6WqPqhTkM,105
|
|
|
138
149
|
oscura/batch/analyze.py,sha256=RfRJQ9w9rlutDlT9nTdqSCswi9FxAsznYbCN51Cx2-Y,4891
|
|
139
150
|
oscura/batch/logging.py,sha256=ay8BxwBfH75k5qgs68gI1LdAjPJQg31ZtBxwmWs2XIo,15502
|
|
140
151
|
oscura/batch/metrics.py,sha256=KrY9R0fKttVSW7wL3ra3A4XHVfAeUaLeoM0BtU3GEWI,17312
|
|
141
|
-
oscura/builders/__init__.py,sha256=
|
|
142
|
-
oscura/builders/signal_builder.py,sha256=
|
|
152
|
+
oscura/builders/__init__.py,sha256=7ryrfaFlT4zAh5zKr76LLQDionMFsPv57E_1OlxrkE0,1326
|
|
153
|
+
oscura/builders/signal_builder.py,sha256=nH7AK6YJZZ_KoDcqL3zsxCFwgBQNFieP1k_fChnD4EU,33099
|
|
143
154
|
oscura/cli/__init__.py,sha256=OsdCTexpFCKn-o7FPnwTEAZE52E2s-NbXwpADUOfhDM,275
|
|
144
155
|
oscura/cli/batch.py,sha256=6WkdQF5G03cwCGxfErqr-nq2llOXJqLrfk3u2agUlXY,10773
|
|
145
156
|
oscura/cli/characterize.py,sha256=yMAm4Ji_Dq4Hml3PeDftoUFq60z1BpU_6O7HJ9dUDtc,8898
|
|
@@ -185,7 +196,7 @@ oscura/core/correlation.py,sha256=3kG-scCs7Lv3uYJhvGYbnSyCsf9gQOqX9hnRTsZjAII,64
|
|
|
185
196
|
oscura/core/cross_domain.py,sha256=ZGJGieFpLEMTHEeQ8GFZnNZL0WgKLW_fn7joEptovpE,16118
|
|
186
197
|
oscura/core/debug.py,sha256=1fz5Mwx6dcMXwsGNQMhPCVduAf2ZTSGSvvwjpqIS3Cc,8160
|
|
187
198
|
oscura/core/edge_cases.py,sha256=-z95foSBKZb3V2DhGQSw1A2VaVOGRBdhMfxDooWbLhg,16367
|
|
188
|
-
oscura/core/exceptions.py,sha256=
|
|
199
|
+
oscura/core/exceptions.py,sha256=VOvd6iY4SQWz_fPx9EgwdbaIHpqydyFAou8SeZa7w48,17691
|
|
189
200
|
oscura/core/gpu_backend.py,sha256=U7DoPKHltlGNTFk6cOhpuVUC5VuglahbBRu1jZ83nDE,17700
|
|
190
201
|
oscura/core/lazy.py,sha256=XwXPznvfpgfJqRvONO2YcgLE9IxekhHLQboiLm3a2jw,26302
|
|
191
202
|
oscura/core/log_query.py,sha256=qV7NrZH3W6Xq1BEsEIc6Z4ZW8k3vi6U16Br23tSynhk,17051
|
|
@@ -289,8 +300,9 @@ oscura/integrations/llm.py,sha256=sPt58GZYW6G4rkwX4956RP-FsFNDXCffyiPlBuah6Y4,58
|
|
|
289
300
|
oscura/jupyter/__init__.py,sha256=L5un2-sVNGP46rzJ7e3qrJOyXmhj2BkhLc7DGQzSLj0,726
|
|
290
301
|
oscura/jupyter/display.py,sha256=HuLg5NEIKAGEZe_3EmABaRkTzLAfdAm6VTBw9LCl030,8597
|
|
291
302
|
oscura/jupyter/magic.py,sha256=O1m9N6I5nMUKhCnNANiOdr2pouQxI9oRIcLeRNtrdTc,9953
|
|
292
|
-
oscura/loaders/__init__.py,sha256=
|
|
303
|
+
oscura/loaders/__init__.py,sha256=JKlIsEY0vKEtnXAccgQ6SJMkWYRm9ijM13SSPaqQQJg,16870
|
|
293
304
|
oscura/loaders/binary.py,sha256=Y5j0jaDggSmhFRZvGHT2Fph2dvhTWsqoYWwkOHIBug4,1875
|
|
305
|
+
oscura/loaders/chipwhisperer.py,sha256=vUsmt6Pamybivp6cqqxe70QUlNrVPdQDn-OS5wEdqxo,12049
|
|
294
306
|
oscura/loaders/configurable.py,sha256=dJKv3nFSgmWe22ZNB1kTZZyIWgiMhWTf8ZU-SNahefk,41267
|
|
295
307
|
oscura/loaders/csv.py,sha256=hjToCQkXQEMUCOSBTf3a1d4AAsntvxYbW_jiccQ9JaM,918
|
|
296
308
|
oscura/loaders/csv_loader.py,sha256=Y4MOJQ-95tZsi9hDdu9ru1vTJQyGtGxkhV7RUqGBLWg,14252
|
|
@@ -305,7 +317,7 @@ oscura/loaders/rigol.py,sha256=nwf5aNpH0bWerDgneUpLNlDQfouQ9E_PChv6vG8GLTA,9238
|
|
|
305
317
|
oscura/loaders/sigrok.py,sha256=puyj357BPiJpzNB-hcv6ofp6DZFEnOv_usdi-_zs6Co,10250
|
|
306
318
|
oscura/loaders/tdms.py,sha256=QngrFLJTpctfqcCtv2x3PJmNwfIeWgyug97N_xSdaMA,10483
|
|
307
319
|
oscura/loaders/tektronix.py,sha256=rLqTefIwGCCmkpUwflEJMuKSfGG1qX_pAFF7Kk0j6-I,24069
|
|
308
|
-
oscura/loaders/touchstone.py,sha256
|
|
320
|
+
oscura/loaders/touchstone.py,sha256=HdrpVsyHACSMD8DR86iCI5cj9vdXGXbpADNkjaQRUng,6179
|
|
309
321
|
oscura/loaders/validation.py,sha256=JA_vVYQJB4gC9KFKa2lsGV5D-_agmIjP9kE_dXpv4Wk,17835
|
|
310
322
|
oscura/loaders/vcd.py,sha256=YtRqU6AEkZjZhNnyNOfgBsxZ8rueB5pALrYIoiRYHQ8,13662
|
|
311
323
|
oscura/loaders/wav.py,sha256=UYPc1A1ZRuw5zC7XmBdEqjZpsi2QvSW1noNmXZqpy2k,7251
|
|
@@ -393,7 +405,11 @@ oscura/search/pattern.py,sha256=pqCtlFDKZwms1LrX64Halt25EQAI1VKr3X_6W4XQ_xI,5735
|
|
|
393
405
|
oscura/session/__init__.py,sha256=LAeHbROHU-OBSep1NWffhhcOxVuK30hoKnYgzBsnmn4,926
|
|
394
406
|
oscura/session/annotations.py,sha256=btHVzA6CedrqVI-c_uFVi_lo7-NByxBLTDHoXWYtY08,8713
|
|
395
407
|
oscura/session/history.py,sha256=3YAMhON7wlzNdR03HpGSYWJEuxBsrYeYq19YALc8k8M,9578
|
|
396
|
-
oscura/session/session.py,sha256=
|
|
408
|
+
oscura/session/session.py,sha256=MWx2cE_ZtyWwl5v8QR_X2MGEBn-TAaFftwKNyZktwIU,16321
|
|
409
|
+
oscura/sessions/__init__.py,sha256=BCmLuo95CfyutHrjEFdWSKRDzKKpDGVMcFi3989HiFA,2371
|
|
410
|
+
oscura/sessions/base.py,sha256=S2ka5o01w1YVBHH59EV64tmW9fXErfNuG2zu9g13-t8,10820
|
|
411
|
+
oscura/sessions/blackbox.py,sha256=CyYA6o7d9pMSR6rsbUOQYq6lBSfUUq-ivtr1QKUppdU,22176
|
|
412
|
+
oscura/sessions/generic.py,sha256=hqwhGO_DT3rS0EOKhLtcebJPu81PPLfHSLH1qVmAWj0,6642
|
|
397
413
|
oscura/streaming/__init__.py,sha256=uJKpXU6-uBW1lWqh8_8WNzUKSLhMYzxrJstsNMDLVcM,959
|
|
398
414
|
oscura/streaming/chunked.py,sha256=tWK7m_fHJVJKGq2y6I3RRfioUER2ObMUDPvJ78K73d0,19487
|
|
399
415
|
oscura/streaming/progressive.py,sha256=YRdAd4P9Zvckerm2kG5bFWZtcuUB1FlRklpS1078s9c,13089
|
|
@@ -458,8 +474,8 @@ oscura/workflows/power.py,sha256=fpTzoIfuZi69ldtu2KAHW-Qu6jzA5jBa_9LVy6xqpTI,608
|
|
|
458
474
|
oscura/workflows/protocol.py,sha256=x3T-M81vFVrW3mouaYA8WjxyLLzZyLATVJbiqcMAVFQ,15275
|
|
459
475
|
oscura/workflows/reverse_engineering.py,sha256=K_yrqrQqQNcCoB0jRAG92e2zy8er3oiKJWSF6lU4nGk,19929
|
|
460
476
|
oscura/workflows/signal_integrity.py,sha256=p-DOC-AhzQOkG_jyyBK3EUaIBAGZhAhdmo-Ub_ifC3U,8391
|
|
461
|
-
oscura-0.
|
|
462
|
-
oscura-0.
|
|
463
|
-
oscura-0.
|
|
464
|
-
oscura-0.
|
|
465
|
-
oscura-0.
|
|
477
|
+
oscura-0.4.0.dist-info/METADATA,sha256=Usu1H_SaG7TkKGT33lnwM0WfPH4FB-icct_YbUwO1EM,16212
|
|
478
|
+
oscura-0.4.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
479
|
+
oscura-0.4.0.dist-info/entry_points.txt,sha256=QLBxd-iTjBQ5HidaVSkLBwvUsqxSG1ZTJ6i-0juu960,48
|
|
480
|
+
oscura-0.4.0.dist-info/licenses/LICENSE,sha256=p1_oEK-oqWDXMFSv5mKbyYkgW-CPbCnFUvdICu490aY,1077
|
|
481
|
+
oscura-0.4.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|