전화가 거의 없습니다.
모든 플랫폼.

Identity Layer은 설계상 최소한의 표면과 통합됩니다. 마이크로 컨트롤러의 경우 MicroPython, Android 및 Windows의 경우 Flutter, 또는 기존 엔드포인트에 PHP bridge을 추가했습니다. 동일한 프로토콜. 동일한 암호화 보장. 4번의 통화.

Raspberry Pi Pico 2W, PN532 NFC reader, SSD1306 OLED display, NTAG424 DNA card
Boot
Registering
Node exists
Verified
Challenge
Active
4번의 수술 호출. WiFi, OLED 및 구성 로딩은 장치 인프라입니다. Identity Layer이 아닙니다. 아이덴티티 프리미티브는 IdentityIoT, 다음을 통해 설치됨 mip.
MicroPython
# Install via mip — no external dependencies
# import mip; mip.install("github:wide/identity-micropython")

from identity_iot import IdentityIoT

# 1. Init — configure node identity
identity = IdentityIoT(
    base_url  = cfg['base_url'],
    node_type = cfg['node_type'],
    tenant_id = cfg['tenant_id'],
    comm_key  = cfg['comm_key'].encode(),
    comm_iv   = cfg['comm_iv'].encode(),
)

# 2. Register — device-bound key, runs once
identity.ensure_registered()

# 3. Authenticate — Ed25519 challenge / verify / JWT
token = identity.authenticate()

# 4. Authenticated request — AES-256-GCM encrypted payload
response = identity.post_encrypted({'request': 'record_sensor_data', 'value': 42})
요소 모델 역할
MCU Raspberry Pi Pico 2W (RP2350) TrustZone, WiFi, device-bound 키 저장소
NFC reader PN532 I2C 인터페이스, NTAG424 DNA 배지를 읽습니다.
표시하다 SSD1306 128x64 OLED 부팅 순서, 확인 상태
NFC badge NTAG424 DNA (NXP) AES-128 온보드, 내보낼 수 없는 키, 동적 CMAC
데이터 센터 및 물리적 액세스 분야에 대한 ESP32 및 RP2040 참조 배포가 진행 중입니다. 프로토콜과 SDK는 지원되는 모든 하드웨어에서 동일합니다.

Identity IoT 노드는 NFC 액세스로 제한되지 않습니다. 동일한 인증된 node는 모든 센서 페이로드를 전달할 수 있습니다. 모든 판독값은 node이 JWT을 획득한 후 AES-256-GCM 암호화된 POST을 통해 전송됩니다.

센서 유형일반적인 하드웨어페이로드 필드
온도DHT22, DS18B20, BME280온도(부동, °C)
습기DHT22, BME280습도(부유물, %)
압력BME280, BMP390압력(부유수, hPa)
PIR 모션HC-SR501모션(부울)
GPSNEO-6M, L76X위도, 경도, 고도(부동 소수점)
에너지 계량PZEM-004T, INA219전압, 전류, 전력(부동)
NFC 액세스PN532 + NTAG424 DNABadge_uid, 부여됨(부울)
JSON(복호화됨)
{
  "node_uid"   : "273ec83a-84c8-4967-aafa-0780ab161cc1",
  "tenant_id"  : "0b3cfe4d-fdf7-46c2-bd41-b533da415dd9",
  "node_type"  : "sensor",
  "temperature": 24.3,
  "humidity"   : 58.1,
  "pressure"   : 1013.2,
  "updated_at" : "2026-06-09 11:42:07"
}

Badge 읽었습니다. 챌린지가 발행되었습니다.
Ed25519이(가) 확인되었습니다.

Identity Tag는 Identity IoT 위에 구축된 애플리케이션 계층입니다. 각 badge 읽기는 백엔드에 대해 전체 Ed25519 challenge/response 주기를 트리거합니다. reader에 저장된 비밀이 없습니다. badge에 일반 텍스트 ID가 없습니다. 다중 tenant 설계.

