🗓️ 2025. 03. 26
⏱️ 9

Node.js에서 국산 암호화 알고리즘(SEED, ARIA) 사용하기

3줄이면 됩니다

개요

한국에서 공공기관, 금융기관 등과 연동된 시스템을 개발하다 보면 SEEDARIA 같은 국산 암호화 알고리즘을 사용해야 하는 상황을 접하게 됩니다. 하지만 이 알고리즘들은 해외에서는 (사실상) 사용되지 않기 때문에, 한국인터넷진흥원(KISA)이 제공하는 구현체에 의존해야 합니다.

문제는 그 구현체 수가 몹시 한정적이라는 것입니다. SEED 구현체는 24년 연말에 추가된 Python을 포함해 C/C++, Java, ASP, JSP, PHP 총 6개의 언어만 제공되며 ARIA는 C/C++, Java로 2개뿐입니다. Node.js 환경에서 이용하고자 검색을 해보면 공식 구현체가 없기 때문에 Java 구현체를 보고 포팅하거나 Java 프로세스를 띄워 해결하는 방법들을 찾을 수 있습니다.

하지만 놀랍게도 Node.js의 내장 모듈인 crypto만으로도 SEED와 ARIA 알고리즘을 사용할 수 있습니다.

이를 알리는 글을 찾을 수 없어 이번 기회에 공유하고자 글을 작성하게 됐습니다.
이 글에서는 Node.js 환경에서 국산 암호화 알고리즘을 사용하는 가장 간단하고 안전한 방법을 소개합니다.

crypto와 OpenSSL

Node.js의 내장 모듈 중 하나인 crypto는 암호화를 담당합니다. 내부적으로 OpenSSL을 사용하기 때문에 OpenSSL에서 지원하는 암호화 알고리즘은 Node.js에서도 사용할 수 있는데, 여기서 중요한 건 OpenSSL에서 SEED와 ARIA도 지원한다는 사실입니다.

요컨대 Node.js의 crypto 모듈에서도 SEED와 ARIA를 직접 사용할 수 있다는 거죠.
그런데 정작 사용해보면 지원되지 않는 것처럼 보입니다.

타입때문에 AES만 지원되는 것처럼 보인다타입때문에 AES만 지원되는 것처럼 보인다

하지만 이건 그저 자동 완성되는 타입일 뿐이고, 실제로 사용할 수 있는 알고리즘 목록은 다음과 같이 확인할 수 있습니다.

import crypto from 'node:crypto';

const supportedAlgorithms = crypto.getCiphers();
console.log(supportedAlgorithms);
// [
//     'aes-128-cbc',       'aes-128-ccm',       'aes-128-cfb',
//     'aes-128-cfb1',      'aes-128-cfb8',      'aes-128-ctr',
//     'aes-128-ecb',       'aes-128-gcm',       'aes-128-ocb',
//     'aes-128-ofb',       'aes-128-xts',       'aes-192-cbc',
//     'aes-192-ccm',       'aes-192-cfb',       'aes-192-cfb1',
//     'aes-192-cfb8',      'aes-192-ctr',       'aes-192-ecb',
//     'aes-192-gcm',       'aes-192-ocb',       'aes-192-ofb',
//     'aes-256-cbc',       'aes-256-ccm',       'aes-256-cfb',
//     'aes-256-cfb1',      'aes-256-cfb8',      'aes-256-ctr',
//     'aes-256-ecb',       'aes-256-gcm',       'aes-256-ocb',
//     'aes-256-ofb',       'aes-256-xts',       'aes128',
//     'aes128-wrap',       'aes192',            'aes192-wrap',
//     'aes256',            'aes256-wrap',       'aria-128-cbc',
//     'aria-128-ccm',      'aria-128-cfb',      'aria-128-cfb1',
//     'aria-128-cfb8',     'aria-128-ctr',      'aria-128-ecb',
//     'aria-128-gcm',      'aria-128-ofb',      'aria-192-cbc',
//     'aria-192-ccm',      'aria-192-cfb',      'aria-192-cfb1',
//     'aria-192-cfb8',     'aria-192-ctr',      'aria-192-ecb',
//     'aria-192-gcm',      'aria-192-ofb',      'aria-256-cbc',
//     'aria-256-ccm',      'aria-256-cfb',      'aria-256-cfb1',
//     'aria-256-cfb8',     'aria-256-ctr',      'aria-256-ecb',
//     'aria-256-gcm',      'aria-256-ofb',      'aria128',
//     'aria192',           'aria256',           'camellia-128-cbc',
//     ...
//   ]

벌써 ARIA가 보이네요! 곧바로 사용해볼까요?

Node.js에서 사용하기

사용법은 아주 단순합니다. 그저 crypto 모듈을 사용해 암/복호화를 수행하면 끝입니다.

import crypto from 'node:crypto';

// 암호화
function encrypt(plainText: string, key: crypto.CipherKey, iv: crypto.BinaryLike) {
  const cipher = crypto.createCipheriv('area-128-cbc', key, iv);
  
  let encrypted = cipher.update(plainText, 'utf8', 'base64');
  encrypted += cipher.final('base64');
  
  return encrypted;
}

// 복호화
function decrypt(encrypted: string, key: crypto.CipherKey, iv: crypto.BinaryLike) {
  const decipher = crypto.createDecipheriv('area-128-cbc', key, iv);
  
  let decrypted = decipher.update(encrypted, 'base64', 'utf8');
  decrypted += decipher.final('utf8');
  
  return decrypted;
}

