이번 프로젝트 중에 OAuth를 구현하는 프로젝트가 있어 늘 궁금했지만, 그리고 늘 해야한다고 생각만 했던 OAuth에 대해 공부한 내용을 최대한 간단하고 간결하게 이야기해보려고 한다.
OAuth 1.0 ? 2.0?
왜 다들 2.0 만 사용하는지 궁금했는데, 간단히 요약하면, 2.0은 Https에게 보안을 전가 하고 인증에만 중심을 두겠다는거고, 1.0은 http던 https던 ftp던 뭐던 상관없이 (독립적으로) 인증을 하기위해 직접 보안을 신경써서 전송하겠다는 거다.
그 외의 명칭이 다르거나 다소 차이점은 있지만 가장큰 차이점은 위에서 말한 전송 방식에 대한 보안을 어떻게 신경쓰느냐 인 것 같다.
OAuth2.0 그리고 지옥으로 가는 길 과 같은 2.0은 위험하다! 라는 이야기도 있지만, 그러면 구글이 아직 까지 쓰고 있지 않을테니 여기서 가장 위험하다고 말해지는 https가 아닌 http를 사용할 경우의 위험만 신경쓰고 OAuth2.0는 https 상에서 통신 한다는 것만을 잊지 말자.
통신 순서
늘 어느 글을 가나 나오는 통신 순서다.
라고 하는데 솔직히 이것만 봐도 그리고 설명을 쭉 봐도 이해가 잘 되지 않는다. 그래서 그냥 내 나름 대로 정리해 보려고 한다.
목표와 명칭 정리
나는 내가 운영하는 사이트에 페이스북 로그인을 넣으려고 한다. 그럴때 아래와 같은 명칭을 가진다.
Resource Owner: 로그인 하는 사람이다. Client: 내가 운영하는 사이트다. Resource Server: 페이스북이다. Authorization Server: 인증서버인데. 그냥 Resource Server와 통합되있다고 생각하자.
1. OAuth 준비
먼저 난 페이스북 개발자 사이트에 가서 Client id와 Client secret key를 발급 받는다.
2. 로그인 페이지에 페이스북 로그인 버튼을 추가한다.
이제 처음 들어오는 유저가 페이스북 로그인을 클릭하고,
최초 접속이니 내 서버의 Client id와 함께 해당 유저를 페이스북 OAuth 인증 페이지로 리다이렉트 한다.
늘 보던 이런거
확인을 누르면 callback URL으로 임시 패스워드[Authorization code]를 전달한다.
3. 내 서버에서 Access Token 발급 요청
서버는 임시 패스워드와[Authorization code] 내 서버의 client id, secret key를 가지고 Access Token을 발급 요청을 한다. (혹은 Refresh token도 함께 받는다) 그리고 저장한다.
4. 내 서버에서 Access Token을 사용해 사용자 데이터에 접근한다.
발급 받은 Access Token을 사용해 사용자에 데이터에 접근할 수 있다. 그 정보로 로그인 내 서버에 로그인 시켜주면된다.
다만, 일정 시간이 지나면 Access Token이 만료되기에 Refresh Token을 사용하여 재발급 받는다.
이때 Refresh Token은 영구적으로 안별할 수 도 있고, 재발급 받을 때 마다 Refresh Token도 재발급 될 수 있다. 이는 각 사이트 정책을 따른다.
+α 이미 정보가 저장 되있으면?
그럼 위 2번에서 바로 내 서버의 callback url로 임시 패스워드가[Authorization code] 보내지고 Access Token을 가지고 혹은 갱신해서 로그인 정보를 가지고 올 수 있다.
즉 확인 버튼 누르는 과정만 없어졋다고 생각 해도 된다.
여튼 여러가지 설명이 있는데 내가 이해한 방식은 위와 같은 방식이고, OAuth를 이해 하는데 도움이 되었으면 좋겠다.
/home/silnex/test/spaceA.php > A
/home/silnex/test/spaceB.php >
/home/silnex/test/index.php > INDEX
spaceB btest function
PHP Fatal error: Uncaught Error: Call to undefined function INDEX\atest() in /home/silnex/test/index.php:11
Stack trace:
#0 {main}
thrown in /home/silnex/test/index.php on line 11
require('spaceA.php') 의 결과가 출력된 1번째 줄을 보면 네임스페이스는 index.php에서 선언된 INDEX가 아닌 spaceA.php 파일에서 선언된 네임 스페이스다.
require('spaceB.php')의 결과가 출력된 2번째 줄을 보면 네임스페이스는 INDEX도 A도 아닌 아무 선언 안된 것을 볼 수 있다. 즉, 네임스페이스는 다른파일엔 영향을 끼치지 않는다는 걸 알 수 있다.
btest()의 실행 결과인 4번째 줄을 보면, 정상적으로 실행되고 있으나, atest()의 경우 5번째줄 부터 표시된 에러가 나는것을 볼 수 있다.
이를 통해 함수가 받는 영향을 알 수 있는데, 기본적으로 Namespace가 없는 함수를 먼저 호출 하고, 만약 함수가 없다면, 현재 파일의 Namespace의 함수를 찾는 것을 확인 할 수 있다.
먼저 10bit의 key인 1010000010를 함수 P10에 넣는다.
▶ P10(1010000010) ::= (1000001100)
P10의 결과 값을 5bit 씩 쪼개어 LS-1을 진행한 뒤 다시 하나로 합친다.
▶ LS-1(10000) = (00001) LS-1(01100) = (11000) ::= 00001 11000
subKey 1 Gen LS-1의 결과 값을 P8에 넣는다.
▶ P8(0000111000) ::= 10100100 (k1)
LS한 결과 값에 LS-2를 한번 더 적용한 뒤 하나로 합친다.
▶ LS-2(00001) = (00100) LS-2(11000) = (00011) ::= 00100 00011
8bit의 PlainText를 함수 IP에 넣는다.
▶ IP(01101101) ::= 1110 0110 {START fk}IP의 결과 값 중 오른쪽4bit(0110)를 함수 E/P에 넣는다.
▶ E/P(0110) ::= 00111100 E/P 결과 값에 subkey k1과 xor 연산을 한다.
▶ 00111100 ⊕ 10100100 ::= 10011000 k1과 Xor한 결과 값을 S-Box에 넣어 매치되는 행렬값을 구한 뒤 합친다.
▶ S0(11,00) = S0(3,0) = 11 (3) | S1(10,00) = S1(2,0) = 11 (3) ::= 1111
S-Box의 결과 값을 P4에 넣고 처음 IP의 결과 값 중 왼쪽4bit와 Xor 연산을한다.
▶ P4(1111) ::= 1111 1111 ⊕ 1110 ::= 0001 {END fk} Xor의 결과 값과 처음 IP의 결과 값 중 오른쪽4bit의 순서를 바꾼다.
▶ SW(0001 0110) ::= {0110 0001}
위 함수를 통해 fk를 2번 반복하는데 Encryption과 과정은 동일하다.
하지만 이번엔 Decryption이기 때문에 fk에서 사용되는 key의 순서가 k2, k1순으로 사용되어야한다.
8bit의 CipherText를 함수 IP에 넣는다.
▶ IP(01000110) ::= 1100 0001 {START fk}IP의 결과 값 중 오른쪽4bit(0001)를 함수 E/P에 넣는다.
▶ E/P(0001) ::= 10000010 E/P 결과 값에 subkey k1과 xor 연산을 한다.
▶ 10000010 ⊕ 01000011 ::= 11000001 k1과 Xor한 결과 값을 S-Box에 넣어 매치되는 행렬값을 구한 뒤 합친다.
▶ S0(10,10) = S0(2,2) = 01 (1) | S1(01,00) = S1(1,0) = 10 (2) ::= 0110
S-Box의 결과 값을 P4에 넣고 처음 IP의 결과 값 중 왼쪽4bit와 Xor 연산을한다.
▶ P4(0110) ::= 1010 1010 ⊕ 1100 ::= 0110 {END fk} Xor의 결과 값과 처음 IP의 결과 값 중 오른쪽4bit의 순서를 바꾼다.
▶ SW(0110 0001) ::= {0001 0110}
Padding Oracle Attack을 공부하기 위해 CBC에 대해서 공부하던 중 Block Cipher에 대해 자세히 알고 싶다는 생각이 들어,
지금은 사용되지 않지만 가장 유명한 암호화 방식인 Data Encryption Standard(DES)를 공부하게 되었다. DES알고리즘을 학습해야하지만 일반적인 DES에서 사용되는 key인 56bit는 다소 복잡해 이해 하기가 어려워,
key가 10bit로 이루어진 Simplified DES를 통해 DES알고리즘에 대해서 학습해본다.
SDES는 기존 DES와 Key의 bit수 차이와 반복되는 Round 의 차이만 있을 뿐 알고리즘은 동일하며,
SDES의 확장을 통해 DES를 이해를 위해 만들어진 SDES인 만큼 DES의 56bit키가 왜 위험한지에 대해서도 충분이 이해 할 수 있다고 한다.
Analyze DES
SDES Scheme (위 그림에 오류가 있는데 keygen을 하는 부분에서 2번째 Shift는 Shift를 2번해주어야 한다.)
DES는 대칭키 암호이기 때문에 Key를 통해 subKey인 K1과 K2를 생성하는 Key Generation(①)과정, (PlainText를 Block단위로 쪼개어 암호화 하기위해서다. DES가 Block Cipher라 불리는 이유)
PlainText(평문)를 암호화하는 Encryption(②) 과정,
암호화된 CipherText(암호문)를 복호화 하는 Decryption(③)과정까지 총 3개의 과정이 필요하다.
수식으로 표현하니 이해하기 여러울 수 도있지만, 단순히 순서를 바꾸는 역할을 할 뿐이다.
예를들어 P10(1,2,3,4,5,6,7,9,0) = (3,5,2,7,4,10,1,9,8,6) 처럼 순서만 바꾸는 역할을 한다.
다만, P10에서 사용되는 바뀌는 순서에 대한 값은 임의의 값이 아닌 SDES에서 고정적인 값이다.
P10을 표로써 표현하면 아래와 같이 표현할 수 있다.
P10
3 5 2 7 4 10 1 9 8 6
Function P8
input length(or bit): 10 output length(or bit): 8
또한 P10과 같은 의미이나 10개의 인자값을 받아 8개만 선택해 출력하는 함수이다.
수식으로 표현하면,
즉, 결과 값에 없는 k1, k2는 버려진다. 이를 표로 표현하면 아래와 같이 표현 할 수 있다.
P8
3 7 4 8 5 10 9
Function Shift
input length(or bit): 5 output length(or bit): 5
Shift는 BitShift연산자중에서 Left Shift를 의미하는데, 왼쪽으로 넘어간 bit는 오른쪽에서 나오게 된다.
즉, 10011(2)을 Shift 2번 이라고 한다면, 00111(2)이 되는것이다.
대게 줄여서 LS라고 하며 Shift횟수에 따라 한번이면 LS-1 두번이면 LS-2라고 한다.