ರಹಸ್ಯ ಮತ್ತು ಅದನ್ನು ಹೊರುವ ಚಿತ್ರ
SnapSeal ಚಿತ್ರಗಳು, ಫೈಲ್ಗಳು ಅಥವಾ ಪಠ್ಯದ ಮೂಲ ಬೈಟ್ಗಳು ಮತ್ತು ಮೆಟಾಡೇಟಾವನ್ನು ಎನ್ಕ್ರಿಪ್ಟ್ ಮಾಡಿ, ಉಂಟಾಗುವ ಎನ್ವೆಲಪ್ ಅನ್ನು ಕವರ್ ಚಿತ್ರದ ಪಿಕ್ಸೆಲ್ಗಳಲ್ಲಿ ಸೇರಿಸುತ್ತದೆ. ಸ್ವೀಕರಿಸುವವರಿಗೆ ಸಂರಕ್ಷಿತ ಫೈಲ್ ಮತ್ತು ಪಾಸ್ವರ್ಡ್ ಬೇಕು; ಮೂಲ ಕವರ್ ಚಿತ್ರವಾಗಲೀ ಸರ್ವರ್ ಆಗಲೀ ಬೇಕಾಗಿಲ್ಲ.
ಕ್ರಿಪ್ಟೋಗ್ರಫಿ ವಿಷಯದ ಗೌಪ್ಯತೆಯನ್ನು ಕಾಪಾಡಿದರೆ, ಚಿತ್ರ ಸ್ಟೆಗನೋಗ್ರಫಿ ಅದನ್ನು ಸಾಗಿಸಲು ವಾಹಕ ಒದಗಿಸುತ್ತದೆ. ಎರಡೂ ಹಿಂದಿನಿಂದಲೂ ಇರುವ ತಂತ್ರಗಳು; ಇಲ್ಲಿ ಅವುಗಳ ನಡುವಿನ ಗಡಿಯನ್ನು ಸ್ಪಷ್ಟಪಡಿಸುವುದು ಮುಖ್ಯ. ಡೆಮೊದಲ್ಲಿರುವ ಚಿತ್ರ ಮತ್ತು ಪರೀಕ್ಷಾ ಪಾಸ್ವರ್ಡ್ ಅನ್ನು ಉದ್ದೇಶಪೂರ್ವಕವಾಗಿಯೇ ಪ್ರಕಟಿಸಲಾಗಿದೆ.
original_bytes + metadataArgon2id → AES-GCMheader + ciphertext + tagRGB → PNG
password = "Public SnapSeal article example"ಕೆಳಗಿನ ಎರಡು ಬಿಟ್ಗಳ ಕೆಲಸ
ಪ್ರತಿ RGB ಪಿಕ್ಸೆಲ್ನಲ್ಲಿ 3 ಚಾನೆಲ್ಗಳಿವೆ; ಪ್ರತಿಯೊಂದೂ 8 ಬಿಟ್ಗಳದ್ದು. ಈ ಉದಾಹರಣೆಯಲ್ಲಿ ಎನ್ಕೋಡರ್ ಚಾನೆಲ್ಗಳನ್ನು ಎಡದಿಂದ ಬಲಕ್ಕೆ ಓದುತ್ತದೆ, ಆಲ್ಫಾ ಚಾನೆಲ್ ಅನ್ನು ಬಿಟ್ಟು ಮೇಲಿನ 6 ಬಿಟ್ಗಳನ್ನು ಉಳಿಸುತ್ತದೆ. ನಂತರ ಕೆಳಗಿನ 2 ಬಿಟ್ಗಳನ್ನು ಬದಲಿಸುತ್ತದೆ. ಹೀಗೆ 4 ಚಾನೆಲ್ಗಳು 1 ಬೈಟ್ ಅನ್ನು ಸಾಗಿಸುತ್ತವೆ.
ಗುರುತಿಸಿದ ಬಿಟ್ಗಳು ಹೇಗೆ ಬದಲಾಗುತ್ತವೆ ಎಂಬುದನ್ನು ನೋಡಲು ಸ್ಲೈಡರ್ ಸರಿಸಿ. ಈ ಕೆಳ-ಬಿಟ್ ಬರವಣಿಗೆ ಮಾತ್ರ ಚಾನೆಲ್ನ ಮೌಲ್ಯವನ್ನು ಗರಿಷ್ಠ 3ರಷ್ಟು ಬದಲಿಸುತ್ತದೆ. ಐಚ್ಛಿಕ JPEG ವಾಹಕ ಮತ್ತು ಚಿತ್ರದ ಇತರ ವಿನ್ಯಾಸ ಬದಲಾವಣೆಗಳಿಂದ ಕವರ್ ಇನ್ನಷ್ಟು ಬದಲಾಗಬಹುದು.
R₀10101011170 → 171 Δ +1G₀10110101181 → 181 Δ 0B₀0101110094 → 92 Δ -2R₁11001011203 → 203 Δ 0def embed_byte(channels: bytes, value: int) -> bytes:
if len(channels) != 4 or not 0 <= value <= 255:
raise ValueError("Expected four channels and one byte")
pairs = [(value >> shift) & 3 for shift in (6, 4, 2, 0)]
return bytes((c & 0xFC) | pair
for c, pair in zip(channels, pairs, strict=True))
def read_byte(channels: bytes) -> int:
value = 0
for channel in channels:
value = (value << 2) | (channel & 3)
return value
cover = bytes([170, 181, 94, 203])
stored = embed_byte(cover, 0xD3)
assert stored == bytes([171, 181, 92, 203])
assert read_byte(stored) == 0xD3ಎಷ್ಟು ಬೈಟ್ಗಳಿಗೆ ಜಾಗವಿದೆ?
3 ಚಾನೆಲ್ಗಳಲ್ಲಿ ತಲಾ 2 ಬಿಟ್ ಎಂದರೆ ಪ್ರತಿ ಪಿಕ್ಸೆಲ್ಗೆ 6 ಬಿಟ್. 1024×1024 ಕವರ್ನಲ್ಲಿ 16-ಬೈಟ್ ಪಿಕ್ಸೆಲ್-ಪ್ಯಾಕೆಟ್ ಹೆಡರ್ಗಿಂತ ಮೊದಲು 786,432 ಬೈಟ್ಗಳಿಗೆ ಜಾಗವಿದೆ; ಹೆಡರ್ ನಂತರ 786,416 ಬೈಟ್ಗಳು ಉಳಿಯುತ್ತವೆ. ಚಿತ್ರ ವಿನ್ಯಾಸಕ್ಕೆ ಕೆಲವು ಪಿಕ್ಸೆಲ್ಗಳನ್ನು ಮೀಸಲಿಟ್ಟರೆ ಸಾಮರ್ಥ್ಯ ಕಡಿಮೆಯಾಗುತ್ತದೆ.
ಸ್ಥಿರ ಗುರುತು ಪ್ಯಾಕೆಟ್ ವಿನ್ಯಾಸವನ್ನು ಸೂಚಿಸುತ್ತದೆ; ಉದ್ದದ ಮೌಲ್ಯ ಎನ್ವೆಲಪ್ ಎಲ್ಲಿ ಮುಗಿಯುತ್ತದೆ ಎಂಬುದನ್ನು ತಿಳಿಸುತ್ತದೆ. ಪ್ಯಾಕೆಟ್ ಮತ್ತು ಎನ್ಕ್ರಿಪ್ಶನ್ ಆವೃತ್ತಿಗಳು ಪ್ರತ್ಯೇಕ: PNG2 ಪ್ಯಾಕೆಟ್ನಲ್ಲಿ v3 ಕ್ರಿಪ್ಟೋಗ್ರಾಫಿಕ್ ಎನ್ವೆಲಪ್ ಇರಬಹುದು.
C = floor(W × H × 3 × 2 / 8) − 16
C(1024, 1024) = 786,416 bytes[0:12] | SNAPSEALPNG2 | 12 bytes |
|---|---|---|
[12:16] | uint32_be(envelope_length) | 4 bytes |
[16:…] | envelope | envelope_length |
ಕೀ ಉತ್ಪಾದನೆ ಮತ್ತು ಎನ್ವೆಲಪ್ ದೃಢೀಕರಣ
SnapSealನ v3 ಪ್ರೊಫೈಲ್, UTF-8 ಪಾಸ್ವರ್ಡ್ನ ಬೈಟ್ಗಳು ಮತ್ತು ಯಾದೃಚ್ಛಿಕ 16-ಬೈಟ್ ಸಾಲ್ಟ್ನಿಂದ 32-ಬೈಟ್ ಕೀ ಉತ್ಪಾದಿಸಲು Argon2id v1.3 ಬಳಸುತ್ತದೆ. ಇದಕ್ಕೆ 64 MiB ಮೆಮೊರಿ, 3 ಪಾಸ್ ಮತ್ತು 1 ಲೇನ್ ಬಳಕೆಯಾಗುತ್ತವೆ. KDF ಚಲಾಯಿಸುವ ಮೊದಲು, ನಿಗದಿತ ಮತ್ತು ಬೆಂಬಲಿತ ಕಾರ್ಯ ನಿಯತಾಂಕಗಳೇ ಇವೆಯೆಂದು ರೀಡರ್ ಪರಿಶೀಲಿಸಬೇಕು.
AES-256-GCM ಮೂಲ ಬೈಟ್ಗಳು ಮತ್ತು ಮೆಟಾಡೇಟಾವನ್ನು ಎನ್ಕ್ರಿಪ್ಟ್ ಮಾಡುತ್ತದೆ. ಅದರ 16-ಬೈಟ್ ಟ್ಯಾಗ್ ಸೈಫರ್ಟೆಕ್ಸ್ಟ್ ಜೊತೆಗೆ ಸಾರ್ವಜನಿಕ 48-ಬೈಟ್ ಹೆಡರ್ನ್ನೂ ದೃಢೀಕರಿಸುತ್ತದೆ. ದೃಢೀಕರಣ ವಿಫಲವಾದರೆ ರೀಡರ್ ಪ್ಲೇನ್ಟೆಕ್ಸ್ಟ್ ಬಿಡುಗಡೆ ಮಾಡಬಾರದು.
[0:8] | SNAPSEAL |
|---|---|
[8:12] | version=3 · KDF=1 · Argon2=0x13 (v1.3) · lanes=1 |
[12:16] | memory_KiB=65536 |
[16:20] | passes=3 |
[20:36] | salt · 16 bytes |
[36:48] | nonce · 12 bytes |
from argon2.low_level import Type, hash_secret_raw
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
def decrypt_v3(envelope: bytes, password: str) -> bytes:
if not 70 <= len(envelope) <= 50 * 1024 * 1024 + 4096:
raise ValueError("Invalid envelope size")
header = envelope[:48]
if header[:12] != b"SNAPSEAL\x03\x01\x13\x01":
raise ValueError("Expected the v3 Argon2id profile")
memory = int.from_bytes(header[12:16], "big")
passes = int.from_bytes(header[16:20], "big")
if (memory, passes) != (65536, 3):
raise ValueError("Unsupported work factors")
secret = password.encode("utf-8")
if not 1 <= len(password) <= 256 or len(secret) > 1024:
raise ValueError("Invalid password length")
key = hash_secret_raw(
secret, header[20:36], time_cost=passes,
memory_cost=memory, parallelism=1, hash_len=32,
type=Type.ID, version=19,
)
return AESGCM(key).decrypt(
header[36:48], envelope[48:], header,
)plaintext = uint32_be(metadata_length) + metadata_json + original_bytes
envelope = header + AESGCM(key).encrypt(nonce, plaintext, header)ಸಂದೇಶ ಇರುವುದು ಪಿಕ್ಸೆಲ್ಗಳಲ್ಲಿ
ಡೇಟಾ ಇರುವುದು ಡೀಕೋಡ್ ಮಾಡಿದ RGB ಮೌಲ್ಯಗಳಲ್ಲಿ, PNG ಮೆಟಾಡೇಟಾದಲ್ಲಲ್ಲ. ಎರಡು PNG ಫೈಲ್ಗಳ ಬೈಟ್ಗಳು ಬೇರೆಬೇರೆಯಾಗಿದ್ದರೂ, ಡೀಕೋಡ್ ಮಾಡಿದ RGB ಮೌಲ್ಯಗಳು ಬದಲಾಗದಿದ್ದರೆ ಅವು ಒಂದೇ ಕೆಳ-ಬಿಟ್ ಸಂದೇಶವನ್ನು ಉಳಿಸಬಹುದು. ಆದರೆ ಸ್ಕ್ರೀನ್ಶಾಟ್, ಪಿಕ್ಸೆಲ್ ಸಂಪಾದನೆ ಅಥವಾ ಗಾತ್ರ ಬದಲಾವಣೆಯಿಂದ ಚಿತ್ರ ಗುರುತಿಸುವಂತೆಯೇ ಉಳಿದರೂ ಡೇಟಾ ನಾಶವಾಗಬಹುದು.
ಮೂಲದ ಸಂಕುಚನವನ್ನು ಸ್ಪಷ್ಟವಾಗಿ ಆಯ್ಕೆ ಮಾಡದಿದ್ದರೆ, ಮರುಪಡೆಯುವಾಗ ಮೂಲ ಬೈಟ್ಗಳು ಮತ್ತು ಮೆಟಾಡೇಟಾ ನಿಖರವಾಗಿ ಮರಳುತ್ತವೆ. ಫೈಲ್ ಹೆಸರು ಎನ್ಕ್ರಿಪ್ಟ್ ಆಗಿರುತ್ತದೆ; ಆದರೆ ಪ್ಯಾಡಿಂಗ್ ಇಲ್ಲದಿದ್ದರೆ ಎನ್ವೆಲಪ್ನ ಅಂದಾಜು ಗಾತ್ರ ತಿಳಿಯುತ್ತದೆ.
PNG bytes A ≠ PNG bytes B
RGB(A) = RGB(B), α(A) = α(B) = 255
→ envelope(A) = envelope(B)ಸಂಕುಚನದ ನಂತರವೂ ಮರುಪಡೆಯಲು JPEG ಮಾರ್ಗ
ಆ್ಯಂಟಿ-ಕಂಪ್ರೆಷನ್ ಎಂದರೆ ಆಯಾಮಗಳು ಬದಲಾಗದ JPEGಯಿಂದ ಡೇಟಾವನ್ನು ಸಾಧ್ಯವಾದಷ್ಟು ಮರುಪಡೆಯುವ ಪ್ರಯತ್ನ. ಅದೇ ಎನ್ಕ್ರಿಪ್ಟ್ ಮಾಡಿದ ಎನ್ವೆಲಪ್ನ ನಷ್ಟರಹಿತ ಪ್ರತಿ PNGಯ ಕೆಳ RGB ಬಿಟ್ಗಳಲ್ಲಿರುತ್ತದೆ; ಐಚ್ಛಿಕವಾಗಿ ಮರುಪಡೆಯುವ ಮತ್ತೊಂದು ಪ್ರತಿ ಚಿತ್ರದ ಆವರ್ತನ ಗುಣಾಂಕಗಳಲ್ಲಿರುತ್ತದೆ.
ಇದು ಸಂಕುಚನವನ್ನು ತಡೆಯುವುದಿಲ್ಲ ಅಥವಾ ಮರುಪಡೆಯುವಿಕೆ ಯಶಸ್ವಿಯಾಗುತ್ತದೆ ಎಂದು ಖಾತರಿಪಡಿಸುವುದಿಲ್ಲ. ಸ್ವರೂಪವನ್ನು ಪತ್ತೆಯಾಗದಂತೆಯೂ ಮಾಡುವುದಿಲ್ಲ.
envelope → RS(255,223)interleave → spread blocksQIM → luma DCT 8×8repair → CRC → AES-GCM
ಪಿಕ್ಸೆಲ್ಗಳಿಂದ ಆವರ್ತನ ಗುಣಾಂಕಗಳಿಗೆ
JPEG, 8×8 ಹೊಳಪಿನ ಬ್ಲಾಕ್ಗಳಿಗೆ DCT ಅಥವಾ ಡಿಸ್ಕ್ರೀಟ್ ಕೊಸೈನ್ ಟ್ರಾನ್ಸ್ಫಾರ್ಮ್ ಅನ್ವಯಿಸಿ ಆವರ್ತನ ಗುಣಾಂಕಗಳಾಗಿ ಪರಿವರ್ತಿಸುತ್ತದೆ; ನಂತರ ಅವನ್ನು ಕ್ವಾಂಟೈಸ್ ಮಾಡುತ್ತದೆ. SnapSeal ಆಯ್ದ ಗುಣಾಂಕಗಳಲ್ಲಿ ಉದ್ದೇಶಪೂರ್ವಕವಾಗಿ ಅಂತರವಿರುವ ಮೌಲ್ಯಗಳ ಮೂಲಕ ಡೇಟಾ ಸಾಗಿಸುತ್ತದೆ. ಇದರಿಂದ JPEG ಎನ್ಕೋಡಿಂಗ್ ಉಂಟುಮಾಡುವ ಕೆಲವು ಬದಲಾವಣೆಗಳನ್ನು ರೀಡರ್ ಸಹಿಸಿಕೊಳ್ಳಲು ಅವಕಾಶ ಸಿಗುತ್ತದೆ.
ದೋಷ ತಿದ್ದುಪಡಿ ಹೊಂದಿರುವ ಟ್ರಾನ್ಸ್ಪೋರ್ಟ್ ಹೆಡರ್ ಮರುಪಡೆಯುವ ಡೇಟಾದ ಸ್ಥಾನವನ್ನು ಗುರುತಿಸುತ್ತದೆ. ರೀಡರ್ಗೆ ಮೂಲ ಕವರ್ ಅಗತ್ಯವಿಲ್ಲ.
RGB → Y → DCT(8×8)
q = round(coefficient / JPEG_quantizer)
coefficient′ = q × JPEG_quantizerಸಂಕೇತಗಳ ನಡುವೆ ಅಂತರ
QIM, ಅಂದರೆ ಕ್ವಾಂಟೈಸೇಶನ್-ಇಂಡೆಕ್ಸ್ ಮಾಡ್ಯುಲೇಶನ್, ಸಂಕೇತಗಳಿಗೆ ಪರಸ್ಪರ ಅಂತರವಿರುವ ಸ್ಥಾನಗಳನ್ನು ನಿಗದಿಪಡಿಸುತ್ತದೆ. 1-ಬಿಟ್ ಕಲಿಕಾ ಮಾದರಿಯಲ್ಲಿ 24ರ ಗುಣಿತಗಳು ಪರ್ಯಾಯವಾಗಿ 0 ಮತ್ತು 1 ಅನ್ನು ಸೂಚಿಸುತ್ತವೆ. 1 ಸಂಗ್ರಹಿಸಲು 70 ಅನ್ನು 72ಕ್ಕೆ ಸರಿಸಲಾಗುತ್ತದೆ. 72ರಿಂದ +11 ಬದಲಾವಣೆಯಾದರೂ ಅದು 1 ಆಗಿಯೇ ಡೀಕೋಡ್ ಆಗುತ್ತದೆ; +13 ಆದರೆ ಗಡಿ ದಾಟಿ ಬಿಟ್ ತಿರುಗುತ್ತದೆ. ಆ ಗಡಿಯನ್ನು ನೋಡಲು ಸ್ಲೈಡರ್ ಸರಿಸಿ.
ನಿಜವಾದ ಚಾನೆಲ್ನಲ್ಲಿ ಆಯ್ದ ಪ್ರತಿ ಗುಣಾಂಕದಲ್ಲಿ Gray coding ಬಳಸಿ 1–3 ಬಿಟ್ಗಳನ್ನು ಸಂಗ್ರಹಿಸಲಾಗುತ್ತದೆ. Pythonನ QIM ತುಣುಕು ಈ ತತ್ವವನ್ನು ವಿವರಿಸುವ ಮಾದರಿ ಮಾತ್ರ; ಅದು JPEG ಡೀಕೋಡರ್ ಅಲ್ಲ.
from math import floor
def put_bit(coefficient: float, bit: int, step: int = 24) -> int:
cell = floor((coefficient / step - bit) / 2 + 0.5)
return step * (2 * cell + bit)
def read_bit(coefficient: float, step: int = 24) -> int:
return floor(coefficient / step + 0.5) % 2
stored = put_bit(70, 1) # 72
assert read_bit(stored + 11) == 1 # 83: same cell
assert read_bit(stored + 13) == 0 # 85: crossed the boundaryಮೊದಲು ದುರಸ್ತಿ, ಕೊನೆಯಲ್ಲಿ ದೃಢೀಕರಣ
Reed–Solomon (255,223), 223 ಡೇಟಾ ಬೈಟ್ಗಳಿಗೆ 32 ಪ್ಯಾರಿಟಿ ಬೈಟ್ಗಳನ್ನು ಸೇರಿಸುತ್ತದೆ. ಅದು ಪ್ರತಿ ಕೋಡ್ವರ್ಡ್ನಲ್ಲಿ ಗರಿಷ್ಠ 16 ತಪ್ಪು ಬೈಟ್ಗಳನ್ನು ಸರಿಪಡಿಸಬಲ್ಲದು. ಇಂಟರ್ಲೀವಿಂಗ್ ಮತ್ತು ಚಿತ್ರದುದ್ದಕ್ಕೂ ಹರಡಿರುವ ಬ್ಲಾಕ್ಗಳು ಹಾನಿ ಕೆಲವೇ ಕೋಡ್ವರ್ಡ್ಗಳಲ್ಲಿ ಕೇಂದ್ರೀಕರಿಸದಂತೆ ಹಂಚಲು ನೆರವಾಗುತ್ತವೆ.
ರೀಡರ್ ಮೊದಲು ಟ್ರಾನ್ಸ್ಪೋರ್ಟ್ ಡೇಟಾವನ್ನು ದುರಸ್ತಿ ಮಾಡಿ, ನಂತರ CRC ಪರಿಶೀಲಿಸುತ್ತದೆ; ಆಮೇಲೆ AES-GCM ಮೂಲಕ ಎನ್ವೆಲಪ್ ದೃಢೀಕರಿಸುತ್ತದೆ. CRC ಟ್ರಾನ್ಸ್ಪೋರ್ಟ್ ಸಮಗ್ರತೆಯ ಪರಿಶೀಲನೆ, ಕ್ರಿಪ್ಟೋಗ್ರಾಫಿಕ್ ದೃಢೀಕರಣವಲ್ಲ. ದುರಸ್ತಿ ಯಶಸ್ವಿಯಾದರೂ GCM ಪರಿಶೀಲನೆ ವಿಫಲವಾದರೆ ಪ್ಲೇನ್ಟೆಕ್ಸ್ಟ್ ಬಿಡುಗಡೆ ಮಾಡಬಾರದು.
223 + 32 = 255 bytes
t = (255 − 223) / 2 = 16 byte errors
A₀ B₀ C₀ A₁ B₁ C₁ … → A, B, C
repair → CRC → AES-GCM → original_bytesಎರಡೂ ವಾಹಕಗಳನ್ನು ಒಟ್ಟಿಗೆ ಪರೀಕ್ಷಿಸುವುದು
ಎರಡೂ ಪ್ರತಿಗಳು ಅದೇ ಪಿಕ್ಸೆಲ್ಗಳನ್ನು ಬಳಸುವುದರಿಂದ, ಕೆಳ ಬಿಟ್ಗಳ ಬರವಣಿಗೆ DCT ಗುಣಾಂಕಗಳನ್ನೂ ಬದಲಿಸುತ್ತದೆ. ಆದ್ದರಿಂದ ಸ್ವಯಂ ಪರೀಕ್ಷೆಗಳು ಅಂತಿಮ ಸಂಯೋಜಿತ ವಾಹಕದ ಮೇಲೆಯೇ ನಡೆಯುತ್ತವೆ. ಸ್ಥಳೀಯ ಬ್ರೌಸರ್ JPEG ಪರೀಕ್ಷೆಗಳಲ್ಲಿ 0.60 ಗುಣಮಟ್ಟದಲ್ಲೂ, ಪುನರಾವರ್ತಿತ 0.85→0.60 ಎನ್ಕೋಡಿಂಗ್ನಲ್ಲೂ ನಿಖರ ಎನ್ವೆಲಪ್ ಮರಳಿದರೆ ಮಾತ್ರ ಮರುಪಡೆಯುವಿಕೆ ಲಭ್ಯವೆಂದು ತಿಳಿಸಲಾಗುತ್ತದೆ. ಪ್ರತಿ ಕೋಡ್ವರ್ಡ್ನಲ್ಲಿ ದುರಸ್ತಿ ಮಾಡಿದ ಬೈಟ್ಗಳು ಗರಿಷ್ಠ 12 ಆಗಿರಬೇಕು; ಇದು 16-ಬೈಟ್ ತಿದ್ದುಪಡಿ ಮಿತಿಗಿಂತ ಕಡಿಮೆ. ಈ ಗುಣಮಟ್ಟದ ಸೆಟ್ಟಿಂಗ್ಗಳು ಸ್ಥಳೀಯ ಪರೀಕ್ಷೆಗಳೇ ಹೊರತು ಎಲ್ಲ JPEGಗಳಿಗೂ ಅನ್ವಯಿಸುವ ಖಾತರಿಯಲ್ಲ.
ಸ್ವಯಂಚಾಲಿತ ಪ್ರಯತ್ನಗಳಿಗೆ, ಹೆಚ್ಚುವರಿ ಓವರ್ಹೆಡ್ ಸೇರಿದಂತೆ, 280,000 ಎನ್ಕ್ರಿಪ್ಟ್ ಮಾಡಿದ ಬೈಟ್ಗಳ ಮಿತಿಯಿದೆ. ಪುನರಾವರ್ತಿತ ಡೇಟಾ ಮತ್ತು ಬಲವಾದ ಸಂಕೇತಗಳಿಗಾಗಿ ಕವರ್ನ ಗುಣಮಟ್ಟ ಮತ್ತು ಸಾಮರ್ಥ್ಯವನ್ನು ವಿನಿಯೋಗಿಸಬೇಕಾಗುತ್ತದೆ; ಈ ಚಾನೆಲ್ ಖಾಸಗಿ ಮೂಲವನ್ನು ಮತ್ತೆ ಸಂಕುಚಿಸುವುದಿಲ್ಲ. ಪರೀಕ್ಷೆಗಳು ವಿಫಲವಾದರೆ ನಷ್ಟರಹಿತ PNG ಅಥವಾ ZIP ವಿತರಣೆಗೆ ಮರಳಲಾಗುತ್ತದೆ. ಕತ್ತರಿಸುವಿಕೆ, ಗಾತ್ರ ಬದಲಾವಣೆ, ತಿರುಗಿಸುವಿಕೆ ಅಥವಾ ಬೇರೆ ಎನ್ಕೋಡರ್ ಮರುಪಡೆಯುವಿಕೆಯನ್ನು ವಿಫಲಗೊಳಿಸಬಹುದು. ಆದ್ದರಿಂದ ಮೂಲ PNG ಅಥವಾ ZIP ಅನ್ನು ಫೈಲ್ ಆಗಿ ಕಳುಹಿಸುವುದೇ ವಿಶ್ವಾಸಾರ್ಹ ಆಯ್ಕೆ.
exact(PNG) ∧ exact(Q60) ∧ exact(Q85 → Q60)
max(corrected_bytes_per_codeword) ≤ 12 < 16
automatic: envelope_length ≤ 280_000ಸ್ವರೂಪ ಏನನ್ನು ಬಹಿರಂಗಪಡಿಸುತ್ತದೆ?
ಸ್ಥಿರ ಗುರುತುಗಳಿಂದ ಈ ಸ್ವರೂಪವನ್ನು ಪತ್ತೆಹಚ್ಚಬಹುದು. ಕವರ್ ಚಿತ್ರ ಸಾರ್ವಜನಿಕವಾಗಿರುತ್ತದೆ ಮತ್ತು ಚಿತ್ರವಾಗಿ ದೃಢೀಕರಿಸಲ್ಪಡುವುದಿಲ್ಲ; ಅದರ ಮೇಲಿನ ಬಿಟ್ಗಳು ಬದಲಾದರೂ ಒಳಗಿನ ಸಂದೇಶ ಉಳಿಯಬಹುದು. ದೋಷ ತಿದ್ದುಪಡಿ ಮತ್ತು CRC ಟ್ರಾನ್ಸ್ಪೋರ್ಟ್ ಹಾನಿಯನ್ನು ನಿಭಾಯಿಸಿದರೆ, AES-GCM ಸಂರಕ್ಷಿತ ವಿಷಯವನ್ನು ದೃಢೀಕರಿಸುತ್ತದೆ.
ಆಕ್ರಮಣಕಾರರು ಆಫ್ಲೈನ್ನಲ್ಲಿ ಪಾಸ್ವರ್ಡ್ ಊಹಿಸಲು ಪ್ರಯತ್ನಿಸಬಹುದು. Argon2id ಪ್ರತಿ ಪ್ರಯತ್ನದ ವೆಚ್ಚವನ್ನು ಹೆಚ್ಚಿಸುತ್ತದೆ, ಆದರೆ ದುರ್ಬಲ ಪಾಸ್ವರ್ಡ್ ಅನ್ನು ರಕ್ಷಿಸಲಾರದು. ಪಾಸ್ವರ್ಡ್ ಮರುಪಡೆಯುವ ವ್ಯವಸ್ಥೆ ಇಲ್ಲ; ಸ್ವತಂತ್ರ ಭದ್ರತಾ ಪರಿಶೋಧನೆ ನಡೆದಿದೆ ಎಂಬ ಹೇಳಿಕೆಯೂ ಇಲ್ಲ.
ಅಪ್ಲಿಕೇಶನ್ ಇಲ್ಲದೆ ಓದುವುದು
ಈ ಸ್ವರೂಪವು ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಕ್ರಿಪ್ಟೋಗ್ರಾಫಿಕ್ ತಂತ್ರಗಳನ್ನು ಬಳಸುತ್ತದೆ ಮತ್ತು ತನ್ನ ರಚನೆ ಹಾಗೂ ಮಿತಿಗಳನ್ನು ಸ್ಪಷ್ಟಪಡಿಸುತ್ತದೆ. ಅದನ್ನು ಸ್ವತಂತ್ರ ರೀಡರ್ನಿಂದಲೂ ಓದಬಹುದು. Python 3.12+ ರೀಡರ್ ಮೂಲ PNGಗಳನ್ನು ಓದುತ್ತದೆ; JPEG ಮರುಪಡೆಯುವ ಪ್ರತಿ ಇರುವ PNGಗಳೂ ಇದರಲ್ಲಿ ಸೇರಿವೆ. ಜೊತೆಗೆ, ನಿಗದಿತ ಮಿತಿಯೊಳಗಿನ ಒಂದು PNG ಹೊಂದಿರುವ SnapSeal ZIPಗಳನ್ನು ಮತ್ತು raw v3 ಎನ್ವೆಲಪ್ಗಳನ್ನು ಬೆಂಬಲಿಸುತ್ತದೆ. JPEGಗೆ ಪರಿವರ್ತಿಸಿದ ಫೈಲ್ಗಳಿಗೆ TypeScript ಕೋಡೆಕ್ ಬೇಕು.
ಇಲ್ಲಿ ವಿವರಿಸಿದ್ದು ಮುಕ್ತ ಮೂಲದ v3 ಅನುಷ್ಠಾನ. ಹಿಂದೆ ನಿಯೋಜಿಸಲಾದ ಹಳೆಯ ರೀಡರ್ಗಳು ಅದರ ಔಟ್ಪುಟ್ ಅನ್ನು ತಿರಸ್ಕರಿಸಬಹುದು. ಪಟ್ಟಿ ಮಾಡಿರುವ ಅವಲಂಬನೆಗಳನ್ನು ವರ್ಚುವಲ್ ಪರಿಸರದಲ್ಲಿ ಸ್ಥಾಪಿಸಿ. ಸಂಪೂರ್ಣ ಮೂಲ ಕೋಡ್ ಮತ್ತು ಐಚ್ಛಿಕ ಡೌನ್ಲೋಡ್ಗಳು ಉದಾಹರಣೆಗಳ ನಂತರ ಇವೆ.
python -m pip install -r requirements.txtfrom getpass import getpass
from pathlib import Path
from decode_snapseal import decode_path
result = decode_path(
Path("protected.png"),
getpass("Password: "),
)
output = Path("restored")
output.mkdir(exist_ok=True)
with (output / result.filename).open("xb") as target:
target.write(result.data)

