보안
OPC UA 보안은 세 가지를 지킵니다(Part 2, 보안 모델).
- 응용 프로그램 인증(application authentication): 클라이언트와 서버가 응용 프로그램 인스턴스 인증서(application instance certificate)로 서로를 확인합니다.
- 메시지 보안(message security): 보안 채널의 메시지를 서명하거나 서명하고 암호화합니다.
- 사용자 인증과 권한(user authentication and authorization): 세션을 활성화할 때 사용자를 확인하고, 노드마다 접근을 허용하거나 거부합니다.
보안 정책
섹션 제목: “보안 정책”보안 정책(SecurityPolicy)은 보안 채널에서 쓰는 알고리즘의 묶음입니다. Part 7이 정책마다 URI와 알고리즘을 정의합니다. PDComm은 다음 정책을 지원합니다.
| 보안 정책 | 비대칭 서명 | 비대칭 암호화 | 대칭 암호화 | 대칭 서명 |
|---|---|---|---|---|
| None | 없음 | 없음 | 없음 | 없음 |
| Basic256Sha256 | RSA PKCS#1 v1.5, SHA-256 | RSA-OAEP(SHA-1) | AES-256-CBC | HMAC-SHA256 |
| Aes128_Sha256_RsaOaep | RSA PKCS#1 v1.5, SHA-256 | RSA-OAEP(SHA-1) | AES-128-CBC | HMAC-SHA256 |
| Aes256_Sha256_RsaPss | RSA-PSS, SHA-256 | RSA-OAEP(SHA-256) | AES-256-CBC | HMAC-SHA256 |
정책 URI는 http://opcfoundation.org/UA/SecurityPolicy# 뒤에 정책 이름을 붙인 형식입니다. 예를 들어 Aes256_Sha256_RsaPss는 http://opcfoundation.org/UA/SecurityPolicy#Aes256_Sha256_RsaPss입니다. RSA 키 길이는 2048~4096비트여야 합니다. 폐기된 Basic128Rsa15와 Basic256 정책은 지원하지 않습니다.
PDComm SDK의 기본 정책은 Aes256_Sha256_RsaPss입니다. C 상수와 .NET 값은 다음과 같습니다.
| 보안 정책 | C 상수 | .NET 값 |
|---|---|---|
| None | PDCOMM_OPCUA_POLICY_NONE |
SecurityPolicy.None |
| Basic256Sha256 | PDCOMM_OPCUA_BASIC256SHA256 |
SecurityPolicy.Basic256Sha256 |
| Aes128_Sha256_RsaOaep | PDCOMM_OPCUA_AES128SHA256RSAOAEP |
SecurityPolicy.Aes128Sha256RsaOaep |
| Aes256_Sha256_RsaPss | PDCOMM_OPCUA_AES256SHA256RSAPSS |
SecurityPolicy.Aes256Sha256RsaPss |
보안 모드
섹션 제목: “보안 모드”보안 모드(MessageSecurityMode)는 정책을 어디까지 적용할지 정합니다.
| 보안 모드 | 값 | 의미 |
|---|---|---|
| None | 1 | 서명도 암호화도 하지 않습니다. 보안 정책 None과만 함께 씁니다. |
| Sign | 2 | 메시지에 서명합니다. 내용은 보이지만 위조를 막습니다. |
| SignAndEncrypt | 3 | 서명하고 암호화합니다. PDComm SDK의 기본값입니다. |
서버는 엔드포인트마다 정책과 모드의 조합을 광고합니다. PDComm 시뮬레이터는 엔드포인트에 보안 수준(security level)을 None 0, Sign 20, SignAndEncrypt 30으로 붙입니다. 클라이언트는 보통 수준이 가장 높은 엔드포인트를 고릅니다.
PDComm SDK 클라이언트는 요청한 정책과 모드를 서버가 광고하지 않으면 다른 조합으로 바꾸지 않고 연결을 거부합니다. 이때 오류 문장은 Requested OPC UA endpoint not advertised입니다. None 정책은 클라이언트와 서버 모두 PDCOMM_OPCUA_ALLOW_NONE 플래그를 설정해야 씁니다.
응용 프로그램 인스턴스 인증서
섹션 제목: “응용 프로그램 인스턴스 인증서”OPC UA 응용 프로그램은 설치된 인스턴스마다 X.509 v3 인증서와 개인 키를 가집니다(Part 6, 응용 프로그램 인스턴스 인증서). 보안 채널을 열 때 양쪽이 인증서를 교환하고, 상대의 인증서를 검증합니다. PDComm은 다음 조건을 검사합니다.
| 항목 | 조건 |
|---|---|
| 키 | RSA 2048~4096비트 |
| 서명 알고리즘 | SHA-256, SHA-384 또는 SHA-512를 쓰는 RSA 서명 |
| 주체(subject) | CN과 O가 비어 있지 않음 |
| subjectAltName URI | 정확히 하나. 응용 프로그램의 ApplicationUri와 같아야 함 |
| subjectAltName DNS·IP | 서버 인증서에 하나 이상. 클라이언트가 endpoint URL에 쓰는 호스트와 일치해야 함 |
| keyUsage | digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment. 자체 서명이면 keyCertSign도 포함 |
| extendedKeyUsage | 서버는 serverAuth, 클라이언트는 clientAuth |
| 유효 기간 | 현재 시각이 notBefore와 notAfter 사이 |
ApplicationUri는 응용 프로그램을 식별하는 URI입니다. PDComm의 기본값은 클라이언트 urn:pdcomm:opcua:client, 서버 urn:pdcomm:opcua:server입니다. 인증서의 URI와 연결 옵션의 ApplicationUri가 다르면 CertificateUriInvalid 오류가 납니다.
인증서가 올바른 형식이어도 신뢰하지 않으면 연결을 거부합니다. 신뢰 판단과 검증 순서는 Part 4의 인증서 검증 절(Table 100)이 정의합니다. PDComm은 구조 검사, 인증서 경로 구성, 서명, 보안 정책 요건, 신뢰 목록, 유효 기간, 호스트 이름(서버 인증서만), URI, 용도, 폐기 목록 순서로 검사합니다.
PDComm은 신뢰를 명시적으로 설정합니다. 자동으로 신뢰하는 인증서는 없습니다.
| 구성 요소 | 신뢰 설정 |
|---|---|
| SDK 클라이언트 | trusted_server_der(.NET TrustedServerDer)에 지정한 서버 인증서 하나 |
| SDK 서버 | trusted_client_der(.NET TrustedClientDer)에 지정한 클라이언트 인증서 하나 |
| 시뮬레이터 서버 | 구성의 server.trust 목록(DER 또는 PEM 파일)과 시뮬레이터 자신의 클라이언트 인증서 |
| 시뮬레이터 클라이언트 | 구성의 client.trust 목록과 같은 시뮬레이터에서 실행 중인 서버의 인증서 |
규모가 큰 설비에서는 인증 기관(CA)과 전역 탐색 서버(Global Discovery Server)로 인증서와 신뢰 목록을 관리합니다(Part 12). PDComm 예제는 응용 프로그램마다 자체 서명 인증서를 만들고 상대 인증서를 직접 신뢰하는 방식을 씁니다. PKI와 신뢰 설정에서 실습합니다.
사용자 ID 토큰
섹션 제목: “사용자 ID 토큰”세션을 활성화하는 ActivateSession 요청에는 사용자 ID 토큰(user identity token)이 들어갑니다(Part 4, UserIdentityToken 매개변수). 서버는 엔드포인트마다 받을 토큰 종류를 사용자 토큰 정책(UserTokenPolicy)으로 광고합니다.
| 토큰 | 설명 |
|---|---|
| AnonymousIdentityToken | 사용자를 밝히지 않습니다. |
| UserNameIdentityToken | 사용자 이름과 암호를 보냅니다. 암호는 서버 인증서의 공개 키로 암호화합니다. |
| X509IdentityToken | 사용자 인증서와 서명을 보냅니다. |
| IssuedIdentityToken | 외부 인증 서비스가 발급한 토큰을 보냅니다. |
PDComm SDK 클라이언트와 시뮬레이터는 AnonymousIdentityToken과 UserNameIdentityToken을 쓰고, SDK 서버는 AnonymousIdentityToken을 받습니다.
암호 암호화 형식은 두 가지입니다. 64바이트 이하의 암호는 기존 RSA 암호화 토큰 형식으로 보내고, 그보다 긴 암호는 EncryptedSecret 형식으로 보냅니다. EncryptedSecret 형식에서 토큰의 encryptionAlgorithm을 비우려면 PDCOMM_OPCUA_USER_SECRET_HEADER_POLICY_ONLY 플래그를 씁니다. 이 형식을 기대하는 서버에만 설정합니다.
PDComm 클라이언트는 보안 정책 None 채널에서는 암호를 보내지 않습니다. 시뮬레이터 서버도 None 엔드포인트에는 익명 토큰만 광고합니다.
권한과 잠금
섹션 제목: “권한과 잠금”사용자 인증이 끝나도 노드마다 접근 권한이 다릅니다. PDComm 서버는 변수를 공개(public) 변수와 인증된 사용자 전용 변수로 나눕니다. 익명 세션이 전용 변수를 읽거나 쓰면 항목 결과가 BadUserAccessDenied(0x801F0000)입니다.
PDComm 서버는 같은 클라이언트(인증서 또는 보안 없는 연결의 IP 주소)의 사용자 인증이 5번 연속 실패하면 그 클라이언트를 10분 동안 잠급니다. 잠긴 동안에는 올바른 암호도 BadUserAccessDenied로 거부합니다. 시뮬레이터는 서버를 다시 시작하면 잠금이 풀립니다.