티스토리 뷰
개요
지난번 포스팅에 이어 실제 코드 구현을 해보자
- 실제구현은 "권경모"님과 함께 하였다.
덤으로 Constant time comparison 에 대해서도 알아보자 .
(참고) 현재까지 관련 포스팅 모음
- Slack slash command: Verifying requests from Slack: https://jusths.tistory.com/75
- Golang: Github - Travis-CI - Heroku: https://jusths.tistory.com/69
- Slack slash command + Golang server: https://jusths.tistory.com/72
- Slack slash command 는 무얼 보내주는 걸까: https://jusths.tistory.com/73
드디어, 실제 코드를 보자
- 코드링크: https://github.com/nicewook/slack_slash_cmd2
1) 환경변수 가져오기
로컬 PC에 SLACK_SIGNING_SECRET 이라고 환경변수를 설정해두었다. 이제 Golang 코드 내에서 읽어와 쓸 수 있다.
set 으로 설정하고 echo 로 값을 확인해보자.
os.LookupEnv() 함수를 이용해 "SLACK_SIGNING_SECRET" 환경변수를 읽어와서
slack2 의 변수인 SlackSigningToken 에 저장해둔다.
2) HTTP POST 에서 원하는 정보 추출하기
- HTTP POST 의 Handler() 함수에서는 우선 Verification 을 시도한다.
- 필요한 재료인, 받은 HTTP POST request message 와 Server 의 환경변수 값을 가져온 slackSigningToken 을 VerifyRequest() 에 넣어준다.
→ 이때 verification 에서 message 를 consume 해버리면, verification 이후의 r.ParseForm() 에서 쓸 게 없다.
→ 이에 대한 대비책 참고 링크: https://jusths.tistory.com/65
- 만약 Verification 과정을 무사히 마쳤다면 Server 는 "Request accepted" 라는 회신을 할 것이다.
→ 물론 최종 목표는 시간 정보를 받아 다른 Time zone 의 시간으로 변경, 회신하는 것이다.
- 첫번째 사각 박스에서 req.Body 정보를 추출해낸뒤, 다시 req.Body 를 채워준다. (위에 언급한 대비책 적용)
- 두번째 사각 박스에서 verification 에 필요한 세 정보인 request Body, timestamp, signature 를 추출한 다음
서버가 가진 slackSiginingToken 과 함께 Verify() 함수로 넘겨준다.
3) HMAC 으로 signature 만들어 비교하기
- Server 에서 Signature 를 만들기 위한 재료를 message 로 만들어서 checkMAC() 함수로 보낸다.
- Golang 이 제공하는 hmac 과 key, message 를 조합하면 아래와 같이 calculatedMAC 을 계산해낼 수 있다.
- 참고: Golang 에서의 HMAC 사용법: https://golang.org/pkg/crypto/hmac/
- calculatedMAC: Golang Server 가 계산해낸 signature
- receivedMAC: Slack 이 계산해서 보내온 signature
- 이 둘을 그냥 비교해도 동작은 하지만, 보안상 안전한 hmac.Equal() 을 이용하여 verify 해준다.
hmac.Equal() 과 보안
hmac.Equal() 을 들여다보면 subtle.ConstantTimeCompare() 를 사용하고,
이 함수의 설명을 보면 중요한 문구가 나온다.
"The time taken is a function of the length of the slices and is independent of the contents"
함수 실행시 소요시간은, 비교하는 슬라이스의 길이와 관련이 있고, 슬라이스가 담고 있는 내용과는 무관하다는 것이다.
이 말의 의미를 찾아가다보면 "constant time comparison" 이란 키워드를 만나게 된다.
|
|
Constant time comparison
아래 링크내용을 짧게 줄여서 설명해본다.
관련 링크: https://codahale.com/a-lesson-in-timing-attacks/
단순히 문자열 두 개를 비교할 때에는 결과값이 리턴되는 시간이 가변하며,
이를 통해 해커의 attack 이 가능하다는 것이다.
우리의 Token 이 "CCCCC" 라고 가정해보자
해커는 A****, B****, C**** 를 차례대로 시도해본다.
이때 각각의 리턴시간이 1ms, 1ms , 2ms 이라면 해커는 첫번째 문자가 C라는 것을 알아차리게 된다.
왜냐하면, 단순 문자열 비교는 A, B 의 경우는 동일 문자열이 아니라고 바로 리턴해주지만,
C 의 경우는 첫번째 문자는 같다는 것을 확인하고, 두번째 문자열을 비교하는 작업까지 하기 때문이다.
이게 과연 가능할까 싶지만, 실제로는 로컬 PC 뿐 아니라 LAN 환경하에 원격의 서버에 대해서도 약 20 us 정도까지도 구분해 낼 수 있다 한다.
해법은 무엇일까?
간단하다. 비교할 문자열의 모든 문자를 비교한 다음에 그 결과를 리턴하게 하는 것이다.
이것이 위에 ConstantTimeCompare() 함수의 설명에서 언급한
"The time taken is a function of the length of the slices and is independent of the contents" 의 의미이다.
'golang' 카테고리의 다른 글
Go Modules - Local Modules 실전 (1) | 2019.04.10 |
---|---|
Go Modules - Local Modules (0) | 2019.04.10 |
Slack slash command: Verifying requests from Slack (0) | 2019.02.19 |
Golang Channel 의 자명한 이치 (Axioms) (0) | 2019.02.18 |
slack slash command 는 무얼 보내주는 걸까 (0) | 2019.02.15 |
- Total
- Today
- Yesterday
- notion
- 체호프
- 인텔리제이
- 독서
- 클린 애자일
- go
- intellij
- websocket
- github
- 독서후기
- API
- Shortcut
- 2023
- solid
- bun
- JIRA
- agile
- Gin
- 제이펍
- pool
- 영화
- ChatGPT
- Bug
- golang
- 잡학툰
- 노션
- OpenAI
- folklore
- strange
- postgres
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |