기존에는 AES 방식으로 암호화를 진행했다면 이제는 jsrsasign이라는 라이브러리를 가지고 RSA 암호화를 구현해보려고 한다. 기존에 사용했던 AES 방식과 RSA 방식이 어떤 차이가 있는지를 먼저 알아보고, 자바스크립트와 리액트에서 사용할 것이다.
1. AES vs RSA 두 방식의 차이는?
1) AES 알고리즘
AES 방식은 대칭키를 사용하여 암호화, 복호화를 진행하는 암호화 알고리즘으로 클라이언트와 서버가 같은 키를 사용해야한다.
- 클라이언트와 서버 간 동일한 키를 공유해야하기 때문에 키 전달 및 관리에 어려움이 있다.
- 키가 노출되면 보안에 매우 취약해진다.
- 비대칭키 암호화 방식에 비해서는 키 사이즈가 작지만 암호화 알고리즘 구조가 간단하여 연산 속도가 빠르다.
2) RSA 알고리즘
RSA 방식은 비대칭키를 이용한 공개키 암호화 방식으로 공개키를 통해 암호화를 진행한 후, 개인키를 가지고 복호화 하는 방법이라고 할 수 있다.
- 암호화 키(공개키)와 복호화 키(개인키)가 다르다.
- 공개키를 가지고 개인키를 알아내기는 어렵다.
- 대칭키 알고리즘에 비해 속도가 느리다.
2. jsrsasign으로 암호화하는 방법(JS, React)
1) 자바스크립트
일반적으로 자바스크립트에서 jsrsasign 라이브러리를 사용할 때, npm으로 설치하는 방법과 cdn 형식으로 불러와서 사용하는 방법이 있는데 나는 cdn 방식으로 추가해주었다.
a. jsrsasign 라이브러리 추가
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsrsasign/10.2.0/jsrsasign-all-min.js"></script>
b. RSA 암호화를 위한 RSA 키 쌍 생성
라이브러리를 추가했다면 RSA 키 쌍을 생성해야한다. 나는 예제를 만들 것이기 때문에 클라이언트에서 RSA 키 쌍을 생성해주었지만, 서버측에서 생성하여 공개키를 내려주는 방식을 사용한다면 키 쌍을 생성할 필요는 없다.
const RSAkey = KEYUTIL.generateKeypair("RSA", 2048); // 2048, 1024, 512 ...
const pubKey = RSAkey.pubKeyObj; // 공개키
const prvKey = RSAkey.prvKeyObj; // 개인키
c. RSA 암호화 진행
다음으로는 json 데이터의 값들을 각각 암호화해보려고 한다. 이름, 전화번호, 생년월일 값을 각각 암호화하기 위해 미리 발급해둔 공개키를 사용한다.
const json = {
name: "김하나",
phone: "01012341234",
birthday: "19980202",
};
// RSA 암호화 함수
function encryptData() {
function encryptAndEncode(data) {
return KJUR.crypto.Cipher.encrypt(data, pubKey, "RSA");
}
json.name = encryptAndEncode(json.name);
json.phone = encryptAndEncode(json.phone);
json.birthday = encryptAndEncode(json.birthday);
console.log(json);
}
해당 코드를 실행하면 아래와 같이 암호화된 데이터가 콘솔에 찍히는 것을 확인할 수 있다.
2) 리액트에서 암호화하는 방법
위의 예시는 html과 js만을 가지고 암호화하는 방식이지만 리액트에서 암호화하는 것도 크게 다를 것이 없다. 리액트에서는 npm or yarn 패키지 매니저를 통해 jsrsasign를 설치해주자.
a. jsrsasign 라이브러리 추가
$ npm i jsrsasign
b. RSA 암호화를 위한 RSA 키 쌍 생성 및 암호화
키쌍을 생성해주기 위해 KEYUTIL, KJUR를 import 해서 가져온다.
import { KEYUTIL, KJUR } from 'jsrsasign'
그 후, 키쌍을 생성하고 암호화하는 방식은 위와 동일하다.
const RSAkey = KEYUTIL.generateKeypair("RSA", 2048); // 2048, 1024, 512 ...
const pubKey = RSAkey.pubKeyObj; // 공개키
const prvKey = RSAkey.prvKeyObj; // 개인키
const json = {
name: "김하나",
phone: "01012341234",
birthday: "19980202",
};
// RSA 암호화 함수
function encryptData() {
function encryptAndEncode(data) {
return KJUR.crypto.Cipher.encrypt(data, pubKey, "RSA");
}
json.name = encryptAndEncode(json.name);
json.phone = encryptAndEncode(json.phone);
json.birthday = encryptAndEncode(json.birthday);
console.log(json);
}
c. pem 키 -> RSA 키로 변환
만약 서버측에서 받은 공개키로 암호화를 진행한다면 키 쌍을 생성하는 부분은 생략되고, 서버측에서 받은 pem 형식의 공개키를 RSA 키로 변환하여 암호화해주면 된다.
// pem 형식의 공개키
const pemKey = "-----BEGIN PUBLIC KEY-----\n" + "서버측 공개키 \n" + "-----END PUBLIC KEY-----";
// RSA 키로 변환
const rsaPublicKey = KEYUTIL.getKey(pemKey);