김보안의 블로깅
  • 🏠 Home
  • 📚 Project
    • Blockchain
      • 🎦 PickMe
      • 🎦 IoTC
      • 🎦 Blackchain
      • 📃 Gemology
      • 🎦 PickMe
      • 🎦 PickMe
    • AI
      • 👋 A.I. Dream Reader
      • 🎦 A.I. Dream Reader
    • Security
      • 🎦 SNAC
    • Education
      • 🎦 Smart Lecture
  • 🤸‍♂ Hobby
    • Music
      • Violin
      • Guitar
      • Piano
      • Drum
    • Flower
      • Flower Certificate
    • Sport
      • Ski
      • Skateboard
      • Golf
      • Boxing

2018년 1월 24일 수요일

Node.js 에서 RSA 로 암복호화 하기

 SecureKim     오전 12:34     암복호화, decrypt, Encrypt, Node.js, RSA, Security     2 comments   


Node.js 의 crypto 모듈은 기본적으로 제공되므로, npm 으로 설치할 필요가 없습니다.

crypto 기본 모듈을 사용해 RSA 의 키로 암복호화 하는 방법을 알아 봅시다.

일단 그 전에 OpenSSL로 RSA Private Key, Public Key 를 생성합니다.


C:\Users\Public>openssl genrsa -out private.key 2048

Generating RSA private key, 2048 bit long modulus
.................................................................................................................................+++
.........+++
unable to write 'random state'
e is 65537 (0x10001)


예전 블로그의 AES 관련 글 을 보시면 아시다시피,

Private key 로 Public key 를 Generate 할 수 있습니다.

C:\Users\Public>openssl rsa -in private.key -out public.key -pubout

그런데 단순히 이렇게 하시면, 결과가 PKCS#8 표준으로 나옵니다.

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuErwCGWyq3nIASTKhgiH
GAaURZ9rs5EBR9L1YUJh1ftYgQSt0gUzab6hyW/upgM4Z4Mu6pA+KZCHncKc4SHJ
XdJvYnj1L6/RRinXQp+R3MmGypoB/r1ckM1aEt75/I0m7Dlatj58f56Z21yHsJNb
tf1LAD981a3kR6kaIb7Uc5bsUDwObF2r5xAenQDtaZoWgaErHWwiqzJJQebcAVVq
lq2/+f1kzRVqHsasosXOD6hrDz9oC2SvBKWVrmOPF4D+mwwaChEKAhFDvCKj5NYw
prmoOXWK6t5WroYvsVo5Sa039DiCPXMsug9MidhQLB7SpW7Bi+xeuwvObWppgGZ8
FQIDAQAB
-----END PUBLIC KEY-----

PKCS#8 표준의 ASN.1 구조를 보면 다음과 같습니다.
PublicKeyInfo ::= SEQUENCE {
  algorithm       AlgorithmIdentifier,
  PublicKey       BIT STRING
}

AlgorithmIdentifier ::= SEQUENCE {
  algorithm       OBJECT IDENTIFIER,
  parameters      ANY DEFINED BY algorithm OPTIONAL
}

우리는 PKCS#1 을 사용할 것이므로 아래와 같이 변환합니다.

C:\Users\Public>openssl rsa -pubin -in public.key -RSAPublicKey_out


-----BEGIN RSA PUBLIC KEY-----

MIIBCgKCAQEAuErwCGWyq3nIASTKhgiHGAaURZ9rs5EBR9L1YUJh1ftYgQSt0gUz
ab6hyW/upgM4Z4Mu6pA+KZCHncKc4SHJXdJvYnj1L6/RRinXQp+R3MmGypoB/r1c
kM1aEt75/I0m7Dlatj58f56Z21yHsJNbtf1LAD981a3kR6kaIb7Uc5bsUDwObF2r
5xAenQDtaZoWgaErHWwiqzJJQebcAVVqlq2/+f1kzRVqHsasosXOD6hrDz9oC2Sv
BKWVrmOPF4D+mwwaChEKAhFDvCKj5NYwprmoOXWK6t5WroYvsVo5Sa039DiCPXMs
ug9MidhQLB7SpW7Bi+xeuwvObWppgGZ8FQIDAQAB