Badge부터 GRANTED까지 4단계로 진행됩니다. reader(Pico 2W + PN532)은 인증된 Identity IoT node입니다. badge은 AES-CBC로 암호화된 개인 키 조각과 분할 DEK을 전달합니다. 백엔드는 챌린지를 발행하고 Ed25519 서명을 수신하고 이를 확인한 후 GRANTED 또는 DENIED을 반환합니다. 일반 텍스트로 전송되는 비밀은 없습니다. 자격 증명 데이터베이스가 없습니다.
흐름: badge 읽기-액세스 결정
# 1. Reader reads NTAG424 DNA NDEF payload
#    Fields: epk (encrypted private key), df2 (DEK fragment 2), mode (STD|HS)

# 2. DEK reconstruction
dek = df1_from_config XOR df2_from_badge

# 3. Decrypt badge private key
badge_privkey = AES_CBC_decrypt(dek, epk)

# 4. Request challenge from backend
challenge = POST identity_tag/it_request_challenge
#    { node_uid, badge_uid, tenant_id }

# 5. Sign challenge with badge key (Ed25519)
signature = ed25519_sign(badge_privkey, challenge_nonce)

# 6. Verify at backend
result = POST identity_tag/it_verify_badge
#    { challenge_id, signature_b64 }  ->  { granted: true }

# 7. Reader actuates relay (GRANTED) or displays DENIED
방법설명사용 사례
STD Badge은(는) 해당 tenant에 대해 승인된 차량의 모든 터미널에서 작동합니다. 사무실 접근, 일반 진입점.
HS Badge는 특정 터미널에 암호화되어 바인딩됩니다. DEK 파생에는 터미널 공개 키의 hash이 통합되어 있습니다. Badge은(는) 다른 reader에서는 유효하지 않습니다. 보안 수준이 높은 공간, 데이터 센터 랙, 장비 캐비닛.
각 tenant에는 자체 node 플릿, badge 레지스트리, 그룹 트리 및 자격 테이블 등 격리된 네임스페이스가 있습니다. Tenant A에 등록된 badge은 Tenant B에 속한 node로 확인할 수 없습니다. Tenant 격리는 애플리케이션 논리만을 통하지 않고 데이터베이스 쿼리 수준에서 시행됩니다.
엔드포인트방법역할
identity_tag/it_request_challengePOSTbadge 확인을 위한 nonce 발행
identity_tag/it_verify_badgePOSTEd25519 서명을 확인하고 GRANTED/DENIED을 반환합니다.
identity_tag/it_node_checkinPOSTNode 하트비트 및 JWT 새로고침
identity_tag/it_register_badgePOST (manager)badge 공개 키 및 자격 부여 쓰기
identity_tag/it_list_nodesGET (manager)tenant의 Node 차량 상태

프로비저닝 및 관리 앱은 Android에서 실행됩니다. 장치의 NFC을 사용하여 badge 페이로드를 작성합니다. 인증된 Identity Layer 채널을 통해 백엔드에 연결됩니다.

Dart / Flutter: badge 쓰기
// identity_tag package - badge provisioning
final writer = IdentityTagWriter(api: tagApi);

// Generate badge keypair and encrypt private key with split DEK
final payload = await writer.prepareBadgePayload(
  tenantId  : tenant.id,
  mode      : BadgeMode.STD,   // or BadgeMode.HS
  nodeUid   : null,              // required for HS mode
);

// Write NDEF to NTAG424 DNA via flutter_nfc_kit
await writer.writeToTag(payload);

장치 바인딩 ID.
4번의 통화.

로컬 패키지. 외부 ID 서비스가 없습니다. 개인 키는 절대 장치 외부로 유출되지 않습니다. 안전한 저장을 통해 flutter_secure_storage 사용 가능한 경우 TEE / Secure Enclave. 페이로드 암호화는 다음을 통해 엔드투엔드 방식으로 수행됩니다. ITEMSEncrypter.

identity_package identity_std identity_hs items_crypto items_search items_document_body
모든 패키지는 로컬입니다. ID 계층에는 pub.dev 종속성이 없습니다. SDK는 라이센스 패키지의 일부로 배포됩니다.
Dart / Flutter
// 1. Init — JWT identity, silent on subsequent boots
final auth = IdentityAuthServiceStd(ITEMSGlobals.authURI);
await auth.ensureJwt(
  preferredLocale: locale.languageCode,
  utcOffsetMin:    DateTime.now().timeZoneOffset.inMinutes,
);

