Search

kms로 key관리하기

배경

회사의 DB 데이터 중 암호화하여 보안을 철저히 해야 하는 정보들의 대다수가 평문으로 저장되어 있어 보안상으로 취약한 부분이 발견되었다.
암호화를 해야 할 데이터들을 전수조사하고 암호화 전략을 세웠다.
암/복호화 하는데 사용하는 키는 AWS의 KMS를 사용하여 관리하도록 결정되었다.
KMS의 이점은 다음과 같다.
1.
높은 보안성
HSM 사용
FIPS 140-2 인증된 HSM에서 키를 생성하고 보호하여 키의 기밀성을 보장
키는 AWS 내부에서만 사용되며 절대 외부로 유출되지 않음.
관리가 용이하다.
모든 키가 KMS 중앙에서 관리되며 접근 제어 및 로깅이 일관되게 적용되어 관리가 편하다.
키 정책 및 IAM 적용
AWS IAM 정책을 적용하여 세밀한 권한 제어가 가능하다.
2.
감사 및 추적 가능
모든 키 사용이 AWS CloudTrail에 기록되어 보안 감사 및 문제 발생 시 원인 추적이 가능하다.
3.
자동화 및 운영 효율성
자동화된 Key Rotation
설정된 주기에 따라 키가 자동으로 갱신되어 수동으로 관리할 필요가 없음
다양한 AWS 서비스와 연계 가능
S3, EBS, RDS, API GATEWAY 등 다양한 서비스에서 KSM 키를 직접 사용 가능하다.

주요 전략

암/복호화 시 비용 최적화를 위해 AWS KMS에 키를 매번 호출하지 않기
암/복호화를 모두 시스템 내부에서 처리 하여 네트워크 Latency 최소화
키 유출 위험을 제거해야 한다.
위 전략을 수행하기 위한 흐름도는 다음과 같다.
1.
KMS로 암호화된 마스터키 복호화 (최초 1회)
2.
마스터키 앱 메모리에 보관
3.
SHA-256으로 파생키 생성 (masterKey + context)
4.
AEC-CBC 방식으로 처리

NestJS로 AWS KMS 연동하기

1. AWS SDK 설치

nestjs에서 AWS KMS와 통신하려면 AWS SDK (@aws-sdk/client-kms) 를ㄹ 설치해야 한다.
@aws-sdk/client-kms
TypeScript
복사

2.

// value: 암호화할 데이터, context: 키 파생에 사용할 문자열 ex)'user:phone', fixedIv?: 고정 IV를 사용할 경우 전달 encrypt(value: string, context: string, fixedIv?: string): string { const key = this.deriveKey(context); // context를 이용해 마스터키로부터 SHA-256 해시를 적용하여 AES 키를 파생 const iv = fixedIv ? Buffer.from(fixedIv, 'utf-8').subarray(0, 16) : randomBytes(16); const cipher = createCipheriv('aes-256-cbc', key, iv); // 암호화 객체 생성 const encrypted = Buffer.concat([ cipher.update(value, 'utf-8'), // 평문을 일부 암호화 cipher.final(), // 남은 데이터를 암호화하고 padding 처리 ]); const combined = Buffer.concat([iv, encrypted]); // 복호화 시 IV를 앞부분에서 분리해낼 수 있도록 구성 return combined.toString('base64'); // Base64 인코딩하여 문자열로 반환 }
TypeScript
복사