01. OVERVIEW
개요
coForward Virtual Keyboard
TouchEn nxKey, INISAFE CrossWeb EX 등 설치형 한국 금융 보안 키패드를 대체하는 웹 표준 기반 보안 가상키패드 SDK입니다. ActiveX·EXE 설치 없이 모든 현대 브라우저에서 동작합니다.
- 암호화 알고리즘
- AES-256-GCM
- 키 교환
- RSA-OAEP
- 지원 키패드
- 3종
- 외부 의존성
- 0개
핵심 보안 원칙
- 키 값 미노출: 모든 키는 Canvas에만 렌더링, DOM에 평문 미노출!
- Shadow DOM 격리: 외부 스크립트가 키패드 내부 상태에 접근 불가
- 하이브리드 암호화: AES-256-GCM + RSA-OAEP 세션별 독립 암호화
- 재전송 방지: 세션 UUID + 타임스탬프 + nonce 서버 검증
- 무작위 배치: 숫자 키패드는 매 세션 Fisher-Yates 셔플 적용
프로젝트 구조
coforward-virtual-keyboard/
├── src/ # 클라이언트 SDK (JavaScript)
│ ├── core/ # 핵심 로직
│ │ ├── crypto.js # AES-256-GCM + RSA-OAEP
│ │ ├── keypad.js # Canvas 렌더링 엔진
│ │ └── session.js # 세션 관리
│ ├── keypads/ # 키패드 레이아웃
│ │ ├── numeric.js
│ │ ├── english.js
│ │ └── korean.js
│ └── index.js # 공개 API 진입점
├── server/ # Java Spring Boot 서버
│ ├── coforward-vk-core/ # 핵심 도메인 로직
│ ├── coforward-vk-spring/ # Spring Boot 자동 설정
│ └── coforward-vk-demo/ # 데모 서버
└── dist/ # 빌드 산출물
├── coForward-virtual-keypad.js # UMD 번들
└── coForward-virtual-keypad.esm.js
02. QUICK START
빠른 시작
3단계만 완료하면 보안 키패드가 동작합니다.
1단계 — 스크립트 포함
<!-- UMD (CDN / 직접 포함) -->
<script src="dist/coForward-virtual-keypad.js"></script>
2단계 — 필드에 속성 추가
<!-- autoInit()이 자동으로 키패드를 연결합니다 -->
<input type="text" data-coForward-vk="numeric" placeholder="비밀번호" />
<input type="text" data-coForward-vk="english" placeholder="영문 ID" />
<input type="text" data-coForward-vk="korean" placeholder="한글 입력" />
3단계 — 서버 설정 (Spring Boot)
@SpringBootApplication
@EnableCoForwardVK
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@EnableCoForwardVK가 /api/vk/session, /api/vk/submit 엔드포인트를 자동으로 등록하고 RSA 키 쌍을 생성합니다.
03. INSTALLATION
설치 방법
npm 패키지
npm install coforward-virtual-keyboard
ESM import
import CoForwardVK from 'coforward-virtual-keyboard';
Maven (서버)
<dependency>
<groupId>com.coforward</groupId>
<artifactId>coforward-vk-spring</artifactId>
<version>1.0.0</version>
</dependency>
04. SDK API
SDK API 레퍼런스
CoForwardVK.init(options)
키패드 인스턴스를 생성하고 반환합니다.
| 옵션 | 타입 | 필수 | 설명 |
|---|---|---|---|
target |
string | HTMLElement |
필수 | 키패드를 연결할 입력 필드 선택자 또는 DOM 요소 |
type |
'numeric' | 'english' | 'korean' |
필수 | 키패드 종류 지정 |
sessionUrl |
string |
선택 | 세션 발급 API URL. 기본값: /api/vk/session |
onSubmit |
(encrypted: string) => void |
선택 | 암호화 완료 시 콜백. 암호문 Base64 문자열 전달 |
onOpen |
() => void |
선택 | 키패드가 열릴 때 호출되는 콜백 |
onClose |
() => void |
선택 | 키패드가 닫힐 때 호출되는 콜백 |
theme |
object |
선택 | CSS 변수 덮어쓰기 객체 (아래 CSS 커스터마이징 참고) |
CoForwardVK.autoInit()
DOM에서 data-coForward-vk 속성이 있는 모든 필드를 찾아 자동으로 키패드를 연결합니다.
SDK 스크립트가 로드되면 DOMContentLoaded 이벤트 후 자동 실행됩니다.
인스턴스 메서드
| 메서드 | 반환값 | 설명 |
|---|---|---|
.open() |
void |
키패드를 열고 새 세션을 발급합니다 |
.close() |
void |
키패드를 닫습니다 |
.clear() |
void |
입력된 값을 모두 지웁니다 |
.getEncrypted() |
Promise<string> |
현재 입력값을 암호화한 Base64 문자열을 반환합니다 |
.destroy() |
void |
키패드 인스턴스를 제거하고 이벤트 리스너를 정리합니다 |
05. KEYPAD TYPES
키패드 종류
숫자 키패드
type="numeric"
매 세션마다 0–9 키 배치를 Fisher-Yates 알고리즘으로 무작위 셔플합니다. 화면 캡처·좌표 기반 공격을 방어합니다.
영문 키패드
type="english"
고정 QWERTY 레이아웃. 대소문자 전환(Shift/Caps)과 특수문자를 지원합니다.
한글 키패드
type="korean"
두벌식 자판 레이아웃. 자음·모음 조합 로직을 내장해 완성된 한글 문자를 생성합니다.
numeric 키패드는 세션 ID 기반으로 무작위 배치를 결정합니다. 서버가 배치 정보를 알고 있어 암호화 없이도 순서 검증이 가능합니다.
06. SERVER API
서버 API
세션 발급
RSA 공개키와 세션 UUID를 발급합니다. 클라이언트 SDK가 자동으로 호출합니다.
응답 (200 OK)
{
"sessionId": "550e8400-e29b-41d4-a716-446655440000",
"publicKey": "-----BEGIN PUBLIC KEY-----\n...",
"expiresAt": 1735689600000,
"keypadSeed": 42
}
암호문 제출
암호화된 입력값을 서버에서 복호화합니다.
요청 본문
| 필드 | 타입 | 설명 |
|---|---|---|
sessionId |
string |
세션 발급 시 받은 UUID |
encryptedKey |
string |
RSA-OAEP로 암호화된 AES 키 (Base64) |
encryptedData |
string |
AES-256-GCM으로 암호화된 입력값 (Base64) |
iv |
string |
AES-GCM 초기화 벡터 (Base64) |
timestamp |
number |
클라이언트 타임스탬프 (ms, 재전송 방지용) |
응답 (200 OK)
{
"success": true,
"plaintext": "1234"
}
응답의 plaintext를 로그에 기록하거나 DB에 평문으로 저장하지 마세요. 반드시 즉시 처리 후 폐기해야 합니다.
07. SPRING BOOT
Spring Boot 연동
자동 설정 활성화
@SpringBootApplication
@EnableCoForwardVK
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
application.yml 설정
coforward:
vk:
rsa-key-size: 2048 # RSA 키 크기 (2048 | 4096)
session-ttl-seconds: 300 # 세션 유효 시간 (초)
allowed-origins:
- "https://yourapp.com"
timestamp-tolerance-ms: 30000 # 타임스탬프 허용 오차
수동 서비스 사용
@RestController
public class LoginController {
private final VirtualKeypadService vkService;
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest req) {
String plainPassword = vkService.decrypt(
req.getSessionId(),
req.getEncryptedKey(),
req.getEncryptedData(),
req.getIv()
);
// plainPassword 즉시 처리 후 폐기
return authService.authenticate(req.getUsername(), plainPassword);
}
}
08. CSS CUSTOMIZATION
CSS 커스터마이징
키패드의 모든 시각적 요소는 CSS 커스텀 프로퍼티(--coForward-vk-*)로 제어합니다.
별도 설정 없이 CSS 변수 덮어쓰기만으로 완전한 커스터마이징이 가능합니다.
주요 CSS 변수
--coForward-vk-bg키패드 배경색--coForward-vk-key-bg키 배경색--coForward-vk-key-hover키 호버 색--coForward-vk-key-active키 클릭 색--coForward-vk-key-color키 텍스트 색--coForward-vk-border키 테두리 색--coForward-vk-radius모서리 둥글기--coForward-vk-font-size키 글자 크기--coForward-vk-width키패드 너비--coForward-vk-shadow키패드 그림자
CSS 덮어쓰기 예시
/* 다크 테마 */
:root {
--coForward-vk-bg: #1a1a2e;
--coForward-vk-key-bg: #16213e;
--coForward-vk-key-hover: #0f3460;
--coForward-vk-key-color: #e0e0e0;
--coForward-vk-radius: 8px;
}
JavaScript 테마 주입
CoForwardVK.init({
target: '#password',
type: 'numeric',
theme: {
'--coForward-vk-bg': '#1a1a2e',
'--coForward-vk-key-bg': '#16213e',
'--coForward-vk-key-color': '#e0e0e0',
}
});
09. SECURITY
보안 고려사항
RSA 공개키 교환 및 암호문 전송은 반드시 HTTPS(TLS 1.2+)에서 이루어져야 합니다. HTTP 환경에서는 보안이 보장되지 않습니다.
보안 체크리스트
- ✅ 서버 RSA 개인키는 환경 변수나 Vault에 보관 — 소스코드에 포함 금지
- ✅ 세션 TTL을 짧게 유지 (권장: 300초 이내)
- ✅
timestamp-tolerance-ms를 30초 이내로 설정해 재전송 공격 방지 - ✅
/api/vk/submit응답의plaintext를 로그에 기록하지 않음 - ✅ 복호화된 평문을 DB에 저장하지 않음 (해시 후 저장)
- ✅ CORS
allowed-origins를 프로덕션 도메인으로 제한 - ✅ CSP(Content-Security-Policy) 헤더 설정으로 XSS 추가 방어
알려진 제한 사항
Canvas 기반 렌더링 특성상 스크린 리더 지원이 제한됩니다. 접근성이 필수인 환경에서는 별도의 대체 입력 수단을 제공하는 것을 권장합니다.
브라우저 지원
| 브라우저 | 최소 버전 | 비고 |
|---|---|---|
| Chrome | 80+ | 완전 지원 |
| Firefox | 78+ | 완전 지원 |
| Safari | 14+ | 완전 지원 |
| Edge | 80+ | 완전 지원 |
| IE 11 이하 | — | 미지원 (Web Crypto API 없음) |