// 2. Handshake — silent if identity already present on device
final result = await api.mjHandshake(
  identityHash: identityHash,
  publicKey:    publicKey,
);

// 3. Store JWT — session active, no password, no credential database
await _storage.write(key: 'token', value: result['token']);

// 4. Every request — AES-256-GCM payload, end-to-end encrypted
final response = await api.postEncrypted({'request': 'your_request'});
YAML
dependencies:

  # Identity Layer — local packages, no external registry
  identity_package:
    path: packages/identity_package
  identity_std:
    path: packages/identity_std
  identity_hs:
    path: packages/identity_hs
  items_crypto:
    path: packages/items_crypto
플랫폼상태안전한 저장
기계적 인조 인간생산, Google Play 삭제됨Android 키스토어 / TEE
윈도우생산, Microsoft Store 삭제됨Windows 자격 증명 관리자
리눅스생산libsecret
iOS/맥OS로드맵 중Secure Enclave

5KB.
스택은 변경되지 않습니다.

PHP bridge은 기존 엔드포인트 앞에 있는 단일 요구 사항입니다. 경로, 데이터베이스, 비즈니스 로직. 손길이 닿지 않은.. Identity Layer은 인증 및 페이로드 암호화를 처리합니다. 추가한 것과 같은 방식으로 제거합니다.

드롭인, 드롭아웃. 하나 require_once 그리고 두 개의 함수 호출. 엔드포인트는 확인되고 해독된 페이로드를 수신하기 시작합니다. 스키마 마이그레이션이 없습니다. 사용자 테이블은 변경되지 않습니다. 세션 저장 공간이 없습니다. 완전한 서버 측 스택은 다음과 같습니다. 225KB.
PHP
// 1. Include the Identity Layer bridge — 5 KB
require_once 'identity/_mj_auth.php';

// 2. Authenticate — JWT verified, identity_hash extracted
//    identity_hash is a 64-char SHA-256 hex — never a user ID
[$identityHash, $tenantId, $claims, $role] =
    mj_authenticate_identity($encoder);

// 3. Every response — AES-256-GCM encrypted, end-to-end
sendEncryptedResponse($encoder, [
    'status' => 'ok',
    'data'   => $yourData,
], ['ts' => time()], 200);
감사 로그가 존재하지만 암호화 방식으로 액세스할 수 없습니다. 액세스하려면 검증된 법원 명령이 필요합니다. 그만큼 mj_mandate_log 끝점 위임장을 등록하고 72시간 내보내기 창을 엽니다. 로그는 수집 후 파기됩니다. 요청하는 기관이 법적인 책임을 집니다.
PHP: mj_mandate_log
// Requires role = admin — never operator
[$userId, $tenantId, $claims, $role] = mj_authenticate($encoder);
mj_require_role($encoder, $claims, 'admin');

// Register mandate — opens 72h export window
// target_identity_hash: 64-char SHA-256, never plaintext identity
// Ciphertext is never stored — metadata only
$connector->executeDatabaseParameterQuery(
    "INSERT INTO audit_log (mandate_number, issuing_country,
     issuing_court, target_identity_hash, export_status)
     VALUES (?, ?, ?, ?, 'PENDING')",
    [$mandateNumber, $issuingCountry, $issuingCourt, $targetHash],
    $db
);
요소기술메모
실행 시간PHP 8.x바닐라, 프레임워크 필요 없음
데이터 베이스MySQL / 마리아DB표준 스키마, 자격 증명 열 없음
캐시/임시Redis챌린지 토큰, 메시지 대기열(TTL < 1분)
교량 크기5KB단일 PHP 파일, 임의의 LAMP 스택에 놓기
전체 스택 크기225KBID STD + HS + 키 + 보안 채널 + IoT + 라벨 + 태그
전개컨테이너 / 온프레미스 / air-gapped필수 클라우드 연결 없음