2015년 12월 31일 목요일

APK to Java Src and Find

APK를 Java 소스로 바꿔주는 배치 프로그램입니다.

제가 만들었고 라이센스 없습니다. 가져다 쓰세요.

7z.exe가 Command line 상에서 사용 가능 해야 하며
같은 폴더에 dex2jar-2.0, jd-cli-0.9.1 이 있어야 합니다.
----------------------------------------------------------------------
@echo off
set Title_BY=ver1.1_by_B.Y.
title %Title_BY%
echo 7zip, dex2jar-2.0, jd-cli-0.9.1 이 모두 있어야 합니다.

7z >NUL
if %ERRORLEVEL% EQU 0 (
goto GO_execute
) ELSE (
echo 7zip을 설치하고, 환경변수로 지정해주세요.
pause
goto GO_END
)
:GO_execute
set pth=%cd%
set new=Src_%date:~5%_%time:~0,2%_%time:~3,2%_%time:~6,2%

set /P pt^=APK (with path):
mkdir %pth%\%new%
rem APK to JAR
7z x %pt% -y -o%pth%\%new%
IF EXIST %pth%\dex2jar-2.0\classes-dex2jar.jar (
del /S /Q %pth%\dex2jar-2.0\classes-dex2jar.jar
)
setlocal enabledelayedexpansion
cd dex2jar-2.0
set LIB=lib
set CP=
for %%X in ("%LIB%"\*.jar) do (
    set CP=!CP!%%X;
)
::에러가 나면 여기를 수정해보세요.
::java -Xms512m -Xmx1024m -cp "%CP%" com.googlecode.dex2jar.tools.Dex2jarCmd %pth%\%new%\classes.dex
java -Xms512m -Xmx1024m -cp "%CP%" com.googlecode.dex2jar.tools.Dex2jarCmd %pth%\%new%\classes.dex
pause
cd ..
cd %pth%
mkdir %pth%\%new%\javaSrc
java -jar jd-cli-0.9.1\jd-cli.jar -od %pth%\%new%\javaSrc %pth%\dex2jar-2.0\classes-dex2jar.jar
cp %pth%\dex2jar-2.0\classes-dex2jar.jar %pth%\javaSrc.jar
start "" %pth%\%new%\javaSrc
::cd %pth%\%new%\javaSrc
IF EXIST %pth%\dex2jar-2.0\classes-dex2jar.jar ( del /S /Q %pth%\dex2jar-2.0\classes-dex2jar.jar )
cls
:_Find
if EXIST findInJavaSrc.bat (
findInJavaSrc.bat %pth%\%new%\javaSrc %Title_BY%
)
:GO_END
----------------------------------------------------------------------

findInJavaSrc.bat은 java 소스파일에서
findStringList.txt 기준으로 문자열을 찾아줍니다.

findInJavaSrc.bat를 독립적으로 실행할 경우에는
같은 위치의 폴더들 (하위폴더 포함)의 자바 소스에서
findStringList.txt 기준으로 문자열들을 찾아줍니다.

----------------------------------findInJavaSrc.bat------------------------------------

@echo off
set Title_BY=%2
if DEFINED Title_BY (
title %Title_BY%
) else (
title findInJavaSrc by B.Y.Kim
)
cls
color 03
set pth=%cd%
set rpth=%1
if NOT DEFINED rpth (
set rpth=%cd%
) ELSE (
set rpth=%1
)
IF EXIST %rpth%\finded (del /Q /S %rpth%\finded)
mkdir %rpth%\finded
cls
cd %rpth%
echo 찾는 위치   : %rpth%
echo 찾을 문자열 : %pth%\findStringList.txt
type %pth%\findStringList.txt
echo.
IF EXIST %pth%\findStringList.txt (
echo 위 문자열들을 찾는 중입니다... 잠시만 기다려 주세요.
echo.
for /f "delims= delims=: tokens=2 eol=; usebackq" %%i in ("%pth%\findStringList.txt") do call :FOR_GO %%i
echo Find END___
goto FOR_END
:FOR_GO
findstr /N /I /S /C:"%1" *.java | findstr /V \/\/ >"%rpth%\finded\%1.txt"
exit/b
) ELSE (
echo 찾을 문자열이 없습니다.
echo "" >> "%pth%\findStringList.txt"
start "" "%pth%\findStringList.txt"
)

:FOR_END

color
start "" %rpth%\finded
:end
----------------------------------------------------------------------


findStringList.txt 는 다음과 같은 포맷으로 되어있습니다.
이 경우 string과 want, password 라는 문자열을 찾습니다.

--------------------------findStringList.txt--------------------------
;
; 설명(주석) :찾을 문자
;
설명 :string
찾을문자열  :want
패스워드 관련  :password
----------------------------------------------------------------------





2015년 12월 29일 화요일

find directory or file


윈도우에서 파일이나 디렉토리 찾는 배치 스크립트입니다.

제가 만들었고 라이센스 없습니다. 편하게 쓰세요.

@echo off
title byfind by B.Y.
set p1=%1
if NOT DEFINED p1 goto _help
set p2=%2
set p3=%3
set p1=%p1:~1%
if DEFINED p3 (
set p2=%3
set dir=%2
) else (
set dir=%cd%
)
if %p1% EQU d (
goto _directory
) else (
if %p1% EQU f goto _file
goto _help
)
:_directory
dir /s /b /a:d %dir%\*%p2%*
goto _exit
:_file
dir /s /b %dir% | find "%p2%"
goto _exit
:_help
echo usage : %0 [/d] [/f] [directory] "name"
echo.
echo /d : directory
echo /f : file
echo.
goto _exit
:_exit
::exit

2015년 12월 22일 화요일

인증서 검증 확인 방법


웹 브라우저에서 인증서를 실제로 검증하는지 검사해 보려면 MITM을 하거나

가짜 인증서와 서버를 만들어 보면 됩니다. 여기서는 후자를 해봅니다.


먼저 패킷을 캡처한 것에서 Certificate를 누르고 ctrl+H 눌러서 빼옵니다.



다 빼내오면 rootCA가 있고

마지막에 demo.labs.mastercard.com을 사이닝 해주는 것을 알 수 있습니다.

저는 중간과정 생략하고 데모 인증서와 rootCA 인증서만 가짜로 만들어 보았습니다.



일단 key를 만듭니다. 키 길이는 인증서를 보고 맞춰줍니다.
openssl genrsa 2048 > my.key

root의 key는 특별히 암호도 걸어주었습니다.
openssl genrsa -aes128 2048 > root.key


OPENSSL_CONF 값이 없으면 Unable to load config info from 에러가 납니다.
(시스템 환경변수로 추가해도 됩니다.)
set OPENSSL_CONF=C:\Program Files (x86)\GnuWin32\share\openssl.cnf

본래 인증서를 잘 보고 인증을 요청하는 csr 파일을 그대로 만듭니다.
( / 같은 특수문자는 앞에 escape 문자 \ 를 붙여줍니다.)
openssl req -new -key root.key -nodes -subj "/C=US/O=Entrust, Inc./OU=www.entrust.net\/CPS is incorporated by reference/OU=(c) 2006 Entrust, Inc./CN=Entrust Root Certification Authority" -out CA-CA.csr

만든 csr을 셀프 사이닝 해줍니다.
openssl x509 -req -days 365 -in CA-CA.csr -signkey root.key -out CA-CA.crt


이제 생성되었습니다. 똑같아 보이지만, 오른쪽이 진짜, 왼쪽이 가짜인증서입니다.




이제 똑같은 방식으로 서버용 키를 만들고 키로 csr파일 만들고,
rootCA로 사인해 주면 됩니다.

아까 키는 만들었었죠.
openssl genrsa 2048 > my.key


인증서를 잘 보고 csr파일을 만들어 줍니다.
openssl req -new -key my.key -nodes -subj "/C=BE/L=Waterloo/O=MasterCard International Incorporated/OU=NS01 ISF/CN=demo.labs.mastercard.com" -out demo.csr
(CN은 본인의 도메인으로 맞춰 줘야 관련 에러가 나지 않습니다.)


이제 rootCA인증서로 csr파일을 사인해 주면 됩니다.
openssl x509 -req -days 500 -in demo.csr -CA CA-CA.crt -CAkey root.key -CAcreateserial -out my.crt

그럼 아래처럼 2단계로 인증하는 가짜인증서 체인을 만들 수 있습니다.



물론 지금 했던 과정은 공개된 인증서를 바탕으로 하는 것이기 때문에

크게 문제될 것은 없습니다. 어차피 RSA2048 은 현재 깰 수 없을 것이기 때문이죠.

그리고 지금 위와 같이 인증서를 만들었다면, SHA1 으로 되어있을 텐데요,

획기적인 해시 충돌 취약점이 발견되서 모두들 SHA256 으로 바꾸도록 하고있으니

설정을 통해 SHA256 으로 바꿔주는게 좋겠습니다. ( -sha256 옵션 추가 )




이제 서버를 올려줍니다. 저는 간단하게 Node.js 를 사용했습니다.


Hello SyntaxHighlighter

HTTPS and HTTP Server


var http=require('http'),
    https = require('https'),
    express = require('express'),
    fs = require('fs');

var options = {
    key: fs.readFileSync('my.key'),
    cert: fs.readFileSync('my.crt')
};

var port1 = 80;
var port2 = 443;

var app = express();

http.createServer(app).listen(port1, function(){
  console.log("Http server listening on port " + port1);
});


https.createServer(options, app).listen(port2, function(){
  console.log("Https server listening on port " + port2);
});

