Files
Aislo/tools/stmate-test/dbf_crypt.py
T
eomsangdonandClaude Opus 5.5 e987602f24 feat(stmate-test): 무손실 저장 — 손대지 않은 저장 = 원본 STC 바이트 동일 · 고친 칸만 다시 씀
- DBF 고친 칸만 다시 씀(한글 깨짐 · 2칸을 1칸으로 · 3칸 87.745% 덮어쓰기 없앰) · 단가 → 내역 행 → 소계 → 직공비 다시 셈 · 행 끼우기·지우기
- SIxMemo(COSTN.SMT · PRJLST.SMT) 블록 구조 유지 · 넘치면 뒤에 붙이고 가리키는 값 갱신
- STC 다시 묶기(같은 파일은 원본 바이트) · 검사 · 자동 백업·복원 · 새 공사 · 복사등록(차수 인계) · 해당분 압축
- BDQTY 역변환(쓰기 준비) · 모듈 dbf_rw · dbf_memo · dbf_crypt · stc_archive · stc_save · stc_read · stc_project · api_file · scr_file
- 지킴 시험 test_stmate_file_roundtrip · file_project · file_payload — 실무 STC 7건 왕복

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 18:42:04 +09:00

43 lines
1.5 KiB
Python

# -*- coding: utf-8 -*-
"""암호 DBF(BDQTY.DBF) 자리별 변환 — 복호(bdqty._dec)의 역변환으로 다시 숨김.
근거: STC_난독화_상태.md · 29_암호화자료의_뼈대.md · bdqty.py(자리별 표 PARAMS)
A 암호 = rol(평문, r) + k B 암호 = rol(평문 + k, r) X 암호 = rol(평문, r) ^ k
표에 없는 자리(글자 칸 등)는 풀 수도 숨길 수도 없음 — 그 자리를 건드리는 쓰기는 오류.
"""
from __future__ import annotations
from bdqty import PARAMS, _dec
def _rol(v: int, r: int) -> int:
return ((v << r) | (v >> (8 - r))) & 0xFF if r else v
def enc_byte(p: int, param: tuple[str, int, int]) -> int:
kind, r, k = param
if kind == "A":
return (_rol(p, r) + k) & 0xFF
if kind == "B":
return _rol((p + k) & 0xFF, r)
return _rol(p, r) ^ k
def covers(off: int, n: int) -> bool:
return all(j in PARAMS for j in range(off, off + n))
class BdqtyCodec:
"""DbfTable codec — off = 레코드 안 칸 시작 자리."""
def decode(self, cipher: bytes, off: int) -> bytes:
if not covers(off, len(cipher)):
raise ValueError(f"BDQTY 자리 {off}~{off + len(cipher) - 1} 은 복호 표에 없음")
return bytes(_dec(c, PARAMS[off + i]) for i, c in enumerate(cipher))
def encode(self, plain: bytes, off: int) -> bytes:
if not covers(off, len(plain)):
raise ValueError(f"BDQTY 자리 {off}~{off + len(plain) - 1} 은 암호 표에 없음")
return bytes(enc_byte(p, PARAMS[off + i]) for i, p in enumerate(plain))