-----END RSA PUBLIC KEY-----



PKCS#1 의 ASN.1 구조는 다음과 같습니다.
RSAPublicKey ::= SEQUENCE {
    modulus           INTEGER,  -- n
    publicExponent    INTEGER   -- e
}

(참고로 반대로 ( PKCS#1 -> PKCS#8 ) 변환하는 하는 방법은 아래와 같습니다.)
openssl rsa -RSAPublicKey_in -in -pubout

이제 예제를 볼까요?



RSA encyrpt & decrypt in node.js


var crypto = require('crypto');

var PRIVKEY = '-----BEGIN RSA PRIVATE KEY-----\n'+
'MIIEowIBAAKCAQEAuErwCGWyq3nIASTKhgiHGAaURZ9rs5EBR9L1YUJh1ftYgQSt\n'+
'0gUzab6hyW/upgM4Z4Mu6pA+KZCHncKc4SHJXdJvYnj1L6/RRinXQp+R3MmGypoB\n'+
'/r1ckM1aEt75/I0m7Dlatj58f56Z21yHsJNbtf1LAD981a3kR6kaIb7Uc5bsUDwO\n'+
'bF2r5xAenQDtaZoWgaErHWwiqzJJQebcAVVqlq2/+f1kzRVqHsasosXOD6hrDz9o\n'+
'C2SvBKWVrmOPF4D+mwwaChEKAhFDvCKj5NYwprmoOXWK6t5WroYvsVo5Sa039DiC\n'+
'PXMsug9MidhQLB7SpW7Bi+xeuwvObWppgGZ8FQIDAQABAoIBAQCPOcYkcI0UETgs\n'+
'E2DGHBiJxoszNLuqOVaKcFw9sy5/87ALzQwdvecAFqR7/d617KjIYb5zk5iMCwQq\n'+
'ylXL7csmfGYOXL0Iy5ZT9i6SW5srwP9ds6U7SgWHj+Ch6+LSsQx/5+8k1ZlCQYuH\n'+
'XPkjdNKAtJK2ZaDqHBPe0YA6m6lXDrEOJl6xrlUWCZS02XPIXFaB+qTBG2UqWCUK\n'+
'KzVa9qIqWf3bVGJCLc70u5UiuvCC+V8VtJ964AEnj90qZy1tRhEc2X8bbWmhL3yB\n'+
'3SLWH4ZvJyEDQe/yycx9rO6CymDj3c378IyWORYt1y6mKRmltr2NJ1Ecbl9xaFrc\n'+
'JeVO8wDdAoGBAOUjZzuaVppccEIiBbLS0NksSeD4tfjlUPFqVU1obZcbkDugK1Id\n'+
'og+W5yVy2NqgeEi4nQ9Ogi485cWbCzTZM52d9zuFe/60hBFPU8jWxafW0OW2o6ci\n'+
'F1vtzWEF2EO7omUoiGu6mOI4yRcUMwXiw1cCWr2NYpASQ39QuxwXKgg7AoGBAM3l\n'+
'sC7nxqDusq+J9CI6V+oNb2v7KgapQmrdXNB5l6Mk2Dl/uNfuX5cDceMQlO5B/ObT\n'+
'44kgsBR3tO6y7PQLDClt5ZPrVJZ16+cCj41UDDgZDD0vDaU24K/qSVrsOH4gNgeM\n'+
'CcsInzX/l1bm+RAhE0pHuPHBZFuLi8brV/wZCpfvAoGAQu4XbmKDn20W4UpczcIk\n'+
'fPshzVP4m24oOYwsxIKXWEcV10TOwpqjRth2RgsI6rtqxxsdzWXKQsVI/HJwUIyN\n'+
'NiH5IGq6MEj8Nq4sNAMAEyl9NUwm+1/K4PBSSF/Trt0070Vqq8UCeTnLCzG8QaDe\n'+
'HCE07h9JRfn/u0WSkf72KRcCgYAUTGmjJix53y50idgsq63RIEP01E0fXP50RKCK\n'+
'2QHvDonWmVXiy9hWrftDVHYqSw0gwJD1CujxC6AlzDP6F0C6sN/qRlAPiU6ZdrIq\n'+
'T7foq+d9/K6OtCtQjHtw4ErtfEV3VwH8Jzxy+WC1K44wXeJl904vX06Ci+5azQbe\n'+
'jqVxtwKBgBnxVKFQCmuDjOZrf7V0jB/mf4ir9npqvHdJMHE/Et70lOaUbhat6i+Y\n'+
'PPtJewynfF4zp+HD6jOlj4RhbCncMNdaWAyDYOucYOJOpMr5mIYJHdCOVQ0aSRD7\n'+
'/dZEOGblrch6VXOEvC++yaToNhjkeTP63IH4K6uqa9btelz3Df5Y\n'+
'-----END RSA PRIVATE KEY-----\n';

var PUBKEY = '-----BEGIN RSA PUBLIC KEY-----\n'+
'MIIBCgKCAQEAuErwCGWyq3nIASTKhgiHGAaURZ9rs5EBR9L1YUJh1ftYgQSt0gUz\n'+
'ab6hyW/upgM4Z4Mu6pA+KZCHncKc4SHJXdJvYnj1L6/RRinXQp+R3MmGypoB/r1c\n'+
'kM1aEt75/I0m7Dlatj58f56Z21yHsJNbtf1LAD981a3kR6kaIb7Uc5bsUDwObF2r\n'+
'5xAenQDtaZoWgaErHWwiqzJJQebcAVVqlq2/+f1kzRVqHsasosXOD6hrDz9oC2Sv\n'+
'BKWVrmOPF4D+mwwaChEKAhFDvCKj5NYwprmoOXWK6t5WroYvsVo5Sa039DiCPXMs\n'+
'ug9MidhQLB7SpW7Bi+xeuwvObWppgGZ8FQIDAQAB\n'+
'-----END RSA PUBLIC KEY-----\n';

// RSA PRIVATE ENCRYPT -> PUBLIC DECRYPT //
 myMSG = "[ORIGINAL] I'm securekim !!!";
 
function privENC_pubDEC(originMSG){
 encmsg = crypto.privateEncrypt(PRIVKEY, Buffer.from(originMSG, 'utf8') ).toString('base64');
 msg = crypto.publicDecrypt(PUBKEY, Buffer.from(encmsg, 'base64'));
 console.log("Encrypted with private key : "+encmsg);
 console.log(msg.toString());
}

function pubENC_privDEC(originMSG){
 encmsg = crypto.publicEncrypt(PUBKEY, Buffer.from(originMSG, 'utf8') ).toString('base64');
 msg = crypto.privateDecrypt(PRIVKEY, Buffer.from(encmsg, 'base64'));
 console.log("\nEncrypted with public key : "+encmsg);
 console.log(msg.toString());
}

privENC_pubDEC(myMSG);
pubENC_privDEC(myMSG);



  • 결과 :


Encrypted with private key : Q9Tz2LRlv91Rk2ScR/Wjv77ouDsiWyefVIKlssIYHBJihZeQ0IDH+rUCMG0aBhSDNT92zZjAmPF5Pah9xejqYsfCfDslmNp+FXvmfoA02uviW6b4A6e90U3atyU1PIZHtp4nDtIAYCvY78xzEyZ5oqwhbDcKuIcs4Uo4dtXNmo6N9/+Rxckf0ByCyRAUv86x1a6SYzgqyGthaDAnIUxFAXsJpAkrAOTeBy9PKx785DEXYDBOzgsFcZRHwMuFNFlMTYfQtW/rwPL0cSA6ud3Ew0Qsv4wY73ty46s2kYezSo6YjrHkYDotlhXLK5rqY+bBtU/SAufvhj/BDxYEDe9scQ==
[ORIGINAL] I'm securekim !!!

Encrypted with public key : CEhDVj/6KquMN5QRi69okZXz6gVjHKQGOm1C1CvBExRTQrKN8sMMT1wqTQpRdVzu+YUlidgCmj+v+5bgiSMl1Ul38VUHT9rL42fwT226RYfhlMvRn2umddboyHh0TMPwWqI6aQ/36DQqmuXN34Rk2It2qs5gERZWTJgRdQ1mYrrz7nOA5nnu/vZyOmk4PjYww9QediUF+J9pxOAlYsIT+AdOXVvdKeB6M5esGZWwQ3trZvklG0KmZSNUQ6HyvQ/+MorsKDMOZxpRcBxTB+3DzzUb+UtvBSlsUNYfnMAYlEeB7M4AzgIJpZ8jfYOecp9DSx6eTzk919YVCyUU3GL2oQ==

[ORIGINAL] I'm securekim !!!


일반적으로 각 함수가 사용되는 용도는 다음과 같습니다.

ㆍprivENC_pubDEC

   - Signature Verify
    예를 들어 상호 인증시 클라이언트는 이때까지 주고받은 내용을 Hash 한 다음
    Private key 로 암호화해 Signature 를 생성해 서버로 전달합니다.
    서버는 이때까지 주고받은 내용을 Hash 한 값과,
    클라이언트가 보내준 인증서의 Public key로 Signature 를 복호화 한 값을 비교하여
    동일한지 판단 합니다.

ㆍpubENC_privDEC

    - AES KEY nego
     클라이언트가 AES Key 를 서버의 Public key 로 암호화해서
     서버에게 전달 해 주면 서버에서는 복호화 합니다.
     이렇게 하여 클라이언트와 서버는 AES Key 를 나눠갖게 되고,
     이후 통신은 AES KEY로 하게 됩니다.

이후 통신을 AES KEY 로 암호화 하는 이유는 RSA 암호화 방식은 AES 에 비해 너무 느리기 때문입니다.

그리고 메시지의 길이가 긴 경우 아래와 같이 RSA 로 암호화가 되지 않습니다.

Error: error:0406C06E:rsa routines:RSA_padding_add_PKCS1_type_1:data too large for key size

다음 포스팅에서는 Node.js 에서 crypto 모듈을 사용해 AES 암호화를 해보겠습니다.

  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
이메일로 전송BlogThis!Twitter에서 공유Facebook에서 공유
최근 게시물 이전 게시물 홈

댓글 2개:

  1. Unknown2021년 5월 7일 오후 6:19

    슨생님 좋은 글 잘 읽었습니다!
    암린이라서 기초적인 질문하나 해도될까요?
    해당 글에서는 pkcs#8 to pkcs#1으로 public key만 변환하였는데 private key는 pkcs#8인 상태일텐데, 변환된 public key로 복호화가 가능한가요? private key도 변환할 필요는 없나요?

    답글삭제
    답글
    1. SecureKim2021년 6월 14일 오전 6:32

      방문 감사합니다. 해당 명령 수행시 private key는 PKCS#1로 생성됩니다.
      주석이 BEGIN RSA PUBLIC KEY 인지 단순히 BEGIN PUBLIC KEY인지 확인해 보면 쉽게 구분이 가능합니다.

      삭제
      답글
        답글
    2. 답글
댓글 추가
더 로드하기...

페이지

  • 홈
  • Hobby

Categories

  • AI
  • android
  • AWS
  • Blockchain
  • Hardware
  • Javascript
  • mysql
  • Node.js
  • Plasma
  • review
  • Security
  • Study
  • Video
  • windows

Popular Posts

  • 회사 프록시와 인증서에 고통받는 그대를 위한 글 (Bash, Gradle, Python, wget, nodejs(npm), apt-get, cURL, git, yarn, androidStudio)
    대기업에 입사하면 장단점이 있는데, 단점 중에 하나가 회사에서 프록시를 사용하여 트래픽 감시를 하므로 프록시 설정을 해주어야 한다는 점 입니다. 특히, 회사에서는 https 트래픽도 감시를 하므로 인증서도 설정해 주어야 합니다. 그런데 문...
  • Termux 로 안드로이드에 우분투(GUI)와 VSCode설치하기
      많은 글들이 있지만 뭔가 대부분 잘 안됐다. 이번 기회에 정리한다. 0. 먼저 Termux와 Remote Desktop Manager를 설치한다. Remote Desktop Manager 대신 아래도 나쁘지 않다. 화면이 작지만 마우스 스크롤이나 ...
  • Node.js 에서 RSA 로 암복호화 하기
    Node.js 의 crypto 모듈은 기본적으로 제공되므로, npm 으로 설치할 필요가 없습니다. crypto 기본 모듈을 사용해 RSA 의 키로 암복호화 하는 방법을 알아 봅시다. 일단 그 전에 OpenSSL로 RSA Private Key...

Blog Archive

  • ►  2023 (1)
    • ►  1월 (1)
  • ►  2022 (10)
    • ►  12월 (1)
    • ►  11월 (3)
    • ►  9월 (1)
    • ►  8월 (1)
    • ►  6월 (2)
    • ►  3월 (2)
  • ►  2021 (9)
    • ►  12월 (3)
    • ►  11월 (1)
    • ►  6월 (1)
    • ►  5월 (2)
    • ►  4월 (2)
  • ►  2020 (12)
    • ►  10월 (1)
    • ►  9월 (2)
    • ►  7월 (1)
    • ►  6월 (1)
    • ►  5월 (5)
    • ►  4월 (1)
    • ►  2월 (1)
  • ►  2019 (14)
    • ►  10월 (2)
    • ►  7월 (1)
    • ►  3월 (4)
    • ►  2월 (2)
    • ►  1월 (5)
  • ▼  2018 (14)
    • ►  12월 (2)
    • ►  11월 (4)
    • ►  10월 (1)
    • ►  8월 (2)
    • ►  5월 (4)
    • ▼  1월 (1)
      • Node.js 에서 RSA 로 암복호화 하기
  • ►  2017 (12)
    • ►  10월 (2)
    • ►  9월 (9)
    • ►  5월 (1)
  • ►  2016 (8)
    • ►  10월 (2)
    • ►  8월 (1)
    • ►  6월 (1)
    • ►  1월 (4)
  • ►  2015 (6)
    • ►  12월 (3)
    • ►  10월 (1)
    • ►  6월 (1)
    • ►  5월 (1)
  • ►  2014 (10)
    • ►  11월 (1)
    • ►  9월 (1)
    • ►  7월 (1)
    • ►  6월 (1)
    • ►  5월 (3)
    • ►  4월 (1)
    • ►  3월 (2)
  • ►  2013 (28)
    • ►  12월 (3)
    • ►  11월 (6)
    • ►  10월 (6)
    • ►  9월 (6)
    • ►  8월 (1)
    • ►  7월 (3)
    • ►  6월 (3)

구독

글
Atom
글
댓글
Atom
댓글

로드 중입니다...

각오

직접 해보지 않은 것은 포스팅 하지 않겠습니다.

Copyright © 김보안의 블로깅 | Powered by Blogger
Design by Hardeep Asrani | Blogger Theme by NewBloggerThemes.com | Distributed By Gooyaabi Templates