안경잡이개발자

728x90
반응형

대회 링크: codeforces.com/contest/1462

A번 문제: codeforces.com/contest/1462/problem/A

 

  N개의 수가 있다. 예를 들어 N = 8이라고 하면, 다음과 같이 수가 나열된다.

 

  원래 배열: a1, a2, a3, a4, a5, a6, a7, a8

 

  이때 다음과 같은 규칙에 따라 수를 재나열한다.

 

  변경된 배열: a1, a3, a5, a7, a8, a6, a4, a2

 

  이 문제에서의 요구사항은, 변경된 배열을 보고 원래의 배열을 맞추는 것이다. 문제 해결 아이디어는 굉장히 심플하다. 앞에서부터, 그리고 뒤에서부터 번갈아 가면서 출력하면 된다.

 

for _ in range(int(input())):
    n = int(input())
    a = list(map(int, input().split()))
    
    for i in range(n): 
        if i % 2 == 1:
            print(a[n - (i // 2) - 1], end=' ')
        else:
            print(a[i // 2],end=' ')
    print()

 

B번 문제: codeforces.com/contest/1462/problem/B

 

  문장이 주어졌을 때, 하나의 substring을 제거하여 "2020"이라는 문자열을 만들 수 있는지 체크하는 문제다. 이 문제를 풀기 위한 가장 간단한 방법은 제일 앞부분과 제일뒷 부분을 확인하여 "2020"을 만들 수 있는지 확인하는 것이다.

 

(공백) 2020
2 020
20 20
202 0
2020 (공백)

 

for _ in range(int(input())):
    n = int(input())
    data = input()
    
    if data[n - 4:] == "2020":
        print("YES")
    elif data[:1] == "2" and data[n - 3:] == "020":
        print("YES")
    elif data[:2] == "20" and data[n - 2:] == "20":
        print("YES")
    elif data[:3] == "202" and data[n - 1:] == "0":
        print("YES")
    elif data[:4] == "2020":
        print("YES")
    else:
        print("NO")

 

C번 문제: codeforces.com/contest/1462/problem/C

 

  하나의 정수 x가 주어졌을 때, 각 자릿수의 합이 x가 되는 정수 중에서 가장 작은 수를 찾는 문제다. 이때 각 자릿수는 서로 달라야 한다. 예를 들어 x = 15일 때는 69가 정답이다. 이 문제의 해결 아이디어는 간단하다. 자릿수의 값을 최대한 크게 설정하면 값이 작아진다는 점을 이용하면 된다. 따라서 9부터 1까지 확인하면서 빼면 된다.

 

  참고로 45 = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9이므로, 45보다 큰 수는 정답이 존재하지 않는다.

 

for _ in range(int(input())):
    x = int(input())
    # 45보다 큰 수는 정답이 없음
    if x >= 46:
        print("-1")
        continue
    result = []
    # 9부터 1까지의 수를 확인하며
    for i in range(9, 0, -1):
        if x >= i:
            result.append(i)
            x -= i
    result.sort()
    print(''.join([str(i) for i in result]))

 

D번 문제: codeforces.com/contest/1462/problem/D

 

  N개의 정수가 있다. 그리고 한 번의 연산을 통해 인접한 두 수끼리 합쳐질 수 있다고 한다. 결과적으로 모든 수가 같아지기까지의 최소 연산 횟수를 구하는 문제다. 예를 들어 [1, 2, 2, 1]이 있다고 하자. 이때 [1, 2, 2, 1] → [3, 2, 1] → [3, 3]으로 단 두 번의 연산이면 된다.

 

  이 문제는 알고 보니 정수론(number theory)이었던 문제다. 모든 수의 합을 summary라고 하자. 1부터 N 사이의 값 중에서 summary를 나누어 떨어뜨리는 것이 가능한 수들이 후보군이다. 예를 들어 summary = 12이고, N = 6이라고 해보자. 그러면 남아있는 수의 개수로는 1, 2, 3, 4, 6이 가능하다. 예를 들어 2의 경우에는 [6, 6]을 남기면 되는 것이다.

 

for _ in range(int(input())):
    n = int(input())
    arr = list(map(int, input().split()))
    
    # 후보군(candidate) 찾기
    summary = sum(arr)
    candidates = []
    for i in range(n, 0, -1):
        if summary % i == 0:
            candidates.append(i)
    
    for candidate in candidates:
        target = summary // candidate
        # 모든 수가 target이 되도록 합칠 수 있는지 체크
        check = True
        value = 0
        for x in arr:
            value += x
            if value == target:
                value = 0
            # 합쳤을 때 target보다 크다면, 불가능한 케이스
            elif value > target:
                check = False
                break
        if check:
            print(n - candidate)
            break
728x90
반응형

728x90
반응형

  고등학교 생활기록부는 나이스(NEIS) 대국민서비스 사이트에 방문하여 발급받으실 수 있습니다. 

 

  ▶ 나이스(NEIS)www.neis.go.kr/

 

  나이스 대국민서비스 사이트에 방문한 이후에는 [홈에듀 민원서비스] 링크로 접속합니다.

 

 

  이후에 자신의 교육청을 선택합니다. 저는 경기도 소재인 고등학교에 다녔기 때문에 [경기도 교육청] 버튼을 클릭하였습니다.

 

 

  이후에 [학교생활기록부] 링크를 클릭하여 생활기록부를 발급할 수 있습니다.

 

 

  여기에서 성명 및 주민등록번호를 입력한 뒤에 [인증서 로그인] 버튼을 눌러 공인인증서로 로그인할 수 있습니다.

 

 

  이후에 다음과 같이 [찾기] 버튼을 클릭하여 자신의 학교를 검색하고 [확인] 버튼을 누릅니다.

 

 

  이어서 [발급] 버튼을 눌러 발급받을 수 있습니다.

 

 

  다음과 같이 [저장] 버튼을 눌러 생활기록부를 다운로드받을 수 있습니다.

 

 

  참고로 문서에는 비밀번호가 걸려 있는데, 비밀번호는 자신의 생년월일 6자리입니다. 필자는 Foxit과 같은 PDF 파일 수정 프로그램을 사용하여 담임 선생님의 성명이나 주소 등은 지웠습니다.

 

728x90
반응형

728x90
반응형

  하나의 프로그램의 취약점을 찾는 방법에는 다양한 기법이 있다. 기본적으로 프로그램은 입력(input)을 받아서 출력(output)을 내보내는 방식으로 동직하는데, 퍼징(fuzzing)이란 자동적으로 입력을 생성하여 반복적으로 프로그램에 넣어보는 것이다. 기본적으로 퍼저(fuzzer)는 입력을 만들어 내는데, 입력을 반복적으로 변형(mutating)하며 프로그램에 넣어보는 소프트웨어를 의미한다. 실질적인 측면에서 퍼징은 크래시(crash)를 만들기 위한 도구로 쓰이는 경우가 많다.

 

  퍼징을 더욱 더 엄밀하게 정의하면 다음과 같다.

 

  "Fuzzing refers to a process of repeatedly running a program with generated inputs to test if a program violates a correctness policy."

 

  카이스트(KAIST) 차상길 교수님의 자료에서는 다음과 같은 그림이 있다.

 

 

  퍼저의 종류는 크게 세 가지로 구분할 수 있다.

 

1. Black-box Fuzzing: 프로그램의 내부적를 알지 못하고, 입력에 따른 출력만 확인이 가능한 상태에서 퍼징을 하는 것이다.

 

2. White-box Fuzzing: 프로그램의 내부를 알기 때문에, 프로그램 내부의 모든 possible path를 검사할 수 있도록 조건에 맞는 입력을 넣는 방식으로 퍼징을 하는 것이다. 그래서 symbolic execution을 같이 하면서 입력값을 mutating하여 퍼징을 진행할 수 있다.

 

3. Grey-box Fuzzing: 프로그램 내부의 일부(some information)를 아는 상황에서 퍼징을 하는 것을 의미한다.

 

  굉장히 유명한 퍼저(fuzzer)로는 AFL이 있다. AFL은 가장 대표적인 Grey-box 방식의 fuzzer으로, 아직까지도 state-of-the-art인 baseline으로 제안되고 있다. 이러한 AFL로부터 매우 많은 fuzzer들이 영향을 받아 제안되었다.

728x90
반응형

728x90
반응형

  블록체인(blockchain) 분야에는 다양한 보안 이슈가 존재한다.

 

1. INFRASTRUCTURE ATTACK

 

  이 분야에서 가장 유명한 공격은 51% 공격(attack)이다. 이는 네트워크에서의 컴퓨팅 파워의 50% 이상을 차지하는 집단이 있다면, 전체 네트워크를 컨트롤할 수 있다는 것을 의미한다. 또한 가상화폐의 trade를 막기 위한 DDoS 공격 유형도 사용될 수 있다. 그리고 시빌(Sybil) 공격은 여러 개의 virtual identity를 만드는 유형을 의미한다. 예를 들어 비트코인의 경우 다수의 지갑을 만들어 실제로는 혼자이지만, 다수의 사람인 척 흉내를 낼 수 있다. 이러한 공격이 이클립스(eclipse) 공격으로 연결될 수 있는데, 특정한 노드와 연결된 노드들을 전부 attack node로 채워버려 하나의 노드를 고립된(isolated) 상태로 만들 수 있다.

 

  또한 mining pool을 공격(attack)하는 유형도 존재한다. 대표적으로 FC 2014에서 발표된 Selfish Mining이 있다. 채굴(mining) 자체는 경쟁적으로 이루어지며, 자신이 속한 체인(chain)의 길이가 가장 길어야 실질적인 이득을 볼 수 있을 것이다. Selfish Mining의 기본적인 아이디어는 nonce 값을 찾은 뒤에 바로 공표하지 않고, 그다음 블록을 미리 만들고 있는 것이다. 나중에 honest miner가 블록을 발표했을 때, 공격자가 한꺼번에 2~3개의 블록을 공표하여 자신의 체인이 가장 길어지도록 한다. 즉, honest miner의 computation power를 wasted 하도록 만드는 것이다.

 

2. APPLICATION ATTACK

 

  먼저 이중 지불(double spending) 공격이 있다. 말 그대로 동일한 돈을 여러 노드에 송금하는 공격이다. 내가 1 BTC를 가지고 있는 상황에서, A와 B에게 모두 1 BTC를 보내는 공격 유형이다. 이중 지불을 막기 위한 기본적인 방어 기법은 해당 transaction 이후에 최소한 6개의 연달아 생성된 블록(block)이 되었을 때 인정하도록 하면 된다.

 

  또한 스마트 컨트랙트(smart contract) 취약점을 공격하는 유형도 존재한다. 실제로 DAO 토큰의 사례가 자주 언급되는데, 스마트 컨트랙트를 작성할 때의 실수로 문제가 발생한 사례이다. 나아가 자동화 도구를 개발하여 이더리움의 스마트 컨트랙트 취약점을 찾도록 하는 연구도 많이 진행되고 있다. 대표적인 문제점인 reentrancy, unchecked send와 같은 다양한 취약점이 존재하는지 개별 스마트 컨트랙트에 대하여 검사하도록 할 수 있다. 대표적인 메서드가 ZEUS이다.

728x90
반응형

728x90
반응형

  기본적으로 다양한 데이터가 있는 DB에 대하여 쿼리(query)를 날려서, 결과를 얻을 수 있다. 공격자는 적당한 쿼리를 날려서 특정한 인물의 데이터를 특정할 수 있다. 이는 개인 정보(Privacy)를 알아내는 공격으로 볼 수 있다.

 

  예를 들어 특정한 마을의 의료 정보 DB가 있을 때, DB 상으로 당뇨에 걸린 사람 중에서 나이가 75살인 여성이 있다고 해보자. 하지만 이때 해당 마을에 70살 이상의 여성이 1명뿐이라면? 우리는 의료 정보 DB로부터 개인을 특정할 수 있고, 이로 인해 개인 정보가 침해될 수 있다.

 

  다른 예시로 학교 DB에 포함된 데이터에서의 평균 나이가 25살, 대부분의 전공이 컴퓨터 공학이라고 해보자. 이때 특정한 사람은 평균 나이의 2배에 해당하는 나이를 가지며, 대부분의 전공과 같은 전공을 가지며, 고급 아파트에 살고 있다는 정보를 알게 되었다고 해보자. 그러면 우리는 학교에서 컴퓨터 전공인 50살을 특정하여, 그 사람이 고급 아파트에 살고 있다는 사실을 알게 된다. 실제로 학교에서 50살인 사람의 수가 매우 희박하다고 하면, 우리는 어떤 사람을 특정할 수 있게 된다. 즉, 개인 정보 보호가 깨지게 된다.

 

  이러한 문제를 어떻게 해결할 수 있을까? 바로 Differential Privacy를 사용하면 된다. DP의 메인 아이디어는 간단하다. DB의 보안성이 떨어지는데, 그렇다고 암호화를 통해 해결할 수 있는 문제도 아니므로, 그냥 노이즈를 섞어버리는 것이다. 실제로 ACM CCS 2014에서 발표된 논문에 의하면 구글도 이러한 DP를 적용하여 개인정보 보호 문제를 해결하고 있다.

 

  아래 공식을 확인하자. 여기에서 A가 1에 가깝다는 말은 i라는 데이터를 넣었을 때나 넣지 않았을 때나 구분이 잘 안 된다는 말이다. 다만 A가 완전히 1의 값을 가지게 되면 한 명의 정보는 전체 DB에 아무런 영향을 미치지 못하므로, 사실상 효용성(utility) 자체가 없다는 말이 된다. 반면에 A가 1보다 너무 커지면 한 명의 정보가 DB에서 빠지면 곧바로 티가 나기 때문에 개인 정보 침해 문제가 발생한다.

 

 

  그렇다면 A라는 값을 어떻게 설정해야 적당할까? 값이 너무 작으면 DB의 효용이 떨어지고, 값이 너무 크면 개인 정보가 유출될 수 있다. 그래서 통계적으로 적당한 값을 설정하면 되는 것이다. 그래서 결과를 내보낼 때 노이즈(noise)를 섞어서 내보내면 된다. 일반적으로 라플라스 노이즈(Laplacian noise)를 사용한다. 쿼리(query)에 대한 응답을 보낼 때마다 매번 새로운 노이즈를 섞어 보내면 된다. 마찬가지로 노이즈가 많이 섞이면 DB의 효용성을 떨어뜨리고, 노이즈가 적게 섞이면 개인 정보가 유출될 수 있는 것이다.

 

  또한 global sensitivity라는 용어를 이해할 필요가 있다. D1과 D2는 오직 한 사람(one person) 만큼의 차이가 있는 DB들을 의미한다. 이때 global sensitivity란 F(D1)와 F(D2)의 거리를 나타내기 위한 식을 의미한다.

 

 

  관련한 내용으로 Local Differential Privacy라는 분야도 존재한다. 이때는 각각의 사람(person)이 DB Service Provider를 믿을 수 없을 때 사용할 수 있는 개념이다. 예를 들어 "Have you ever used illegal drugs?"라는 질문에 대하여, 내가 응답한 내용이 DB에 담긴다고 하보자. 이때 단순히 진실만을 말하지는 말고, 내가 DB에 데이터를 넣기 전에 노이즈(noise)를 섞을 수 있다.

 

  예를 들어 응답하기 전에 동전을 던져서 앞면이 나왔을 때는 그냥 랜덤하게 Yes/No라고 답하고, 뒷면이 나왔을 때는 진실한 답변을 할 수 있다. 나중에 추적을 당했을 때를 고려하여, 이렇게 DB에 넣기 전에 로컬(local)에서 노이즈를 섞자는 아이디어를 합법적 부인이라고 표현한다. 쉽게 말하면 여기에서는 DB에 데이터 삽입할 때 노이즈가 섞인 데이터를 넣는 작업으로 볼 수 있다.

 

 

  마찬가지로 입실론(epsilon) 값을 설정하여 privacy-utility의 trade-off를 결정할 수 있다. 입실론 값이 작으면 두 분포를 구분할 수 없으므로 더욱 privacy하고, 입실론 값이 크면 두 분포를 쉽게 구분할 수 있으므로 덜 privacy 하다고 이해하면 된다.

 

 

  대표적으로 Google RAPPOR (CCS 2014)와 같은 논문이 이러한 아이디어를 이용한 방법을 제안하고 있다.

728x90
반응형

728x90
반응형

  SD 카드에 Ubuntu 16.04 Server 설치용 이미지를 구워보자. 설치용 이미지는 다음의 경로에서 받을 수 있다.

 

  ▶ Ubuntu 16.04 Releases: releases.ubuntu.com/16.04/

 

  참고로 설치용 이미지 파일의 용량은 1GB도 안 되는 작은 크기를 가지고 있다. 따라서 짧은 시간에 다운로드가 가능하며, 곧바로 사용할 수 있다.

 

 

  리눅스(Linux) 터미널 환경에서는 다음과 같이 wget 명령을 이용하여 다운로드받을 수 있다.

 

mkdir ubuntu_images
cd ubuntu_images/
wget https://releases.ubuntu.com/16.04/ubuntu-16.04.7-server-amd64.iso

 

 

  이후에 SD 카드를 컴퓨터에 연결한다. fdisk -l 커맨드를 이용하여 다음과 같이 SD 카드의 블록 장치를 확인할 수 있다. 필자의 경우 /dev/sde이다.

 

 

  따라서 dd 명령어를 사용하여 플래시를 진행하면 된다. 참고로 sync 명령어는 데이터 동기화를 수행하여 유실되는 데이터가 없도록 한다.

 

sudo dd if=ubuntu-16.04.7-server-amd64.iso of=/dev/sde
sync

 

  결과적으로 다음과 같이 ISO 파일을 플래시 하는 작업이 완료된다.

 

 

  이제 SD 카드에 Ubuntu 16.04 설치용 이미지가 플래시 된 것이다.

 

  최종적으로 이 SD 카드를 컴퓨터에 꽂고 부팅하여, Ubuntu 16.04 서버를 원하는 저장장치에 설치하면 된다. (당연히 실제로 OS가 설치될 저장 장치는 따로 있어야 한다.)

728x90
반응형

728x90
반응형

  Htop은 리눅스에서 프로세스를 모니터링(monitoring)할 때 사용하는 유틸리티입니다. 쉽게 말하면 윈도우(Windows) OS에서의 작업관리자와 유사하다고 말할 수 있습니다. 설치 방법은 간단합니다. 다음의 명령어를 이용하면 됩니다.

 

 apt-get install htop

 

 

  이후에 바로 htop 명령어를 입력하여 모니터링 화면을 확인할 수 있습니다.

 

 

  이때 특정 프로세스를 종료하고 싶다면 스페이스 바(Space Bar)를 눌러 원하는 프로세스들을 선택한 뒤에 F9을 눌러 종료하면 됩니다. 또한 F4를 누르면 문자열을 입력하여 검색어 필터링(filtering)을 수행할 수 있습니다.

728x90
반응형

728x90
반응형

  리눅스 기반의 컴퓨터를 사용할 때, 가끔 로그(log) 때문에 너무 많은 용량이 소비되는 경우가 있다. 커널 개발을 할 때 커널 로그를 무분별하게 찍도록 하거나 웹 서버를 운영할 때 주기적으로 커스텀 로그 정보를 남기도록 하는 경우가 대표적인 사례다.

 

 

  실제로 df 명령어를 이용해 용량을 확인해 보면 뜬금없이 어느 순간에 /dev/root가 가득 차버리곤 한다. 이럴 때는 du 명령어를 이용해 도대체 어떤 폴더에서 이렇게 많은 용량을 차지하는 것인지 알아낼 필요가 있다. 

 

sudo du / -h --max-depth=1

 

  확인 결과 필자는 다음과 같이 /var 폴더에서 55G를 사용하고 있다는 것을 알 수 있었다. /var 폴더에는 로그(log) 정보뿐만 아니라 캐시 관련 데이터, 프로세스 관련 데이터도 포함한다.

 

 

  결과적으로 다음과 같이 /var/log에 존재하는 몇몇 로그가 비정상적으로 큰 용량을 가지는 것을 알 수 있었다.

 

 

  필자는 개인적으로 개발 목적으로 커널 로그를 자주 찍도록 하였는데, 그것이 원인인 것 같다. 이럴 때는 불필요한 로그(log) 파일을 제거하면 해결된다. 필자의 경우에는 커널 로그 전체를 지우도록 했다.

 

sudo rm kern.log
sudo rm messages
sudo rm syslog

 

 

  이어서 재부팅을 진행하면 다음과 같이 용량이 정상적으로 확보된다.

 

728x90
반응형

728x90
반응형

※ 이미지를 보관(비공개) 설정하기 ※

 

  인스타그램(Instagram)에 올린 게시물을 비공개 설정하는 방법은 간단합니다. 바로 [보관] 설정을 하면 됩니다. 다음과 같이 자신이 올렸던 사진에 대하여 설정 버튼을 눌러 확인합니다.

 

 

  이후에 [보관] 버튼을 누르면 됩니다.

 

 

 

  그러면 다른 사용자에게는 이미지가 보이지 않게 됩니다.

 

※ 보관(비공개) 처리된 이미지를 다시 공개 설정하기 ※

 

  비공개 처리했던 이미지를 다시 보이도록 하기 위해 보관된 이미지를 확인합시다.

 

 

  이후에 자기가 비공개 처리했던 이미지의 설정 정보를 다시 확인합니다.

 

 

  여기에서 [프로필에 표시] 버튼을 누르면 됩니다.

 

 

  그러면 다시 프로필 화면에 이미지가 공개적으로 보이게 됩니다.

728x90
반응형

728x90
반응형

  우리는 다양한 상황에서 주민등록등본이 필요합니다. 참고로 주민등록등본(초본)을 인터넷으로 발급받을 때는 무료입니다. 또한 인터넷으로는 즉시 발급받아 출력할 수 있기 때문에 굉장히 편리합니다.

 

  ▶ 링크주민등록등본 인터넷 신청

 

주민등록표등본(초본)교부 | 민원안내 및 신청 | 민원24 | 정부24

주민등록표등본(초본)교부 주민등록표등본(초본)교부 정보 신청방법, 처리기간, 수수료, 신청서, 구비서류, 신청자격 정보 제공 신청방법 인터넷, 방문 처리기간 즉시(근무시간 내 3시간) 수수료

www.gov.kr

 

  링크에 방문한 뒤에 [신청하기] 버튼을 누르면 됩니다.

 

 

  참고로 공인인증서만 있으면 [비회원 신청하기] 버튼을 눌러 확인할 수 있습니다.

 

 

  다음과 같이 이름, 주민등록번호를 입력하여 [확인] 버튼을 누릅니다.

 

 

  이제 구체적으로 자신이 발급받고자 하는 문서가 등본인지 초본인지 구분하여 선택할 수 있습니다.

 

 

 

  이후에 [온라인발급]을 선택하여 [민원신청하기]를 누르시면 됩니다.

 

 

  이후에 [문서출력] 버튼을 누르면 주민등록등본을 확인할 수 있습니다.

 

728x90
반응형