app.get('/', function (req, res) {
    res.writeHead(200, {'Content-Type' : 'text/html'});
    res.write('

Welcome

'); res.write('Please login'); res.end(); }); app.get('/login', function (req, res){ res.writeHead(200, {'Content-Type': 'text/html'}); res.write('

Login

'); res.write('
'); res.write('') res.write(''); res.write('') res.write(''); res.write(''); res.write('
'); res.end(); }) app.post('/login', function (req, res){ var userId = req.param("userId"); var password = req.param("password") res.writeHead(200, {'Content-Type': 'text/html'}); res.write(userId+', you are now logged in.'); res.write(' back home'); res.end(); });


자 이제 접속 해보면 아래와 같이 나오는게 정상입니다.



2015년 10월 9일 금요일

AWS Security Bootcamp


1. 교육 목적
앱, 운영체제, 방화벽, 데이터등 상위 계층에서 보안 문제가 발생시 책임은 사용자에게 있음을 분명히 함.
대신 AWS 인스턴스나 서비스 자체에 대한 보안성은 아마존에서 보장하고 책임짐.
아마존에서 구현해놓은 이러한 보안 서비스도 어느정도 사용자가 상황에 맞게 설정해야 하므로 이를 위해 교육 함.

2. 내용 요약
1. Preview
2. 데이터 암호화 (KMS), Replication
3. 권한 (IAM)
4. 보안 관련 모니터링

3. 주의 사항
여기서 나오는 서비스들은 AWS의 서비스이며, 계정이라 함은 OS의 계정이 아니라 AWS서비스의 계정임.
따라서 AWS 서비스, 이름에 대해 미리 알고 있어야 함. 예를 들어 AWS에서 쓰는 DNS서버를 Route53이라고 부름.

4. 교육 내용
1. Preview
요약 : 교육내용 전체 Preview, AWS의 서비스와 장점 (서버실을 직접 운영하면 생기는 단점들)

a. NACL(Network Access Control List)
방화벽과 동일한 방식. 사용자가 필요한 룰들을 설정해 놓으면
위에서부터 아래로 내려오면서 Inbound/Outbound 패킷을 Allow/Deny 할지 결정.

b. Security Group
룰 관리를 쉽게 하기 위해 계층적으로 되어있는 보안 규칙 그룹.
여러 보안 그룹들을 만들수 있고, 모든 그룹에 추가해야하는 공통의 룰이 있다면
해당 룰을 상위 그룹으로 설정하면 하위그룹에도 함께 적용됨.

c. VPE (Virtual Private Endpoint)
기존에는 EndPoint 를 위해 방화벽 룰들을 세우고 proxy구성을 해서 설정했어야 했는데
쉽게 그러한 설정을 해줄 수 있도록 새로 나온 서비스.

d. DDoS 대응 방안
대부분의 DDoS 공격이 TCP, UDP등 Layer3, Layer4 공격임.
따라서 AWS (S3, CloudFront, Route53)를 가장 앞단에 두면 대부분의 DDoS공격은 자동으로 막힘.
그리고 VPC를 구성해서 내부 서비스(EC2 ,WAS, DB 등)들을 보호.

2. 데이터 암호화
요약 : 아마존에서 제공하는 KMS서비스에 대한 것.
키는 아마존에서 관리하여 안전하고 사용자는 API호출해서 암호화 하면됨.

a. KMS (Key Management Service)
AWS데이터 암호화 서비스의 핵심임.
사용자는 가장 먼저 API로 MasterKey를 생성해 달라고 요청하고 이름을 지음.
MasterKey 자체는 어떠한 형태로도 제공되지 않으며 어떤 사용자도 알 수 없음.
어떤 데이터를 암호화 하고 싶으면 먼저 API로 DataKey를 요청.
그럼 MasterKey로 암호화된 DataKey와 평문 DataKey가 도착함.

도착한 평문 DataKey는 데이터 암호화하는데 쓰고 반드시 폐기해야함.
도착한 암호화된 DataKey는 저장해 놓고 다음에
API호출하면 KMS에서 MasterKey로 복호화해서 평문 DataKey를 전달해줌

모든 암/복호화를 KMS에서 처리하지 않고, DataKey를 발급받아 로컬에서 처리하라고 하는 이유는
속도 때문임. 대신 4KB 이하 작은 데이터는 KMS에서 직접 암호화 해줌.

a-1. 개인적으로 KMS에 대해 알아낸 점.
Decrypt 시 KMS는 어떤 MasterKey를 갖고 암호화 했는지 알아서 자동으로 복호화 한다고 함.
DataKey, Data 각각을 MasterKey로 암호화 한 결과를 유심히 보았는데 앞부분에 동일한 문자열이 붙음.
복호화시 암호화된 부분 중 앞쪽 문자열을 분석해 어떤 MasterKey로 암호화 되었는지 판별하는것으로 추정.

b. 가격
MasterKey는 한 계정에 최대 2개 생성가능.
키 하나당 $1/달
암,복호화 API 호출 $2/백만번

c. KMS 사용 가능 서비스(자동)
- EBS (Volume 단위 암호화)
- RDS (DB)
- Red Shift

d. Replication (RDS)
저장소 클라이언트는 현재 DB가 암호화 되어있는지 아닌지 알 수 없음.
따라서 일반적인 툴을 사용해서 DB를 Replication 하듯 사용하면 됨. (DB Full load 하고 보낸 다음 변경값 Capture해서 보내고 복사)
다른 Region으로 Replication 할때 PlainText이므로 반드시 VPN, SSL을 사용해서 보내 줘야함.

e. Replication (Red Shift)
Red Shift 자체가 AWS 에서 제공하는 서비스이므로 KMS 암호화된 상태로 보냄
다른 Region으로 Replication 될 때 암호화 된 snapshot이 전송됨.
MasterKey가 Region에 종속적이므로, 서로 다른 Region이면 MasterKey를 알 수 없음.
따라서 snapshot이 전송될 때 AWS 내부적으로 masterKey의 정보를 함께 보내줌.

3. IAM ( Identity and Access Management )
요약 : IAM을 통해 AWS 서비스 사용자 계정을 만들고 권한을 부여할 수 있음.
모든 AWS서비스에 대해 권한 제어를 IAM Policy로 할 수 있음.

a. Root 계정으로 모든 작업을 하는 것은 권장되지 않으므로
IAM을 통한 사용자 계정 제작 및 제한된 권한을 부여해서 사용 권장

b. IAM Policy
AWS의 모든 권한 제공의 핵심. Json형태로, 룰들을 섞어서 매우 정밀한 권한을 부여할 수 있음.
-Person 어떤 사용자에 대해서 Deny/Allow
-Action 어떤 행위에 대해서 Deny/Allow
-Resource 어떤 자원에 대해서 Deny/Allow
-Condition 어떤 IP, 시간에 대해서 Deny/Allow

Dynamo DB, Instance 접근, 콘솔 접근 등 모든 AWS 서비스에 대한 권한을 IAM Policy로 부여.
이러한 IAM Policy를 설정하는 권한도 IAM Policy로 부여.
방화벽 룰과 다르게 Deny가 룰 위치에 상관없이 가장 먼저 우선순위를 가진다.

c. IAM Policy Auto test
자신이 JSON 포맷으로 설정해 놓은 IAM Policy가 제대로 작동하는지 테스트 해 볼 수 있음.
자동으로 다양한 API를 던져보고 Allow/Deny 결과를 정리해서 보여줌.

d. Cognito
개발자들이 서비스를 제작할 때 로그인, 데이터 싱크/공유, SNS연동 등 당연히 만들어야 하는 모듈 존재
아마존은 이러한 필수 구성요소들을 미리 만들어놓고 쉽게 사용할 수 있도록 Cognito 서비스 제공.
이때 필요한 DB접근 권한, 사용자들의 권한, 개발자의 권한 등도 IAM Policy로 설정해서 사용.

4. Trusted Advisor Security
a. 이메일로 Security 관련 조언을 받을 수 있음. 물론 자동화된 조언.
이메일 Noti는 다음과 같이 구성되어 있음.
- Short Summary
- 조치했던 것과 개선점
- Security 체크에서 배제된 것 (설정 가능)

b. 점검 항목 (12가지)
- Security Group 특정 알려진 취약 포트 점검
- Security Group 전체 포트 점검
- ELB Listener SSL, TLS, Protocol suite 사용하는 Cipher가 안전한 것인지
- ELB Security 실제 포트는 닫혀있는데 Policy 에서는 Allow 되어있거나 한 것들 점검
- Bucket 권한 설정 (유/무) 점검
- RDS 보안 위협 불필요한 포트 Allow 점검
- IAM Use IAM 사용 여부
- IAM Password IAM Password 길이나 주기 점검
- MFA Root Multifactor 인증 사용 여부
- Cloud Trail 사용 여부
- Route53 설정 점검
- Cloud front Custom SSL 점검
- 인증서 검증 만료기간, 도메인 이름 등 점검

체크에서 배제하고 싶은것은 배제해서 이메일로 전달 받을 수 있고 취약부분은 링크가 제공되어 쉽게 개선 가능

c. Trusted Advisor Access Control
어떤 부분이 취약한지 종합적으로 알려주므로 이걸 볼 수 있는 권한도 IAM Policy로 제어해야함.

d. Logging
AWS 서비스는 API 콜로 이루어지고, 모든 API콜은 Logging됨.
권한을 가진 사용자가 적법하게 API를 호출했어도 AWS에 Logging되고 볼 수 있음.

2015년 6월 1일 월요일

대칭키 암호화 알고리즘, AES


오늘은 대칭키 암호화 알고리즘의 대표주자인 AES에 대해 포스팅 하려 합니다.

  • 대칭키 암호화 알고리즘
암호화와 복호화에 같은 암호 키를 쓰는 암호 알고리즘입니다.

  • 간단한 예시
대칭키는 RSA와 다르게 간단한 예시를 통해 대강 이해해 볼 수 있습니다.

(RSA와는 다르다! RSA와는!)

'각각의 문자를 key만큼씩 더한다'

라는 암호화 알고리즘을 생각해 봅시다.

원문  : KBS1tv

key가 1일 때

abcdefghijklmnopqrstuvwxyz 이니까

암호화: LCT2uw

복호화는 1씩 빼면 되겠죠?

여기서 키는 1로, 암호화와 복호화에 같은 키 1이 쓰였습니다.

이런 것을 대칭키 알고리즘이라고 합니다.
  • AES
Rijndael 암호에 기반한 블록 암호 방식으로
AES공모전에서 21개의 알고리즘 경쟁중 1등으로 선정되어
2001년 미국 표준 기술 연구소(NIST)에 의해 표준으로 제정되었습니다.

미 국가안보국에 의해 1급비밀에 사용할 수 있도록 승인된 알고리즘 중

최초로 공개되어 있는 알고리즘입니다.
-------------AES--------------

S-Box
ShiftRows
MixColumns
AddRoundKey
----------
이후
BASE64로 인코딩
PKCS7 / PKCS5 Padding
------------------------------

라는 과정을 거치는데요,


직접 구현해보지는 않았습니다.


C 구현 (https://github.com/saju/misc/blob/master/misc/openssl_aes.c?p=36)

Java 구현 (http://aesencryption.net/#Java-aes-encryption-example)

2015년 5월 22일 금요일

RSA에 대한 설명과 간단한 구현 (C++)


안녕하세요.

SSL에 대해 공부하던중 RSA가 잘 이해가 안되서 직접 간단하게 구현해 보았습니다.

이해를 돕기위해 색상을 넣었는데요.

노란색은 폐기.

초록색은 공개.

붉은색은 비공개 입니다.



  • RSA 준비과정


1. p!=q 인 소수 p,q 를 고릅니다.

2. N=p*q;

3. P=(p-1)*(q-1);

4. P를 바탕으로 다음을 만족하는 e를 찾습니다.

e<P , GCD(P,e) == 1;

5. eP를 이용해 다음을 만족하는 d를 찾습니다.

d*e%P==1

6. 이제 pq, P는 폐기합니다.

구해진 것들은 다음과 같습니다.

p,q,N,P,d,e

공개키는 N,e
개인키는 N,d




  • RSA 암호화

보내려는 메시지 M을 준비합니다. 상대방의 공개키 N,e를 확인합니다.

M을 N보다 작게 m으로 바꾸는데, 바꾸는 방법은 메시지와 함께 보내줍니다.

암호화 메시지 c = m^e % N 입니다.



  • RSA 복호화

암호화된 메시지 c를 받았습니다. 개인키 N,d 를 통해 변경된 메시지 m을 찾습니다.

변경된 메시지 m = c^d % N

m을 원래 메시지 M으로 바꾸면 됩니다. (이건 암호화 한 사람이 보내줍니다.)



  • 크래커

스니핑을 통해 메시지 c를 얻었다고 칩시다. m을 M으로 변환하는 방법도요.

공개키 N,e는 공개되어있기 때문에 쉽게 얻었습니다.

우리는 암호화 하는 방법을 알고 있습니다.

메시지 c=m^e % N 입니다.

그리고 우리는 c, N, e 를 알고있습니다.

그런데 말입니다. m을 구할 수 있을까요?


그러나 불행히도 c, N, e를 알아도 m을 구할 수는 없습니다.

왜냐하면 저 식을 만족하는 m의 개수가 엄청나게 많기 때문입니다.

예를들면, c가 8, N이 33, e가 3인경우

m은 2 , 35 ...등등이 될 수 있습니다.

또, 수가 크면 계산하는데 시간이 굉장히 오래 걸립니다.


그러므로

꼭 d를 알아야하는데, d*e%P==1 에서 나왔죠.

꼭 P를 알아야하는데, P=(p-1)*(q-1) 에서 나왔죠.

 p, q를 알아야하는데, N = p * q이 보통 굉장히 크므로

N을 통해 p, q를 구하려면 굉장히 많은 시간이 걸립니다.





  •  증명 : m == c^d % N


c = m^e % N 이니까 (암호화 하는 부분 참조)

m = c^d % N 에 c를 대입하면 (m^e % N)^d % N 이죠.

mod연산의 특성에 따라

(m^e % N)^d % N == m^(e*d) % N

준비과정 5번에서 d*e%P==1 이었기 때문에 d*e=k*P+1 (k는 상수) 이고,

P=(p-1)*(q-1) 이기 때문에 m^(e*d) % N 에 대입하면

m^(k*(p-1)*(q-1)+1) % N 이 됩니다.


m^(k*(p-1)*(q-1)+1) % N == (m^(p-1))^(k*(q-1))*M % N

(m^(p-1))^k*(q-1))*m % N== 1^(k*(q-1))*m % N==m % N

이므로 c^d % N == m % N


m은 N보다 작으므로 m % N == m.

따라서 c^d % N == m


어떻게 이런걸 생각해 냈을까요?

결국 이 공로로  Rivest, Shamir, Adleman

세 사람은 2002년 튜링상을 받게됩니다.

부럽죠......



  • 안전성

1999. 8. 22 에 암호키 155자리 수가 네덜란드, 캐나다, 미국 등 구미 6개국의

11개 연구기관으로 이루어진 공동연구팀에 의해 292대의 PC와 워크스테이션 등을 활용해

작업 개시 7개월 반만에 RSA의 암호화에 사용하는 암호키(열쇠)인 512비트의 숫자

(암호코드 RSA­155)를 General Number Field Sieve방법을 이용하여

소인수 분해하는데 성공했습니다.


또한 소인수분해 알고리즘을 이용하지 않고도 공격이 가능한데,

그것은 RSA서명에 의한 RSA암호 공격입니다.

이것은 다음 글을 참고하길 바랍니다.

RSA 서명에 의한 RSA 암호 공격

따라서 취약해 지지 않기 위해서는 두 소수를 선택할 때 규칙을 따라야 합니다.

1. p, q의 크기가 거의 같을 것.

2. p-q 가 클 것.

3. p-1 이 큰 수를 인수로 가질 것.

4. p+1 이 큰 수를 인수로 가질 것.



이외에도 1993년 피터 쇼어는 쇼어 알고리즘을 발표,

양자 컴퓨터를 이용하여 임의의 정수를 다항 시간 안에

소인수 분해하는 방법을 발표하였기 때문에,

미래에 양자 컴퓨터가 상용화 된다면

결국 RSA는 무용지물이 될 것으로 예상됩니다.



  • 코드

//RSA 암호화 -> 해독하는 간단한 프로그램입니다.



#include
#include  
using namespace std;


int GCD(int a, int b)
{
int tmp;
while (1)
{
if (a < b) swap(a, b);

if (a%b == 0) return b;
else
{
tmp = a%b;
a = b;
b = tmp;
}
}
}


int Get_e(int P)
{
int e;
for (e = 2; e < P; e++)
{
if (GCD(P, e) == 1)
{
return e;
}
}
}

int Get_d(int P,int e)
{
int d;
for (d = 1;; d++)
{
if ((d*e) % P == 1)
{
return d;
}
}
}
int Get_m(int M, int N)
{
int cnt=0;
while (M > N)
{
M -= N;
cnt++;
}
return cnt;
}


int PowWithMod(int x, int y, int mod)
{
//x의 y승
int ret = 1;
int i;
for (i = 0; i < y; i++)
{
ret = ret*(x%mod);
ret %= mod;
}
return ret%mod;
}



void main()
{
int p,q;
int e, N, P, d, c;
int m, M;
int mf;
int cnt;
cout << "두 소수 p,q 입력 :"< cin >> p >> q;

N = p*q;
P = (p - 1)*(q - 1);
e=Get_e(P);
d = Get_d(P, e);
system("cls");

cout << "-RSA 암호화-" << endl;
cout << "공개키는 <" < 입니다."< cout << "개인키는 <" << N << "," << d << "> 입니다." << endl;
cout << "보내고 싶은 메시지를 입력하세요(M)" << endl;
cin >> M;
//임의의 방법으로 M->m으로 변환시킵니다. m은 N보다 작아야합니다.
//이 코드에서 임의의 변환방법은 m이 N보다 클 때마다 N으로 빼주는 것입니다.
//실제로는 더 복잡한 방법들이 사용됩니다.
//또한 이 방법은 미리 메시지를 보낼 사람에게도 알려주어야 합니다.
cnt = Get_m(M, N);
m = M - cnt*N;
//cout << "메시지 M이 N보다 작은 m으로 변환되었습니다. (N=" << N << ",m=" << m << ",cnt=" < system("cls");

c = PowWithMod(m, e, N);

cout << "-RSA 복호화-" << endl;
cout << "당신은 암호화된 메시지를 얻었습니다." << endl;
cout << "암호화된 메시지는 " << c << "입니다."< cout << "공개키는 입니다." << endl;
cout << "복호화 한 후 cnt*N를 더하면 실제 메시지가 됩니다. (cnt*N="< cout << "실제 메시지는 무엇일까요?" << endl;
cin >> p;
m = PowWithMod(c, d, N);

if (p == m + cnt*N) cout << "맞았습니다! ";
else cout << "틀렸습니다! ";
cout << "실제 메시지는 ("<< m + cnt*N << ") 입니다."<< endl;
cout << "개인키는 였습니다." << endl;
}