단 3줄만에 모든 구현이 끝났습니다. 진짜 간단하죠?
이렇게 구현을 마친 함수는 다음과 같이 사용할 수 있습니다.

// 16바이트 (128비트) 키와 IV
const key = Buffer.from('1234567890abcdef');
const iv = Buffer.from('abcdef1234567890');

const plainText = "Hello, ARIA-128-CBC"

const encrypted = encrypt(plainText, key, iv)
const decrypted = decrypt(encrypted, key, iv)

console.log(`🔐 암호문 : ${encrypted}`);
console.log(`🔓 복호문 : ${decrypted}`);
$ node main.js

# 🔐 암호문 : L+EwB2zc2p5J2lntq5v6x8QdPSK7J2QoblPxQ5nMaRk=
# 🔓 복호문 : Hello, ARIA-128-CBC

ARIA가 아닌 SEED를 사용하고 싶다면 앞선 구현 코드에서 알고리즘을 'seed-cbc'로 바꾸기만 하면 됩니다.
그런데... Node.js v17 이후 버전이라면 SEED 알고리즘은 기본적으로 사용할 수가 없습니다.

Node.js v17 이후

사용중인 Node.js 버전이 v17 이후라면 SEED 알고리즘 사용시 아래 에러 메시지를 마주치게 됩니다.

Error: error:0308010C:digital envelope routines::unsupported

말그대로 SEED 알고리즘이 지원되지 않는다는 것이죠.
Node.js 버전 문제이니 곧장 다운그레이드를 떠올릴 수도 있겠지만, 아시다시피 다운그레이드는 결코 좋은 해결책이 아닙니다.
우선 우리는 왜 v17부터 SEED 알고리즘이 지원되지 않는지를 먼저 알아봐야 합니다.

Node.js v17의 릴리즈 노트에는 crypto 모듈의 의존성인 OpenSSL의 버전을 1.1.1에서 3.0으로 업데이트했다는 내용이 있는데, 어떤 변경사항이 있길래 SEED를 사용할 수 없게 된 건지 알아보겠습니다.

OpenSSL 3.0에서는 만들어진지 오래되어 보안에 취약하거나 잘 사용되지 않는 알고리즘들을 모두 legacy로 분류했습니다. 사실상 사용이 권장되지 않는 알고리즘들을 따로 빼둔 것이죠 (공식 문서에서는 암호화 알고리즘의 '요양원'이라고 표현합니다;;)
1999년에 개발된 SEED 알고리즘이 legacy로 분류되는 건 당연한 걸지도 모르겠습니다.

하지만 legacy로 분류됐을 뿐이지 구현 자체가 OpenSSL에서 빠진 것은 아니기 때문에 legacy 옵션을 준다면 사용할 수 있습니다.

# node.js v17 이후
$ node --openssl-legacy-provider main.js

# 🔐 암호문 : HFrNGFIU02tOFt6bUQIokA==
# 🔓 복호문 : Hello, SEED-CBC

다운그레이드 없이 간단히 해결할 수 있었네요!
아무쪼록 이 글이 국내 여러 기관과 함께 힘써주는 개발자분들께 도움이 되길 바랍니다!

번외

비화

OpenSSL에 ARIA 알고리즘이 추가된 계기가 꽤 재밌습니다.

KISA 주도의 커밋 메시지KISA 주도의 커밋 메시지

SEED 알고리즘은 2007년에 KISA 주도로 구현됐는데요, ARIA는 뜬금없이 컴퓨터 공학 박사인 Paul Dale의 주도로 2017년에 구현됐습니다. 당시 Paul Dale은 Oracle에 재직중이었는데 Oracle은 DB에 OpenSSL을 사용할 예정이었고, 마침 한국 고객이 ARIA를 사용해야 했기 때문에 이를 구현했다고 하네요.

ARIA 논의 내역ARIA 논의 내역

명령어 팁

  • Node.js에서 사용중인 OpenSSL 버전 확인하기
$ node -e "console.log(process.versions.openssl)"
# 3.0.15+quic
  • OpenSSL에서 사용할 수 있는 알고리즘 확인하기
$ openssl list -cipher-algorithms | grep SEED
  seed => SEED-CBC
  SEED-CBC
  SEED-CFB
  SEED-ECB
  SEED-OFB
  • OpenSSL에서 직접 암호화하기
# legacy로 인한 오류
$ echo -n "Hello SEED-CBC" | openssl enc -seed -e -K 1234567890abcdef1234567890abcdef -iv abcdef1234567890abcdef1234567890 -p -base64
Error setting cipher SEED-CBC
20B0CD8EFFFF0000:error:0308010C:digital envelope routines:inner_evp_generic_fetch:unsupported:../crypto/evp/evp_fetch.c:386:Global default library context, Algorithm (SEED-CBC : 53), Properties ()

# legacy 옵션 부여
$ echo -n "Hello SEED-CBC" | openssl enc -seed -e -K 1234567890abcdef1234567890abcdef -iv abcdef1234567890abcdef1234567890 -p -base64 -provider legacy
salt=0015FE31B10CE33C
key=1234567890ABCDEF1234567890ABCDEF
iv =ABCDEF1234567890ABCDEF1234567890
HPCofnp3k26s+h8fQdeabw==

참고

돌아가기
© 2025 VERYCOSY.