Posted onInComputer
,
CodingTestDisqus: Symbols count in article: 1.6kReading time ≈1 mins.
ROT13
문제
ROT13은 카이사르 암호의 일종으로 영어 알파벳을 13글자씩 밀어서 만든다.
예를 들어, “Baekjoon Online Judge”를 ROT13으로 암호화하면 “Onrxwbba Bayvar Whqtr”가 된다. ROT13으로 암호화한 내용을 원래 내용으로 바꾸려면 암호화한 문자열을 다시 ROT13하면 된다. 앞에서 암호화한 문자열 “Onrxwbba Bayvar Whqtr”에 다시 ROT13을 적용하면 “Baekjoon Online Judge”가 된다.
ROT13은 알파벳 대문자와 소문자에만 적용할 수 있다. 알파벳이 아닌 글자는 원래 글자 그대로 남아 있어야 한다. 예를 들어, “One is 1”을 ROT13으로 암호화하면 “Bar vf 1”이 된다.
문자열이 주어졌을 때, “ROT13”으로 암호화한 다음 출력하는 프로그램을 작성하시오.
입력
첫째 줄에 알파벳 대문자, 소문자, 공백, 숫자로만 이루어진 문자열 S가 주어진다. S의 길이는 100을 넘지 않는다.
출력
첫째 줄에 S를 ROT13으로 암호화한 내용을 출력한다.
예제 입력 1
1
Baekjoon Online Judge
예제 출력 1
1
Onrxwbba Bayvar Whqtr
예제 입력 2
1
One is 1
예제 출력 2
1
Bar vf 1
해결
시저암호의 알고리즘은 secret key가 주어지면 문자를 secret key만큼 shift 하는 것으로
$f(x) = (x + key) mod 26 $ 이다.
대문자 소문자 구분은 Ascii 코드를 이용하여 대소문자를 구별할 수 있으며 문제는 N 이후로는 13번 shift를 하면 A 로 넘어가버린다.
이 문제를 해결하기 위해 key가 13 이니까 N은 N - A = 13 이므로 $26 mod 26 = 0$ 이 되므로
일반적인 문자열에서 줄바꿈은 허용되지 않고 공백(white-spce)를 표현하기 위해 백슬래시(\)로 시작하는 이스케이프 시퀀스(Escape Sequence)를 사용해야한다. 템플릿 리터럴은 일반적인 문자열과 다르게 여러 줄에 걸쳐 문자열을 작성할 수 있으며 템플릿 리터럴 내의 모든 white-space는 있는 그대로 적용된다.
OAuth 2.0은 OAuth 1.0의 단점을 개선한 것으로, OAuth 1.0은 웹 애플리케이션이 아닌 애플리케이션에서는 사용하기 곤란하다는 단점이 있다. 그리고 절차가 복잡하여 OAuth 구현 라이브러리를 제작하기 어렵고, 복잡한 절차 때문에 Service Provider에게도 연산 부담이 발생한다.
OAuth 1.0과 OAuth2.0의 차이
인증절차의 간소화로 인해 개발자가 구현하기 쉬워짐
기존에 사용하던 용어도 바뀌면서 Authorization Server와 Resource서버의 분리가 명시적으로 되었다.
다양한 인증방식을 지원
OAuth 2.0의 특징
인증절차 간소화
기능을 단순화했으며 기능과 규모의 확장성 등을 지원한다.
OAuth 1.0은 디지털 서명 기반이지만 OAuth 2.0의 암호화는 HTTPS에 맡김으로 복잡한 디지털 서명에 관한 로직을 요구하지 않으므로 개발이 쉬움 쉽게말해 암호화가 필요 없으며 HTTPS를 사용하고 HMAC을 사용하지 않는다.
용어변경
Resource Owner : 사용자 (1,0 User해당)
Resource Server : 자원을 호스팅 하는 서버[REST API Server(1.0 Protected Resource)]
Authorization Server : 사용자의 동의를 받아 권한을 부여하는 인증서버.(API 서버와 같을 수 있다. 1.0 Service Provider) 일반적으로 Resource Server와 같은 URL 하위에 있는 경우가 많다.
Client : Resource Server에서 제공하는 자원을 사용하는 애플리케이션[ Third Party Application(1.0 Service Provider해당)]
Resource Server와 Authorization Server의 분리
커다란 서비스는 인증 서버로 분리하거나 다중화 할 수 있어야한다.
Authorization Server의 역할을 명확히 한다.
다양한 인증방식(grant_type)
Authorization Code Grant
Implicit Grant
Resource Owner Password Credentials Grant
Client Credentials Grant
Device Code Grant
Refresh Token Grant
웹 애플리케이션이 아닌 데스크탑, 앱 애플리케이션 지원강화
그외
Signature의 단순화 정렬과 URL 인코딩이 필요 없다.
Access Token 갱신 Ouath 1.0에서 Access Token을 받으면 Access Token을 계속 사용할 수 있다. OAuth2.0에서는 보안 강화를 위해 Access Token의 Life-time을 지정할 수 있도록 했다.
인증 종류
OAuth 2.0은 6가지의 인증종류가 있다.
Authorization Code Grant
Authorization Code Grant는 일반적인 웹사이트에서 소셜로그인과 같은 인증을 받을 때 가장 많이 쓰는 방식으로 기본적으로 지원하고 있는 방식이다.
1 Authorization Request : 클라이언트가 Redirect URL을 포함하여 Authorization server 인증 요청을 한다.
2 User Login & Consent : Authorization Server는 유저에게 로그인창을 제공하여 유저를 인증하게 된다.
4, 5, 6, 7, 8, 9 :Client는 코드를 Authorization server에 Access Token을 요청한다. 그리고 Authorization 서버는 클라이언트에게 Access token을 발급해주고, Access Token을 이용하여 Resource server에 자원을 접근할 수 있게 된다.
10, 11 : 토큰이 만료된다면 Refresh token을 이용하여 토큰을 재발급 받을 수 있다.
Implicit Grant
Public Client인 브라우저 기반의 애플리케이션(Javascript application)이나 모바일 애플리케이션에서 바로 Resource Server에 접근하여 사용할 수 있는 방식이다.
일반적인 문자열에서 줄바꿈은 허용되지 않고 공백(white-spce)를 표현하기 위해 백슬래시(\)로 시작하는 이스케이프 시퀀스(Escape Sequence)를 사용해야한다. 템플릿 리터럴은 일반적인 문자열과 다르게 여러 줄에 걸쳐 문자열을 작성할 수 있으며 템플릿 리터럴 내의 모든 white-space는 있는 그대로 적용된다.
Posted onEdited onInComputer
,
CodingTestDisqus: Symbols count in article: 2.4kReading time ≈2 mins.
후위 표기식
문제
수식은 일반적으로 3가지 표기법으로 표현할 수 있다. 연산자가 피연산자 가운데 위치하는 중위 표기법(일반적으로 우리가 쓰는 방법이다), 연산자가 피연산자 앞에 위치하는 전위 표기법(prefix notation), 연산자가 피연산자 뒤에 위치하는 후위 표기법(postfix notation)이 그것이다. 예를 들어 중위 표기법으로 표현된 a+b는 전위 표기법으로는 +ab이고, 후위 표기법으로는 ab+가 된다.
이 문제에서 우리가 다룰 표기법은 후위 표기법이다. 후위 표기법은 위에서 말한 법과 같이 연산자가 피연산자 뒤에 위치하는 방법이다. 이 방법의 장점은 다음과 같다. 우리가 흔히 쓰는 중위 표기식 같은 경우에는 덧셈과 곱셈의 우선순위에 차이가 있어 왼쪽부터 차례로 계산할 수 없지만 후위 표기식을 사용하면 순서를 적절히 조절하여 순서를 정해줄 수 있다. 또한 같은 방법으로 괄호 등도 필요 없게 된다. 예를 들어 a+bc를 후위 표기식으로 바꾸면 abc+가 된다.
중위 표기식을 후위 표기식으로 바꾸는 방법을 간단히 설명하면 이렇다. 우선 주어진 중위 표기식을 연산자의 우선순위에 따라 괄호로 묶어준다. 그런 다음에 괄호 안의 연산자를 괄호의 오른쪽으로 옮겨주면 된다.
예를 들어 a+bc는 (a+(bc))의 식과 같게 된다. 그 다음에 안에 있는 괄호의 연산자 를 괄호 밖으로 꺼내게 되면 (a+bc)가 된다. 마지막으로 또 +를 괄호의 오른쪽으로 고치면 abc*+가 되게 된다.
다른 예를 들어 그림으로 표현하면 A+B*C-D/E를 완전하게 괄호로 묶고 연산자를 이동시킬 장소를 표시하면 다음과 같이 된다.
이러한 사실을 알고 중위 표기식이 주어졌을 때 후위 표기식으로 고치는 프로그램을 작성하시오
입력
첫째 줄에 중위 표기식이 주어진다. 단 이 수식의 피연산자는 A~Z의 문자로 이루어지며 수식에서 한 번씩만 등장한다. 그리고 -A+B와 같이 -가 가장 앞에 오거나 AB와 같이 가 생략되는 등의 수식은 주어지지 않는다. 표기식은 알파벳 대문자와 +, -, , /, (, )로만 이루어져 있으며, 길이는 100을 넘지 않는다.
출력
첫째 줄에 후위 표기식으로 바뀐 식을 출력하시오
예제 입력 1
1
A*(B+C)
예제 출력 1
1
ABC+*
풀이
스택을 이용해서 문제를 해결할 수 있다. 이 문제는 괄호가 있거나 연산자의 우선순위가 높을경우 라는 경우의 수가 있다.
publicstaticvoidconvertToPostfix()throws Exception { BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out)); BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); String infix = in.readLine();
Stack<Character> stack = new Stack<>(); for (char ch : infix.toCharArray()) { switch (ch) { case'+':case'-':case'*':case'/': //스택에 있는 연산자가 우선순위가 더 크거나 같으면 출력 while(!stack.isEmpty() && prec(stack.peek()) >= prec(ch)) out.write(stack.pop()); stack.push(ch); break; case'(': stack.push(ch); break; case')': char op = stack.pop(); //왼쪽괄호를 만날 때까지 계속 출력 while (op != '(') { out.write(op); op = stack.pop(); } break; default: //A~Z out.write(ch); break; } } while(!stack.isEmpty()) { out.write(stack.pop()); } out.flush(); out.close(); in.close(); ; }
Posted onInComputer
,
CodingTestDisqus: Symbols count in article: 1.7kReading time ≈2 mins.
[BaekJoon-1935] 후위표기식2
문제
후위 표기식과 각 피연산자에 대응하는 값들이 주어져 있을 때, 그 식을 계산하는 프로그램을 작성하시오.
입력
첫째 줄에 피연산자의 개수(1 ≤ N ≤ 26) 가 주어진다. 그리고 둘째 줄에는 후위 표기식이 주어진다. (여기서 피연산자는 A~Z의 영대문자이며, A부터 순서대로 N개의 영대문자만이 사용되며, 길이는 100을 넘지 않는다) 그리고 셋째 줄부터 N+2번째 줄까지는 각 피연산자에 대응하는 값이 주어진다. (3번째 줄에는 A에 해당하는 값, 4번째 줄에는 B에 해당하는값 , 5번째 줄에는 C …이 주어진다, 그리고 피연산자에 대응 하는 값은 정수이다)
출력
계산 결과를 소숫점 둘째 자리까지 출력한다.
예제 입력 1
1 2 3 4 5 6 7
5 ABC*+DE/- 1 2 3 4 5
예제 출력 1
1
6.20
예제 입력 2
1 2 3
1 AA+A+ 1
예제 출력 2
1
3.00
문제해결
스택을 이용하여 문제를 해결해나간다.
피연산자일 경우 스택에 Push하고 연산자를 만나면 두 수를 pop()하여 연산을 하고 연산결과를 다시 Push를 한다
publicstaticvoidpostfixNotation()throws Exception { BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out)); BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(in.readLine()); String postfix = in.readLine(); double[] numbers = newdouble[n]; for (int i = 0; i < n; i++) { numbers[i] = Double.parseDouble(in.readLine()); }
OAuth는 Open Authorization or Open Authentication이란 뜻으로 인터넷 사용자들이 비밀번호를 제공하지 않고 다른 웹 사이트 상의 자신들의 정보에 대해 웹 사이트나, 애플리케이션의 접근 권한을 부여할 수 있는 공통적인 수단으로 사용되는 접근 위임을 위한 개방형 표준이다. 구글, 페이스북, 트위터, 카카오, 네이버 등의 기업들이 타사 애플리케이션이나 웹 사이트의 계정을 공유할 수 있게 허용해준다.
애플리케이션 서비스 공급자들이(Service Provider) 유저의 비밀번호를 Third Party앱에 제공 없이 인증, 인가를 할 수 있는 표준 프로토콜이며, OAuth 인증을 하면 애플리케이션 API를 접근할 수 있는 권한을 얻을 수 있다.
과거에는 인증방식의 표준이 없기에 아이디와 비밀번호를 사용했고 이것은 보안상 취약한 구조를 가지고 있었다. 유저의 비밀번호가 노출될 가능성이 크기 때문이다. 이 문제를 해결하기 위해 OAuth의 인증이 등장했고 API를 제공하는 서버에서 인증을 진행하고 유저가 인증되었으면 Access Token을 발급하였다. 발급이 완료된 Access Token은 Third Party(Consumer) 애플리케이션에서 서비스 공급자(Service Provider)의 API를 안전하고 쉽게 사용할 수 있게 되었다.
용어
용어
설명
사용자(User)
Service Provider에 계정을 가지고 있으면서, Consumer 앱을 사용하려는 사용자
서비스 공급자(Service Provider)
OAuth를 통해 접근을 지원하는 웹 애플리케이션(Open API를 제공하는 서비스. ex) kakao, naver, facebook, google, etc.)
보호 자원(Protected Resource)
서비스 공급자(Service Provider)로부터 제공되어지는 API 자원들
소비자(Consumer)
Open API를 이용하여 개발된 OAuth를 사용하여 서비스 공급자의 기능을 사용하는 웹 사이트 또는 애플리케이션
소비자 키(Consumer Key)
소비자(Consumer)가 서비스 제공자(Service Provider)에게 자신임을 식별하는데 사용하기 위한 키
소비자 비밀번호(Consumer Secret)
소비자(Consumer)가 소유권을 인정하기 위해 소비자(Consumer)가 사용하는 Secret
요청 토큰(Request Token)
소비자가 사용자에게 접근권한을 인증받기 위해 필요한 정보가 담겨 있으며 후에 접근 토큰(Access token)으로 변환
접근 토큰(Access Token)
인증 후 사용자가 서비스 제공자가 아닌 소비자를 통해서 보호된 자원에 접근하기 위한 키를 포함한 값
토큰 암호(Token Secret)
주어진 토큰의 소유권을 인증하기 위해 소비자가 사용하는 Secret
OAuth 1.0의 WorkFlow
사전에 소비자(Consumer)는 서비스 공급자(Service Provider)로부터 Client Key와 Secret을 발급 받아야한다. 이것은 서비스 공급자(Service Provider)의 API를 사용할 것을 등록하는 것과 동시에 서비스 공급자(Service Provider)가 소비자(Consumer)을 식별할 수 있게 한다.
처리과정
Consumer는 Request Token을 받기위해 Consumer 정보, Signature 정보를 A 처럼 Service Provider에 보내어 Request Token을 요청하고 Service Provider는 Request Token을 발급하여 B 처럼 Consumer에게 결과를 보낸다.
Request Token을 받은 Consumer는 C 처럼 Service Provider의 인증 사이트로 이동하여 유저는 그곳에서 Service Provider의 유저임을 인증한다.
그러면 Service Provider는 D처럼 유저 인증이되면 Consumer에게 OAuth_token과 OAuth_verifier를 넘겨준다.
Consumer는 OAuth_token과 OAuth_verifier를 받고 E의 흐름처럼 다시 서명을 하여 Service Provider는 Access Token을 생성을 한다.
그리고 F처럼 다시 Consumer에게 Access Token을 전송하고 Accsss Token을 가진 Consumer는 Access Token 및 서명정보를 통해 G 처럼 Service Provider의 Protected Resource에 접근할 수 있다.
Request Token 요청 매개변수
매개변수
설명
oauth_callback
Service Provider가 인증을 완료한 후 리다이렉트할 Consumer의 웹 주소. 만약 Consumer가 웹 애플리케이션이 아니라 리다이렉트할 주소가 없다면 소문자로 ‘oob’(Out Of Band라는 뜻)를 값으로 사용한다.
oauth_consumer_key
Consumer를 구별하는 키 값. Service Provider는 이 키 값으로 Consumer를 구분한다.
oauth_nonce
Consumer에서 임시로 생성한 임의의 문자열. oauth_timestamp의 값이 같은 요청에서는 유일한 값이어야 한다. 이는 악의적인 목적으로 계속 요청을 보내는 것을 막기 위해서이다.
oauth_signature
OAuth 인증 정보를 암호화하고 인코딩하여 서명 값. OAuth 인증 정보는 매개변수 중에서 oauth_signature를 제외한 나머지 매개변수와 HTTP 요청 방식을 문자열로 조합한 값이다. 암화 방식은 oauth_signature_method에 정의된다.
oauth_signature_method
oauth_signature를 암호화하는 방법. HMAC-SHA1, HMAC-MD5 등을 사용할 수 있다.
oauth_timestamp
요청을 생성한 시점의 타임스탬프. 1970년1월 1일 00시 00분 00초 이후의 시간을 초로 환산한 초 단위의 누적 시간이다.
oauth_version
OAuth 사용버전. 1.0a는 1.0이라고 명시하면 된다.
oauth_signature 만들기
OAuth 1.0에서는 Service Provider에게 요청을 하려면 매번 oauth_signature 생성해야 한다. Consumer와 Service Provider가 같은 암호화(signing) 알고리즘을 이용하여 oauth_signature 만들어야 한다.
oauth_signature 다음과 같이 네 단계를 거쳐 만든다.
요청 매개변수를 모두 모은다. oauthsignature를 제외하고 ‘oauth‘로 시작하는 OAuth 관련 매개변수를 모은다. POST body에서 매개변수를 사용하고 있다면 이 매개변수도 모아야 한다.
매개변수를 정규화(Normalize)한다. 모든 매개변수를 사전순으로 정렬하고 각각의 키(key)와 값(value)에 URL 인코딩(rfc3986)을 적용한다. URL 인코딩을 실시한 결과를 = 형태로 나열하고 각 쌍 사이에는 &을 넣는다. 이렇게 나온 결과 전체에 또 URL 인코딩을 적용한다.
Signature Base String을 만든다. HTTP method 명(GET 또는 POST), Consumer가 호출한 HTTP URL 주소(매개변수 제외), 정규화한 매개변수를 ‘&’를 사용해 결합한다. 즉 ‘[GET|POST] + & + [URL 문자열로 매개변수는 제외] + & + [정규화한 매개변수]’ 형태가 된다. 이 예제에서는 ‘http://nid.naver.com/naver.oauth‘ 을 URL로 사용하고, 이 URL에 URL 인코딩을 적용한 값을 사용했다.
키 생성 3번 과정까지 거쳐 생성한 문자열을 암호화한다. 암호화할 때 Consumer Secret Key를 사용한다. Consumer Secret Key는 Consumer가 Service Provider에 사용 등록을 할 때 발급받은 값이다. HMAC-SHA1 등의 암호화 방법을 이용하여 최종적인 oauth_signature를 생성한다.
Access Token 생성 요청
Access Token을 요청하는 방법은 Request Token을 요청하는 방법과 거의 같지만, 사용하는 매개변수의 종류가 약간 다르고 oauth_signature를 생성할 때 사용하는 키가 다르다.
Access Token 을 요청할 때에는 매개변수 oauth_callback는 없고, oauth_token와 oauth_verifer가 있다.
Request Token 발급을 요청할 때에는 Consumer Secret Key를 사용해 oauth_token_secret를 생성했다.
Access Token 발급을 요청할 때에는 Consumer Secret Key에 oauth_token_secret을 결합한 값(Consumer Secret Key + & + oauth_token_secret)을 사용해 oauth_token_secret를 생성한다. 암호화 키를 변경하여 보안을 더 강화하는 것이다.
Access Token발급 요청 매개변수
매개변수
설명
oauth_consumer_key
Consumer를 구별하는 키 값. Service Provider는 이 키 값으로 Consumer를 구분한다.
oauth_nonce
Consumer에서 임시로 생성한 임의의 문자열. oauth_timestamp의 값이 같은 요청에서는 유일한 값이어야 한다. 이는 악의적인 목적으로 계속 요청을 보내는 것을 막기 위해서이다.
oauth_signature
OAuth 인증 정보를 암호화하고 인코딩하여 서명 값. OAuth 인증 정보는 매개변수 중에서 oauth_signature를 제외한 나머지 매개변수와 HTTP 요청 방식을 문자열로 조합한 값이다. 암화 방식은 oauth_signature_method에 정의된다.
oauth_signature_method
oauth_signature를 암호화하는 방법. HMAC-SHA1, HMAC-MD5 등을 사용할 수 있다.
oauth_timestamp
요청을 생성한 시점의 타임스탬프. 1970년1월 1일 00시 00분 00초 이후의 시간을 초로 환산한 초 단위의 누적 시간이다.
oauth_version
OAuth 사용 버전
oauth_verifier
Request Token 요청 시 oauth_callback으로 전달받은 oauth_verifier 값
oauth_token
Request Token 요청 시 oauth_callback으로 전달받은 oauth_token 값
위의 표에 정의한 매개변수를 상황에 맞게 정의한 다음 Access Token을 요청하면 oauth_token과 oauth_token_secret을 전달받게 된다. Service Provider에 따라 사용자의 아이디나 프로필 정보 같은 것들이 반환되기도 한다.
Acess Token 사용
매개변수
설명
oauth_consumer_key
Consumer를 구별하는 키 값. Service Provider는 이 키 값으로 Consumer를 구분한다.
oauth_nonce
Consumer에서 임시로 생성한 임의의 문자열. oauth_timestamp의 값이 같은 요청에서는 유일한 값이어야 한다. 이는 악의적인 목적으로 계속 요청을 보내는 것을 막기 위해서이다.
oauth_signature
OAuth 인증 정보를 암호화하고 인코딩하여 서명 값. OAuth 인증 정보는 매개변수 중에서 oauth_signature를 제외한 나머지 매개변수와 HTTP 요청 방식을 문자열로 조합한 값이다. 암화 방식은 oauth_signature_method에 정의된다.
oauth_signature_method
oauth_signature를 암호화하는 방법. HMAC-SHA1, HMAC-MD5 등을 사용할 수 있다.
oauth_timestamp
요청을 생성한 시점의 타임스탬프. 1970년1월 1일 00시 00분 00초 이후의 시간을 초로 환산한 초 단위의 누적 시간이다.