Computer >> 컴퓨터 >  >> 프로그래밍 >> JavaScript

Node.js crypto 모듈의 cipher.final() 메서드 완벽 가이드

Node.js에서 cipher.final() 메서드는 암호화(cipher) 객체의 최종 결과 값을 Buffer 또는 String 형태로 반환하는 데 사용됩니다. 이 메서드는 crypto 모듈 내 Cipher 클래스가 기본적으로 제공하는 내장 메서드 중 하나입니다.

주요 동작 방식은 다음과 같습니다.

  • 출력 인코딩(outputEncoding)을 지정하면 문자열(String)을 반환합니다.
  • 출력 인코딩을 지정하지 않으면 Buffer 객체를 반환합니다.
  • cipher.final() 메서드를 두 번 이상 호출하면 에러가 발생합니다.

문법(Syntax)

cipher.final([outputEncoding])

매개변수(Parameters)

  • outputEncoding – 출력 인코딩 방식을 나타내는 매개변수로, 문자열(string) 타입입니다. 사용 가능한 값으로는 hex, base64 등이 있습니다.

예제 1: 인코딩 지정하여 결과 출력하기

cipherFinal.js라는 이름의 파일을 생성하고 아래 코드를 복사한 후, 다음 명령어로 실행해 보겠습니다.

node cipherFinal.js
// cipher.final() 메서드 사용 예제

// crypto 모듈 불러오기
const crypto = require('crypto');

// AES 알고리즘 초기화
const algorithm = 'aes-192-cbc';
// 키 생성에 사용할 비밀번호 설정
const password = '12345678';

// 암호화 객체에 사용할 키 생성
const key = crypto.scryptSync(password, 'salt', 24);

// 고정 IV(초기화 벡터) 생성
const iv = Buffer.alloc(16, 0);

// 암호화 객체 생성
const cipher = crypto.createCipheriv(algorithm, key, iv);
const cipher2 = crypto.createCipheriv(algorithm, key, iv);

// outputEncoding이 지정되어 있으므로 문자열로 반환됨
let hexValue = cipher.final('hex');
let base64Value = cipher2.final('base64');

// 결과 출력
console.log("Hex String:- " + hexValue);
console.log("Base64 String:- " + base64Value)

실행 결과

C:\home\node>> node cipherFinal.js
Hex String:- 8d11772fce59f08e7558db5bf17b3112
Base64 String:- jRF3L85Z8I51WNtb8XsxEg==

위 예제에서 볼 수 있듯이, 인코딩을 'hex'로 지정하면 16진수 문자열이, 'base64'로 지정하면 Base64 인코딩된 문자열이 반환됩니다.

예제 2: final() 재호출 시 에러 발생 확인하기

이번에는 같은 암호화 객체에서 final() 메서드를 여러 번 호출했을 때 어떤 일이 발생하는지 살펴보겠습니다.

// cipher.final() 메서드 사용 예제

// crypto 모듈 불러오기
const crypto = require('crypto');

// AES 알고리즘 초기화
const algorithm = 'aes-192-cbc';
// 키 생성에 사용할 비밀번호 설정
const password = '12345678';

// scrypt 콜백 방식으로 키 생성
crypto.scrypt(password, 'salt', 24,
    { N: 512 }, (err, key) => {

        if (err) throw err;

        // 고정 IV(초기화 벡터) 생성
        const iv = Buffer.alloc(16, 0);

        // 암호화 객체 생성
        const cipher = crypto.createCipheriv(algorithm, key, iv);

        // outputEncoding이 없으므로 Buffer로 반환됨
        let hexValue = cipher.final();
        // 이미 final()이 호출되었으므로 에러 발생!
        let base64Value = cipher.final('base64');

        // 결과 출력
        console.log("Buffer:- " + hexValue);
        console.log("Base64 String:- " + base64Value)
    });

실행 결과

C:\home\node>> node cipherFinal.js
internal/crypto/cipher.js:164
    const ret = this._handle.final();
                        ^
Error: Unsupported state
    at Cipheriv.final (internal/crypto/cipher.js:164:28)
    at Object. (/home/node/test/cipher.js:22:26)
    at Module._compile (internal/modules/cjs/loader.js:778:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
    at Module.load (internal/modules/cjs/loader.js:653:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
    at Function.Module._load (internal/modules/cjs/loader.js:585:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:831:20)
    at startup (internal/bootstrap/node.js:283:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:623:3)

에러 원인 분석

위 예제에서 에러가 발생한 이유는 이미 해당 키로 final() 메서드가 한 번 호출되었기 때문입니다. final()은 말 그대로 암호화 과정을 종료하는 마지막 단계 메서드이므로, 동일한 암호화 객체에서 두 번째 호출 시 더 이상 처리할 데이터 상태가 없어 Error: Unsupported state 예외가 발생하게 됩니다.

따라서 실무에서는 하나의 암호화 객체당 final()을 반드시 한 번만 호출하도록 주의해야 하며, 추가 암호화 작업이 필요하다면 새로운 cipher 객체를 생성해야 합니다.