2번 모듈 신규(raspberry_pi4_sht30/): SHT30 온습도 → cafe24, raw-body X-Signature HMAC, 폐쇄망 오프라인 설치(vendor/install), systemd, CRC/포맷 자가점검. firmware sht30_fw wire 포맷과 byte-parity 검증. 1번 모듈 통합(raspberry_pi4/): 누수+카메라를 동일 서버로. 레거시 sha256(key+json) body-sig → X-Signature HMAC 전환, 사진 canonical=device_id|sensor_id|log_id|timestamp. 서버 통합(php/): api/sensor_data.php 누수 이벤트 수신, api/photo_upload.php 신규(HMAC·finfo·서버생성 파일명·nonce 멱등·sensor 결속), photo.php 인증 사진서빙, dashboard.php 누수 패널+사진, sms_send.php 누수 SMS, config.php 태그/요약. DB: sql/migration_add_leak.sql(가산·멱등), schema_sht30.sql 통합 스키마. 보안 하드닝(외부 펜테스트 대비, 확정 CRITICAL/HIGH 0): cron_heartbeat api_key fail-closed, setup_mfa 부트스트랩 토큰 post-enrollment 잠금, var/ PHP 실행차단, HSTS. 문서/테스트: SYSTEM_OVERVIEW.md, security_hardening_test.php 갱신. 참고: 사용자 요청으로 세션 외 기존 미커밋 변경도 함께 포함. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
50 lines
1.7 KiB
C
50 lines
1.7 KiB
C
/* =============================================================================
|
|
* sig_cli.c - 호스트 C 패리티 드라이버
|
|
*
|
|
* 펌웨어의 실제 서명 구현(common/sig.c: sig_raw_body)을 호스트에서 그대로 컴파일·
|
|
* 실행하여, Python 레퍼런스(reference.py: sign_raw)와 서버(php verify_signature_raw)
|
|
* 와 *바이트 단위로* 일치하는지 검증한다. 이렇게 해야 "C 는 컴파일·실행되지 않아
|
|
* 손으로만 맞춘" 갭이 닫힌다(C↔Python↔PHP 3자 패리티).
|
|
*
|
|
* 사용: sig_cli <api_key> (본문은 stdin, 바이너리 그대로)
|
|
* 출력: lowercase_hex(HMAC-SHA256(key=api_key, msg=body)) (개행 없음)
|
|
*
|
|
* parity_test.py 가 common/{sig.c,sha256_sw.c,hexutil.c} 와 함께 컴파일한다.
|
|
* ===========================================================================*/
|
|
#include "sig.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
if (argc < 2) {
|
|
fprintf(stderr, "usage: %s <api_key> (body on stdin)\n", argv[0]);
|
|
return 2;
|
|
}
|
|
const char *key = argv[1];
|
|
|
|
/* stdin 전체를 바이너리 그대로 읽는다(서명은 본문 바이트에 대해 계산되므로
|
|
* 어떤 변환도 하지 않는다). */
|
|
size_t cap = 4096, len = 0;
|
|
char *body = (char *)malloc(cap);
|
|
if (body == NULL) {
|
|
return 3;
|
|
}
|
|
int c;
|
|
while ((c = getchar()) != EOF) {
|
|
if (len + 1 > cap) {
|
|
cap *= 2;
|
|
char *n = (char *)realloc(body, cap);
|
|
if (n == NULL) { free(body); return 3; }
|
|
body = n;
|
|
}
|
|
body[len++] = (char)c;
|
|
}
|
|
|
|
char out_hex[SIG_HEX_BUFSZ];
|
|
sig_raw_body(key, body, len, out_hex);
|
|
fputs(out_hex, stdout);
|
|
|
|
free(body);
|
|
return 0;
|
|
}
|