1. 문제 상황
인증 절차에 공개키 알고리즘을 사용하고 있었습니다.
server와 client 모두 node 환경이므로, crypto를 사용해 암호화/복호화를 진행했습니다
import crypto from 'crypto';
encrypt(plainText: string, publicKey: string) {
const buffer = Buffer.from(plainText);
const encrypted = crypto
.publicEncrypt(publicKey.replace(/\\n/g, '\n'), buffer)
.toString('hex');
return encrypted;
}
decrypt(encrytedText: string, privateKey: string) {
const buffer = Buffer.from(encrytedText, 'hex');
const decrypted = crypto
.privateDecrypt(privateKey, buffer)
.toString('utf8');
return decrypted;
}
client에서 공개키(public key)를 통해 encrypt를 진행하고
server에서는 개인키(private key)를 통해 decrypt를 시도, 복호화에 성공했을 경우 인증 처리를 진행했습니다.
이때 client의 public key를 외부에 노출해서는 안되므로, env 파일에서 관리를 진행했습니다.
// .env.development
PUBLIC_KEY='-----BEGIN PUBLIC KEY-----
abcabcabcabcabcabcabcabcabcabcabcabc
abcabcabcabcabcabcabcabcabcabcabcabc
-----END PUBLIC KEY-----'
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
env: {
PUBLIC_KEY: process.env.PUBLIC_KEY,
},
};
module.exports = nextConfig;
nextConfig 파일에 환경 변수를 지정하고
// page.tsx
import React from "react";
import App from "src/components/App";
import { cryptoService } from "@/services/crypto";
const fetchLogin = async () => {
const publicKey = process.env.PUBLIC_KEY
// cryto 암호화 함수
const encryptedMessage = cryptoService.encryptPublicKey(
publicKey,
new Date().getTime().toString()
);
return viewerLoginService.login(encryptedMessage);
};
const page = async () => {
const response = await fetchLogin()
};
export default page;
next 14 버전에서 개발했기 때문에, server component를 활용해 login(인증) 요청을 보냈습니다.
개발 환경에서는 아무런 문제가 없었고, 그대로 배포를 진행했습니다.
사내에서는 프론트엔드 배포에 AWS Amplify를 사용하고 있었습니다.
GUI 환경에서 쉽게 key-value 값을 환경 변수에 주입할 수 있습니다.
그러나 배포 후 해당 페이지에 접근하니 유효한 사용자임에도 불구, fetchLogin 실패 화면이 동작하고 말았습니다.
원인을 파악하기 위해 이런저런 테스트를 하던 도중...
fetchLogin에서 crypto의 encryptPublicKey 동작 시
1E08010C DECODER routines unsupported 에러가 발생함을 확인할 수 있었습니다!
2. 문제 상황
해당 에러의 원인은 간단합니다. 올바르지 않은 public key로 암호화를 시도했기 때문이죠.
3. 해결 방안
얼핏 봤을 때는 분명 유효한 public key였지만...
좌측의 실제 public key를 우측 Amplify GUI에 붙여 넣기 한 경우,
해당 요소는 input이기 때문에 → \n(개행)이 띄어쓰기(공백)로 변경되어 입력 됩니다!
두 값은 완전히 다르며, 이 때문에 crypto의 publicEncrypt 실행 시 에러가 발생했던 것이죠.
따라서 해당 값에 \n 를 직접 추가해 주고 (공백은 당연히 제거합니다)
const encrypted = crypto.publicEncrypt(
publicKey.replace(/\\n/g, "\n"),
buffer
);
입력받은 publicKey의 \n 문자를 개행으로 변경해 해결할 수 있습니다.
'source-code > FrontEnd' 카테고리의 다른 글
[chrome extension] 에러 핸들링 (0) | 2024.02.02 |
---|---|
[chrome extension] side panel 사용하기 (0) | 2024.02.01 |
[chrome extension] 익스텐션 설치 여부 감지하기 (0) | 2024.01.18 |
XState Visualizer 활용하기 (1) | 2024.01.01 |
JS 종료 시점 제어되는 ScrollIntoView 구현하기 (0) | 2023.12.01 |