본문으로 건너뛰기
yceffort
PostsSeriesTagsAbout🧪 Research
EN

Tweaks

theme
accent palette
film grain
minimal mode
BACK TO INDEX
◆ ESSAY
--min
--year
KOoriginal

mailMail icongithubtwitter
yceffort
•
© 2026
•
https://yceffort.kr
BACK TO INDEX
◆ ESSAY

Nodejs에서의 암/복호화

avatar
yceffort
2020-06-09 · 3분
3min
2020year
KOoriginal
nodejssecurity

Nodejs에서의 암호화와 복호화

만약 같은 텍스트로 암호화를 동일하게 시도했을 때, 암호화된 결과가 동일하게 나온다면 이 암호화는 굉장히 약한 암호화라 볼 수 있다. 강력한 암호화는 매번 암호화를 시도할 때마다 (설령 같은 텍스트라 할지라도) 다른 결과가 나와야 한다.

물론, 어쨌든 암호화 되어 있다는 사실 만으로도 만족할 수도 있다. 그러나 공격자가 암호화된 데이터에 접근했을 때 유사한 패턴을 찾게 된다면 그것으로 패턴을 분석할 수 있게 된다. 공격자가 입력한 텍스트가 동일하게 암호화 되었고, 그 암호화된 텍스트가 DB에서 발견 된다면, 그 텍스트는 추론할 수 있게 되며 더 이상 암호화는 유효하지 않게 된다. 따라서 암호화된 출력이 항상 다르게 하기 위해서는, 임의성 (randomness)을 추가해야 한다.

암호화가 매번 다른 결과를 만들어 주는 것이 Initialize Vector (IV) 초기화 벡터이다. 암호화 알고리즘에 IV를 추가하여 위에서 언급한 임의성을 얹을 수 있고, 이 임의성은 암호화가 매번 다른 결과를 만들수 있도록 도와 준다. 강력한 암호화를 위해서는, 매번 암호화를 시도할 때마다 서로다른 랜덤값을 IV로 제공해야 한다. 이는 암호 해싱의 salt와 유사하다.

단순함을 유지하면서, 암호화된 데이터에 대한 단일 데이터베이스 필드와 값을 사용하기 위해, 암호화전에 IV를 준비하여 암호화된 결과에 맞게 준비한다. 그런 다음, 암호를 해독하기전에, IV를 읽고 이를 키와 함께 사용하면 된다.

'use strict'

const crypto = require('crypto')

const ENCRYPTION_KEY =
  process.env.ENCRYPTION_KEY || 'abcdefghijklmnop'.repeat(2) // Must be 256 bits (32 characters)
const IV_LENGTH = 16 // For AES, this is always 16

function encrypt(text) {
  const iv = crypto.randomBytes(IV_LENGTH)
  const cipher = crypto.createCipheriv(
    'aes-256-cbc',
    Buffer.from(ENCRYPTION_KEY),
    iv,
  )
  const encrypted = cipher.update(text)

  return (
    iv.toString('hex') +
    ':' +
    Buffer.concat([encrypted, cipher.final()]).toString('hex')
  )
}

function decrypt(text) {
  const textParts = text.split(':')
  const iv = Buffer.from(textParts.shift(), 'hex')
  const encryptedText = Buffer.from(textParts.join(':'), 'hex')
  const decipher = crypto.createDecipheriv(
    'aes-256-cbc',
    Buffer.from(ENCRYPTION_KEY),
    iv,
  )
  const decrypted = decipher.update(encryptedText)

  return Buffer.concat([decrypted, decipher.final()]).toString()
}

const text = 'hello my name is yceffort'
const encryptResult = encrypt(text)
console.log('encrypt result:', encryptResult)

const decryptResult = decrypt(encryptResult)
console.log('decrypt result:', decryptResult)
encrypt result: bad1fdcaa253c63bc3c8a5aadb7d8913:97a0a7ab35c84d3e52b56afeb717ad888669c67132cc97f941f7969ec52a1732
decrypt result: hello my name is yceffort

여기의 코드를 참고했다.

IV에 대해서 설명하려면 한도 끝도 없고 내 두뇌 용량도 초과하므로, 자세한 설명은 생략하지만 서도 - 암호화를 할 때 꼭꼭꼭꼮 IV를 쓰도록 하자. 이미 nodejs의 crypto 라이브러리에서는 iv 를 쓰지 않는 코드는 deprecated 되었다.

관련 글

  • #nodejs#security#javascript

    Node.js vm 모듈의 함정: 샌드박스가 아닌 이유

    집필 중인 Node.js Deep Dive의 5.2장(vm 모듈의 함정) 일부를 미리 공개합니다.

    2026-02-27·25분
  • #nodejs#security

    colors.js와 faker.js 사태가 준 교훈

    다이나믹하게 시작하는 2022년

    2022-01-17·10분
  • ◆ 프론트엔드 개발자가 알아야 할 쿠버네티스
    #kubernetes#autoscaling#nextjs

    오토스케일링은 자동이지만 즉시가 아니다: HPA의 시간을 구간별로 실측한 기록

    트래픽을 12배로 올리고 새 파드가 첫 요청을 받기까지 31.5초. 그 31.5초의 내역서를 스톱워치로 뽑았다. 감지 창이 지배하는 구조, 배포 직후 5분 창에서 오토스케일러가 눈을 잃는 조건, 안정화 창의 계단, 메모리 HPA가 Node에서 불발되는 이유, KEDA의 선제 확장까지. 프론트엔드 개발자를 위한 쿠버네티스 시리즈의 다섯 번째 편이다.

    2026-08-10·39분
  • ◆ 프론트엔드 개발자가 알아야 할 쿠버네티스
    #kubernetes#nextjs#nodejs

    파드는 어떻게 종료되는가: 배포 중 에러의 원인과 해결을 실측한 기록

    코드를 한 줄도 바꾸지 않은 배포에서도 에러는 샌다. 롤링 배포 중 새는 실패를 유형과 시각까지 태깅해 원인 네 가지를 부검하고, 처방을 한 층씩 얹어 0으로 만들기까지의 실측 기록이다. Next.js의 종료 코드 원문과 인질 드레인, CrashLoopBackOff의 실제 시간표까지. 프론트엔드 개발자를 위한 쿠버네티스 시리즈의 네 번째 편이다.

    2026-08-08·36분

새 글을 놓치고 싶지 않으시다면 RSS로 구독해 주세요.

RSS 구독 →

yceffort — 프론트엔드 엔지니어입니다. 발표·기술 자문·기고 문의는 이곳에서 받고 있습니다.

← Back to the blogIssue on GitHub →