SHT30 온습도 모니터링 시스템 전체 소스(서버 PHP, STM32 펌웨어, SQL, 테스트). 전체 코드리뷰에서 도출된 보안 하드닝 10건 반영: - 요청 서명 HMAC-SHA256 전환(펌웨어 sig.c/서버 config.php/호스트 패리티 동시) - 재전송 방어 + 기본 API_KEY fail-closed + 디바이스 문자열 정제(api/sensor_data.php) - 오프라인 SMS 중복 발송 경합 제거(cron_heartbeat.php, 원자적 선점) - CSV 수식 주입 방지(monthly_report.php), 감사로그 회전 락(retention_cleanup.php) - 브루트포스 카운터 원자화(login.php), 예시 TOTP 비밀키 무효화, 마이그레이션 멱등화 _backup/(하드코딩 실 비밀값 포함)·config.local.php·런타임 상태는 .gitignore 제외.
56 lines
2 KiB
C
56 lines
2 KiB
C
/* =============================================================================
|
|
* sig.c - raw-body 서명 구현 (HMAC-SHA256)
|
|
*
|
|
* 서버 규약(php/config.php:verify_signature_raw):
|
|
* X-Signature = lowercase_hex( HMAC-SHA256( key=API_KEY, msg=raw_body_bytes ) )
|
|
*
|
|
* HMAC(키 접두 SHA256 이 아님)을 쓰는 이유: 길이확장(length-extension) 공격에
|
|
* 견디고, 서버 hash_hmac('sha256', body, API_KEY) 와 바이트 단위로 일치한다.
|
|
* reference.py:sign_raw() (hmac.new) 와도 동일하다.
|
|
* ===========================================================================*/
|
|
#include "sig.h"
|
|
#include "sha256_backend.h"
|
|
#include "hexutil.h"
|
|
#include <string.h>
|
|
|
|
/* SHA-256 블록 크기(HMAC 키 패딩 단위). */
|
|
#define SIG_HMAC_BLOCK 64u
|
|
|
|
void sig_raw_body(const char *key, const char *body, size_t body_len,
|
|
char out_hex[SIG_HEX_BUFSZ])
|
|
{
|
|
uint8_t k0[SIG_HMAC_BLOCK]; /* 블록 크기로 정규화한 키 K' */
|
|
uint8_t ipad[SIG_HMAC_BLOCK];
|
|
uint8_t opad[SIG_HMAC_BLOCK];
|
|
uint8_t inner[SHA256_DIGEST_LEN];
|
|
uint8_t digest[SHA256_DIGEST_LEN];
|
|
sha256_ctx ctx;
|
|
size_t key_len = strlen(key);
|
|
|
|
/* K' = 키를 블록 크기로 맞춘 값. 64바이트 초과면 SHA256 으로 줄이고 0 패딩. */
|
|
memset(k0, 0, sizeof(k0));
|
|
if (key_len > SIG_HMAC_BLOCK) {
|
|
sha256((const uint8_t *)key, key_len, k0); /* 앞 32바이트, 나머지는 0 유지 */
|
|
} else {
|
|
memcpy(k0, key, key_len);
|
|
}
|
|
|
|
for (size_t i = 0; i < SIG_HMAC_BLOCK; i++) {
|
|
ipad[i] = (uint8_t)(k0[i] ^ 0x36u);
|
|
opad[i] = (uint8_t)(k0[i] ^ 0x5cu);
|
|
}
|
|
|
|
/* inner = SHA256(ipad || body) */
|
|
sha256_init(&ctx);
|
|
sha256_update(&ctx, ipad, SIG_HMAC_BLOCK);
|
|
sha256_update(&ctx, (const uint8_t *)body, body_len);
|
|
sha256_final(&ctx, inner);
|
|
|
|
/* digest = SHA256(opad || inner) */
|
|
sha256_init(&ctx);
|
|
sha256_update(&ctx, opad, SIG_HMAC_BLOCK);
|
|
sha256_update(&ctx, inner, SHA256_DIGEST_LEN);
|
|
sha256_final(&ctx, digest);
|
|
|
|
hex_encode_lower(digest, SHA256_DIGEST_LEN, out_hex);
|
|
}
|