반응형

1. Renaming

1.1 ClassRename

class renaming은 class의 이름를 "Base64Coder"처럼 식별할 수 있는 문자대신, "pabd63bb"와 같이 무슨 의미인지 알 수 없게 바꾸어 준다. 따라서 역공학으로 해당 파일을 보더라도 무슨 역할을 하는 지 알아차리기 힘들어 역공학을 방해한다. [1]

 

python3 -m obfuscapk.cli -o ClassRename ../../sample_apps/app_1.apk
apktool b app_1/ -o app_1_ClassRenamed.apk

 

ClassRename 난독화를 하고 해당 앱을 리패키징하여 jadx로 비교하였다.

class의 이름이 Base64Coder에서 pabd63bb로 바뀐 것을 알 수 있다.

 

기존앱을 virustotal로 검사하면 30개의 백신에서 탐지가 된다.

하지만 ClassRename을 하고 난 뒤에는 20개의 백신에만 탐지가 된다.

1.2. MethodRename

Method Rename method의 이름을 식별하기 힘들게 변경하는 것이다. 따라서 역공학시 해당 메소드가 어떠한 역할을 하는지 명시적으로 알기 어려워져 분석하기 어려워진다.[1]

python3 -m obfuscapk.cli -o MethodRename ../../sample_apps/app_2.apk

 

리패키징을 해준뒤 jadx로 기존앱과 비교하면

c.ca/a 자바 클래스 파일의 메소드 f m8fa14cdd로 변경됨을 알 수 있다.

 

백신탐지 비교 시

(왼쪽 : 기존 앱, 오른쪽 : MethodRename 적용)

Method Rename을 적용한 경우에 백신 탐지가 덜 되는 것을 알 수 있다.

 

2. Encryption

2.1. ConstStringEncryption

소스 코드의 문자열 상수를 암호화한뒤 decrypString함수를 통하여 복호화하여 원래의 문자열 상수를 얻도록 한다. 따라서 역공학 분석시, 암호화된 문자열이 어떠한 것을 가리키는 지 인식하기 힘들어 역공학을 어렵게한다.[2]

python3 -m obfuscapk.cli -o ConstStringEncryption ../../sample_apps/app_5.apk

app_5의 connector파일을 보면 "http://" String(왼쪽사진)이 암호화(오른쪽사진)되어 있는 것을 알 수 있다.

(jadx 사용)

\

 

백신탐지 비교시

왼쪽 : 기존앱, 오른쪽 : ConstStringEncryption적용)

ConstStringEncryption을 적용한 경우에 백신 탐지가 덜 되는 것을 알 수 있다.

 

2.2. AssetEncryption

python3 -m obfuscapk.cli -o AssetEncryption ../../sample_apps/app_2.apk

 

Asset 디렉토리에 있는 리소스를 복제, 수정으로부터 보호한다.[4]

 

smali/android/annotation 안에 DecryptAsset.smali가 생긴 것을 알 수 있다.

[그림] DecryptAsset.smali

 

또한 com.decryptassetmanager.DecryptAsset 파일이 생겼음을 알 수 있다.

[그림] com.decryptassetmanager.DecryptAsset

 

Assets에 접근 시 복호화하여 파일을 불러온다.

 

백신탐지 비교 시

(왼쪽 : 기존 앱, 오른쪽 : AssetEncryption 적용)

AssetEncryption을 적용한 경우에 백신 탐지가 덜 되는 것을 알 수 있다.

 

3. Code

 

3.1. Goto

java에는 없는 goto bytecode를 추가함으로써, control-flow를 수정하고 control-flow를 이해하기 어렵게 한다. [3]

python3 -m obfuscapk.cli -o Goto ../../sample_apps/app_2.apk

[그림]"smali/android/view/a.smali" 비교

 

처음에 메소드의 끝을 가리키는 goto가 있고, 메소드 끝에 메소드의 처음을 가리키는 goto가 추가되어 bytecode 흐름이 달라졌다.

 

 

백신탐지 비교시

(왼쪽 : 기존앱, 오른쪽 : Goto옵션 적용)

Goto 옵션을 적용한 경우에 백신 탐지가 덜 되는 것을 알 수 있다.

 

3.2. Reorder

Reorder는 역공학하여 분석하기 어렵도록, 메소드의 명령어 흐름을 복잡하게 한다. 왼쪽의 그림이 Reorder된 app_3의 BandManager.smali이다. [2] 오른쪽의 기존과 method와 다르게 추가된 내용도 생기고 흐름도 goto문이 생기는 등 복잡하게 바뀐 것을 알 수 있다.

python3 -m obfuscapk.cli -o Reorder ../../sample_apps/app_3.apk

[그림]"smali/com/BandManager.smali"비교

 

 

백신탐지 비교시

(왼쪽 : 기존앱, 오른쪽 : Reoreder 적용)

Reoreder 옵션을 적용한 경우에 백신 탐지가 덜 되는 것을 알 수 있다.

 

3.3. Nop

Nop 명령어를 추가하여 bytecode 흐름을 수정한다. 따라서 control flow를 이해하기 어렵게 한다. [3]

python3 -m obfuscapk.cli -o Nop ../../sample_apps/app_2.apk

왼쪽의 Nop 옵션이 적용된 app_2/smali/c/ca/a.smali 파일을 보면 오른쪽의 기존 파일과 다르게 nop 명령어들이 추가된 것을 알 수 있다.

[그림] "smali/c/ca/a.smali"비교

 

백신탐지 비교 시

(왼쪽 : 기존앱, 오른쪽 : nop 옵션 적용)

nop 옵션을 적용한 경우에 백신 탐지가 덜 되는 것을 알 수 있다.

 

 

 

 

 

 

3.4. ArithmeticBranch

ArithmetiBranch 옵션은 의미 없는 코드를 삽입하여 명령어 흐름을 복잡하게 만들다. 따라서 역공학시 분석을 하기 어렵게 한다. [2] 왼쪽의 ArithmeticBranch 옵션이 적용된 app_4/smali/com/example/eroplayer/MainActivity을 보면 오른쪽의 기존 파일과 다르게 junk code가 삽입된 것을 알 수 있다.

[그림] “smali/com/example/eroplayer/MainActivity.smali" 비교

 

백신 탐지 비교 시

 

ArithmetiBranch 옵션을 적용한 경우에 백신 탐지가 덜 되는 것을 알 수 있다.

 

 

 

 

 

일반적인 개발자의 입장에선, 안드로이드 난독화는 역공학을 어렵게하여, 개발자가 만든 소스코드, 파일 등을 보호할 수 있게 해주는 좋은 수단이다.

악성 앱 개발자의 입장에선, 안드로이드 난독화는 control-flow를 바꾸거나, 암호화, renaming등으로 백신이 악성코드를 탐지하게 어렵게 악용하는 수단이다. 

 

 

참고 논문

[1] 난독화에 강인한 안드로이드 앱 버스마킹 기법 김 동 진Š , 조 성 제° , 정 영 기* , 우 진 운**, 고 정 욱***, 양 수 미**** Android App Birthmarking Technique Resilient to Code Obfuscation Dongjin KimŠ , Seong-je Cho° , Youngki Chung* , Jinwoon Woo**, Jeonguk Ko***, Soo-mi Yang****

 

[2] 안드로이드 어플리케이션 역공학 보호기법 하 동 수*, 이 강 효*, 오 희 국*

 

[3] Android Code Protection via Obfuscation Techniques: Past, Present and Future Directions Parvez Faruki, Malaviya National Institute of Technology Jaipur, India Hossein Fereidooni, University of Padua, Italy Vijay Laxmi, Malaviya National Institute of Technology Jaipur, India Mauro Conti, University of Padua, Italy Manoj Gaur, Malaviya National Institute of Technology Jaipur, India

 

[4] APK에 적용된 난독화 기법 역난독화 방안 연구 및 자동화 분석 도구 구현* 이 세 영,† 박 진 형, 박 문 찬, 석 재 혁, 이 동 훈고려대학교 정보보호대학원

728x90
반응형

'공부 > 보안' 카테고리의 다른 글

cwe119 버퍼 오버플로우 방어  (0) 2021.06.02
Widthness bugs  (0) 2021.06.02
암호화 기본 - 2  (0) 2021.06.02
암호화 기본 - 1  (0) 2021.06.01
apk 난독화  (0) 2021.05.17
블로그 이미지

아상관없어

,
반응형

기존에는 멀티 스레드를 사용하지 않는 작업 하이퍼 스레딩이 필요하지 않음따라서 남는 레지스터를 활용하자는 생각을 .

 

Loop Splitting 사용하는 프로그램을 만들어, 병렬의 개수를 늘려가며 하이퍼 스레딩 사용 유무에 따라 비교를 해보았다.

#include<stdio.h>
#include<Windows.h>
#include<stdint.h> 
/*
vmware의 리눅스에서 하려고 하였다. 하지만 하이퍼 스레딩 유무에 따라 CPU정보 명령어( cat /proc/cpuinfo, grep -c processor /proc/cpuinfo, grep "physical id" /proc/cpuinfo | sort -u | wc -l, grep "cpu cores" /proc/cpuinfo | tail -1)를 사용하여 확인하였지만 차이가 없어 윈도우환경에서 하였다.
*/
//windows에는 gettimeofday함수가 없으므로 인터넷에서 참고하였다.
int gettimeofday(struct timeval* tp, int* tz)
{
 LARGE_INTEGER tickNow;
 static LARGE_INTEGER tickFrequency;
 static BOOL tickFrequencySet = FALSE;
 if (tickFrequencySet == FALSE) {
  QueryPerformanceFrequency(&tickFrequency);
  tickFrequencySet = TRUE;
 }
 QueryPerformanceCounter(&tickNow);
 tp->tv_sec = (long) (tickNow.QuadPart / tickFrequency.QuadPart);
 tp->tv_usec = (long) (((tickNow.QuadPart % tickFrequency.QuadPart) * 1000000L) / tickFrequency.QuadPart);
 
 return 0;
}

void main() {
	struct timeval startTime, endTime;

	double diffTime;

	int limit = 100000;
	int i;
    int loop = 1;
	int data[100000];
	int a;
	for (a = 0; a < limit; a++) {
		data[a] = 1;
	}
	
	int x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19;
	x0 = 1;
	x1 = 1;
	x2 = 1;
	x3 = 1;
	x4 = 1;
	x5 = 1;
	x6 = 1;
	x7 = 1;
	x8 = 1;
	x9 = 1;
	x10 = 1;
	x11 = 1;
	x12 = 1;
	x13 = 1;
	x14 = 1;
	x15 = 1;
	x16 = 1;
	x17 = 1;
	x18 = 1;
	x19 = 1;
    printf("loop %d,  %d loop splitting\n", limit, loop);
    gettimeofday(&startTime, NULL);
    printf("starttime %d.%d s\n",startTime.tv_sec, startTime.tv_usec);
	for (i = 0; i < limit; i += loop) {
		x0 = x0 * data[i];
		/*x1 = x1 * data[i + 1];
		x2 = x2 * data[i + 2];
		x3 = x3 * data[i + 3];
		x4 = x4 * data[i + 4];
		x5 = x5 * data[i + 5];
		x6 = x6 * data[i + 6];
		x7 = x7 * data[i + 7];
		x8 = x8 * data[i + 8];
		x9 = x9 * data[i + 9];
		x10 = x10 * data[i + 10];
		x11 = x11 * data[i + 11];
		x12 = x12 * data[i + 12];
		x13 = x13 * data[i + 13];
		x14 = x14 * data[i + 14];
		x15 = x15 * data[i + 15];
		x16 = x16 * data[i + 16];
		x17 = x17 * data[i + 17];
		x18 = x18 * data[i + 18];
		x19 = x19 * data[i + 19];*/
	}

	gettimeofday(&endTime, NULL);
    printf("endtime %d.%d s\n",endTime.tv_sec, endTime.tv_usec);
}

테스트를 해보기 하이퍼 스레딩 기능을 켰다.

 

다음은 하이퍼 스레딩이 켜진 상태에서 실행한 결과이다.

 

<병렬 1>

<병렬 2>

<병렬 4>

<병렬 5>

<병렬 8>

<병렬 10 >

<병렬 20>



그리고 나서 하이퍼 스레딩을 끄고 테스트를 해보았다.

 

 

<병렬 1>

<병렬 2>

<병렬 4>

<병렬 5>

<병렬 8>

 

<병렬 10 >

<병렬 20>

 

테스트 결과들을 표로 정리하면 다음과 같다.

 

startT endT 시간() 평균 시간
1 병렬      
158.286745 158.286334 0.000411 0.000529
159.294495 159.293966 0.000529  
159.941791 159.941145 0.000646  
2 병렬      
205.491576 205.491193 0.000383 0.000429
206.256555 206.256076 0.000479  
206.781915 206.781489 0.000426  
4 병렬      
233.779762 233.779216 0.000546 0.000466
234.638762 234.638302 0.00046  
235.315725 235.315334 0.000391  
5 병렬      
276.227503 276.227081 0.000422 0.001615
277.362467 277.361994 0.000473  
278.18864 278.18469 0.00395  
8 병렬      
305.11175 305.10701 0.00474 0.003192
306.78751 306.78311 0.0044  
306.816079 306.815644 0.000435  
10 병렬      
373.782009 373.781564 0.000445 0.000421
374.588579 374.588149 0.00043  
375.25087 375.250482 0.000388  
20 병렬      
411.261493 411.261106 0.000387 0.000412
412.976789 412.976307 0.000482  
413.531929 413.531562 0.000367  
HTon      

<하이퍼 스레딩 켰을 >

 

 

startT endT 시간() 평균시간
1 병렬      
1193.879285 1193.878775 0.00051 0.001763
1195.55735 1195.55297 0.00438  
1195.954497 1195.954098 0.000399  
2 병렬      
1250.718352 1250.718071 0.000281 0.000349
1251.968818 1251.968417 0.000401  
1252.790355 1252.789991 0.000364  
4 병렬      
1333.682861 1333.682653 0.000208 0.000284
1336.171769 1336.171549 0.00022  
1337.950726 1337.950303 0.000423  
5 병렬      
1449.503198 1449.502993 0.000205 0.000939
1452.7616 1452.75931 0.00229  
1452.823454 1452.823132 0.000322  
8 병렬      
1589.8527 1589.852293 0.000407 0.00044
1590.653918 1590.653423 0.000495  
1591.37499 1591.374572 0.000418  
10 병렬      
1652.622676 1652.622495 0.000181 0.001527
1653.424747 1653.424336 0.000411  
1654.68126 1654.67727 0.00399  
20 병렬      
1875.417252 1875.416802 0.00045 0.001983
1876.366084 1876.365556 0.000528  
1877.5143 1877.50933 0.00497  
HToff      

<하이퍼 스레딩을 껐을 >

 

하이퍼 스레딩을 켰을 경우와 껐을 경우의 컴퓨터 환경을 최대한 동일하게 하기 위해 네트워크를 차단하고 켜진 프로그램도 최대한 동일하게 유지하였다. (따라서, 환경이 동일한 환경이라고 가정하고 차이를 보았다.)

병렬개수별 시간을 여러 측정하여 평균치를 사용하였다. 병렬개수별 시간 차이는 다음과 같다

 

 

차이를 보기 쉽게 시간에 10^5만큼 곱하였다.

병렬 차이(HTon - HToff)
1 52.86490367
2 8.066666663
4 18.2
5 67.59999999
8 275.1666667
10 -110.6333333
20 -157.0666667

병렬의 개수를 많이 늘렸을 하이퍼 스레딩을 껐을 경우가 시간이 오래 걸리는 것으로 보아, 하이퍼 스레딩을 껐을 , 남은 Architectural state(레지스터) 활용하지 못하는 것으로 판단하였다.

 따라서 이러한 단일 프로세스만 수행해야하는 상황에서 어떻게 하면 효율적으로 수행할 있을까 생각해보게 되었고, 결국 레지스터를 어떻게 하면 최대한 많이 넣고 많이 사용할 잇을까에 대해 생각해보게 되었다.

 

문제 인식 무어의 법칙을 근거로 다양한 기능 시도

1. 병렬적 작업을 하는 단일 프로세스만 수행할 , 하이퍼 스레딩기능을 끄고 하이퍼 스레딩을 위한 레지스터를 활용하면 많은 레지스터를 있지 않을까?

 


PROPOSAL

             <기존의 멀티코어 시스템>

 


예전 Pentium D processor 듀얼 코어와 달리 캐시와 버스 인터페이스를 cpu간에 공유하기 시작하면서 본격적으로 멀티코어 기술에 대한 관심이 많아졌고, 중에 Architectural State부분에서 아래와 같이 cpu내부에 스레드를 여러 두어 문맥 교환을 os 아닌 cpu에서 처리하도록 Hyper threading 기술이 있고 더욱 효율적인 Architectural state 가지로 제안을 하게 되었다

 

1.   기존의 cpu 번째 제안

 

1-1            기존의
 cpu 번째 제안

 

1- 2 제안

           

728x90
반응형

'공부 > 운영체제&시스템프로그래밍' 카테고리의 다른 글

myshell  (0) 2020.07.16
mycp  (0) 2020.07.16
EXT2 file system 실습 (6번 디렉토리안의 82번 파일 찾기)  (0) 2020.07.16
블로그 이미지

아상관없어

,
반응형

병행 수행

- 여러 사용자가 DB를 동시 공유할 수 있게 여러개의 트랜잭션을 동시에 수행하는 것

- 여러 트랜잭션이 차례로 번갈아 수행되는 인터리빙 방식으로 진행

(단위 시간에 많은 트랜잭션을 처리하기 위해)

(트랜잭션 제각각 처리 시간이 다르므로, 처리시간이 긴 연산 수행 동안 다른 연산 수행)

 

병행제어

- 병행 수행시, 같은 데이터에 접근하여 연산을 실행해도 문제가 발생하지 않고 정확한 수행 결과를 얻을 수 있게 트랜잭션 수행을 제어하는 것.

- 정확한 수행 결과가 아닌 경우가 발생하지 않게 병행제어를 잘 해야한다.

 

 

병행 수행 시 발생할 수 있는 문제점

1. 갱신 분실

- 하나의 트랜잭션이 수행한 데이터변경 연산의 결과를 다른 트랜잭션이 덮어서 변경연산 무효화됨

- 여러 트랜잭션이 동시에 수행되더라도 순차적으로 수행한것과 같은 결과값을 얻을 수 있어야된다.

=> T1에 대해 갱신 분실이 발생한다.

 

트랜잭션을 순차적으로 수행하면 해결된다.

 

 

2. 모순성

- 하나의 트랜잭션이 여러 개 데이터 변경 연산을 실행할때, 일관성 없는 상태의 데이터베이스에서 데이터를 가져와 연산 => 모순된 결과가 발생

T1이 X, Y를 다른 상태의 데이터베이스에서 가져와 

트랜잭션 T1의 결과가 X= 4000, Y = 4000이 아닌 X=2000, Y=2500의 잘못된 결과가 나온다.

T1이 완료된후 T2가 실행되면 모순성 문제가 발생하지 않는다.

 

3. 연쇄복귀

- 트랜잭션이 완료되기전, 장애가 발생하여 rollback연산을 수행 => 장애 발생 전에 트랜잭션이 변경한 데이터를 가져가 변경연산을 실행한 다른 트랜잭션도 연쇄적으로 rollback연산을 해야함

==> 장애로 잘못된 결과가 나오고 그 잘못된 결과를 가져가 다른 트랜잭션이 연산을 수행했으므로

(T1 -> 결과(문제발생) -> T2 -> 결과(문제발생!, 잘못된 결과로 연산하였으므로)

 

T2는 T1이 변경한 X를 가져가 연산을 수행한다.

T1 트랜잭션 완료 전 장애가 발생한다.

T1을 rollback해야하지만, T2는 연산이 이미 끝나 rollback이 불가하다.

순차적으로 수행 (T1완료후  -> T2수행)하면 연쇄 복귀 문제가 발생하지 않는다.

 

 

트랜잭션 스케줄

1. 직렬 스케줄 => 인터리빙이 아닌, 각 트랜잭션별로 연산을 순차적으로 실행 => 시간이 길어짐

2. 비직렬 스케줄 => 인터리빙 방식으로 트랜잭션 병행해서 수행 => 병행성 문제 발생

3. 직렬 가능 스케줄 => 직렬스케줄처럼 정확한 결과를 생성하는 비직렬 스케줄 => 시간을 줄이고 병행성 문제 해결

 

1. 직렬 스케줄

- 다른 트랜잭션의 방해를 받지 않고 독립적으로 수행 => 항상 모순 없는 결과

- 병행 수행이 아님 => 시간이 오래걸림

- 다양한 직렬 스케줄을 만들 수 있음

 

T1 -> T2

T2 -> T1

 

2. 비직렬 스케줄

- 트랜잭션이 번갈아 연산 실행 => 하나의 트랜잭션 완료전 다른 트랜잭션 연산 실행가능

- 갱신분실, 모순성, 연쇄복귀 문제 발생하여 결과의 정확성 보장 X

- 다양한 비직렬 스케줄 생성가능 (그중엔 잘못된 결과를 생성하기도함)

 

비직렬 스케줄이지만 병행 수행에 성공하여 정확한 트랜잭션 수행 결과를 생성한다. => 직렬가능 스케줄

 

병생 수행에 실패하여 잘못된 결과를 생성한다.

 

 

 

 

3. 직렬 가능 스케줄

- 비직렬 스케줄 중에서 수행 결과가 동일한 직렬 스케줄이 있는 것.

- 인터리빙 방식으로 병행수행하면서 정확한 결과 얻음

- 직렬 가능 스케줄인지 판단한는것은 복잡한 작업

- 따라서 직렬가능성을 보장하는 병행제어 기법 사용 

 

 

 

병행 제어 기법

- 병행 수행하면서 직렬 가능성도 보장

- 모든 트랜잭션이 준수하면 직렬가능성이 보장되는 rule 정의

- lock 기법이 있음

 

lock기법 - 상호배제

- 병행 수행되는 트랜잭션들이 같은 데이터에 동시에 접근하지 못하게 lock/unlock연산

lock - 트랜잭션이 데이터에 대한 독점권 요청

unlock - 트랜잭션이 데이터에 대한 독점권 반환

 

- 데이터에 접근하기 전 lock하여 독점권을 획득 (read/write 전 lock)

- 다른 트랜잭션에 의해 이미 lock이 걸린 데이터는 lock 불가& 실행 불가

- 연산 수행 끝나면 unlock

 

lock 단위가 커지면 병행성은 낮아지지만 제어가 쉬워지고

단위가 작아지면 제어가 어렵지만 병행성은 높아진다.

 

lock 효율 향상 => 동시성이 높아짐

공용 lock => read만 가능

- read연산 수행가능 ,write 불가 

- 다른 트랜잭션도 동시에 공용 lock 가능

- 데이터 사용권을 여러 트랜잭션이 함께 가지는 것 가능

 

전용 lock => write하기 위해

- read/write 둘다 가능

- 다른 트랜잭션은 어떠한 lock 연산도 실행 불가

- 데이터에 대한 독점권 가짐

 

T1이 X에 대해 빨리 unlock을 해버려 T2가 일관성 없는 데이터에 접근하여 잘못된 결과가 나온다.

(T1이 끝날때까지 lock을 해야한다.)

 

2단계 lock rule = 축소, 확장

- 위와 같은 기본 lock rule의 문제 해결

- 직렬 가능성 보장 위해 lock/unlock연산 수행 시점에대한 새로운 rule 추가

- 트랜 잭션이 처음수행되면 확장단계 => lock만 가능 (lock을 검)

- unlock 연산을 실행하면, 축소단계 => unlock만 가능

- 트랜잭션은 첫번째 unlock 연산전, 필요한 lock 연산을 실행해야한다.

 

하지만 이러한 방법도 

T1 -> X (lock)  ====> Y가 unlock 되길 기다림

T2 -> Y (lock) =====> X가 unlock 되길 기다림

과 같은 경우 데드락이 발생 할 수 있다.

따라서 교착 상태가 발생되지 않게 예방하거나 빨리 탐지하여 조치를 해야한다.

 

 

 

 

 

 

728x90
반응형

'공부 > 데이터베이스' 카테고리의 다른 글

회복과 병행제어 - 회복  (0) 2021.06.03
관계 대수  (0) 2021.06.03
파이썬 연동 예제  (0) 2021.06.02
index  (0) 2021.06.02
데이터 베이스 보안  (0) 2021.06.02
블로그 이미지

아상관없어

,
반응형

병행제어 : 수많은 사람들이 동시에 데이터베이스를 이용하는데 문제가 발생하지 않게 제어해주어야한다.

 

트랜젝션

- 하나의 작업을 수행하는데 필요한 데이터베이스 연산을 모은것.

- 작업 수행에 필요한 SQL문 집합

- 논리적 작업단위

- 장애발생시, 복구나 병행제어 작업을 위한 중요한 단위로 사용

- DB의 무결성과 일관성을 보장하기 위해서 작업 수행에 필요한 연산들을 하나의 트랜잭션으로 제대로 정의하고 관리해야함.

ex 1)

1번 작업과 2번 작업이 하나의 트랜잭션이다.

처리 순서는 중요하지 않지만, 두개의 update 명령이 정상적으로 실행되어야한다.

 

ex 2)

insert와 update 모두 정상적으로 실행되어야 상품주문 트랜잭션이 성공적으로 수행된다.

 

 

트랜잭션 특성

1. 원자성 => 회복기능

- all or nothing

- 트랜잭션의 연산들이 모두 정상적으로 실행 or 하나도 실행 X

- 트랜잭션 수행중 장애가 발생되면? => 실행한 연산을 모두 취소하고 DB를 트랜잭션 작업 전으로 복구

- 따라서 원자성 보장을 위해 회복 기능이 필요하다.

ex)

DB = A: 10000, B : 0

-계좌이체 트랜잭션-

(1) A계좌에서 5000원 인출

(2) B계좌에 5000원 입금

DB = A: 5000, B: 5000

 

1,2번 작업 중 장애가 발생하면 실행한 작업을 취소하고

DB = A: 10000, B : 0

상태로 되돌린다.

 

2. 일관성 => 병행 제어

- 트랜잭션이 성공적으로 수행된 후에도 DB가 일관된 상태를 유지해야한다.

ex)

DB = A: 10000, B : 0  ==> 합계 10000

-계좌이체 트랜잭션-

(1) A계좌에서 5000원 인출

(2) B계좌에 5000원 입금

DB = A: 5000, B: 5000  ==> 합계 10000

 

 

 

3. 격리성 => 병행 제어

- 수행 중인 트랜잭션이 완료될때까지, 다른 트랜잭션이 중간 연산 결과에 접근 불가

- 다른 트랜잭션과 연결 X, 독립됨

- 여러 트랜잭션이 동시에 수행되더라도, 순서대로 하나씩 수행되는 것처럼 정확하고 일관된 결과를 얻게 제어해야함

- 트랜잭션 서로 간섭 X

 

DB = A: 10000, B : 0

-계좌이체 트랜잭션-

(1) A계좌에서 5000원 인출

(2) B계좌에 5000원 입금

DB = A: 5000, B: 5000

 

여기서 B계좌에 1000원을 입금하는 다른 트랜잭션이 동시에 수행되어 (1)작업 후 수행되면

계좌입금 트랜잭션은 

-계좌입금 트랜잭션-

DB = A: 5000, B : 0

(1) B 계좌에 1000원 입금

DB = A: 5000, B : 1000

이 되어 두 트랜잭션이 완료되면

DB = A: 5000, B: 5000

DB = A: 5000, B : 1000

B의 계좌 잔액이 일치하지 않게 된다.

 

이러한 문제가 발생한 원인은 두 트랜잭션이 간섭을 일으키기 때문이다. 

따라서 계좌이체 트랜잭션이 끝날때 까지 기다린후, 계좌 입금 트랜잭션을 수행하면 같은 정보를 update하는 충돌이 발생하지 않는다.

즉, 간섭(충돌)이 되는 작업은 기다리고 아니면 동시수행한다.

 

 

 

4. 지속성 => 회복기능

- 트랜잭션이 성공적으로 완료된 후, 데이터베이스에 반영한 수행결과는 영구적이여야 함.

- 트랜잭션을 성공했으면 결과는 어떤일이 일어나더라도 유지되야한다.

(만약 트랜잭션을 성공했는데 시스템 다운으로 데이터가 날라가 결과에 데이터가 없으면 안된다.)

- 지속성의 보장을 위해선 장애 발생시 회복기능이 필요하다. (다시 복구)

 

 

 

트랜 잭션의 주요연산

1. commit - 트랜잭션이 성공적으로 수행되었음을 선언 (작업 완료)

=> 트랜잭션의 수행 결과가 데이터베이스에 반영되고 일관된 상태를 지속적으로 유지

2. rollback - 트랜잭션을 수행하는데 실패했음 선언 (작업 취소)

=> 지금까지 실행한 연산 결과를 취소하고 트랜잭션 수행 전의 데이터베이스로 상태 되돌림

 

 

트랜 잭션 상태

활동(수행중) -> 실패 -> rollback -> 철회

                 -> 부분완료 -> commit -> 완료

                 -> 부분완료 -> 실패 -> rollback -> 철회

 

활동

- 트랜잭션 수행중

 

부분 완료

- 트랜잭션의 마지막 연산이 실행을 끝낸 직후

 

완료

- 트랜잭션이 성공적으로 완료되어 commit 연산 실행한 상태, 결과를 DB에 반영, DB가 새로운 일관된 상태가 되고 트랜잭션 종료

 

실패

- 장애가 발생하여 트랜잭션 수행 중단된 상태

 

철회

- 트랜잭션 수행실패로 rollback 연산 실행한 상태,

- 지금까지 실행한 트랜잭션 연산을 모두 취소 후 트랜잭션 수행 전으로 DB되돌리고 트랜잭션 종료

- 철회 상태로 종료된 트랜잭션은 다시 수행되거나 폐기됨(상황에 따라)

 

장애 

휘발성 저장장치(소멸성 ) : 장애가 발생하면 저장된 데이터 손실

비휘발성 저장장치(비소멸성) : 장애가 발생해도 저장된 데이터 손실X, 저장장치 자체에 이상이 발생하면 데이터 손실

안정 저장장치 : 비휘발성 저장장치 이용, 데이터 복사본 여러개, 어떤 장애가 발생되도 데이터 손실X, 데이터 영구적 저장

 

트랜잭션 수행을 위해 필요한 데이터 이동 연산

응용프로그램 <-(read) - 메인메모리 <-(input) - 디스크

응용프로그램 ->(write) - 메인메모리 - (output)-> 디스크

read/write에 비해 input, output은 느리다.

트랜잭션에 read/write, input/output 연산이 포함된다.

 * 메인 메모리 데이터 베이스 = 디스크에 있다가 실행 시점에 전부 메인메모리로 가져와 사용한다. (규모가 작고 빠른 R/W시 사용한다.) (주로 read인 경우 - select)

 

디스크와 메인메모리 간의 데이터 이동연산은 block단위로 수행된다.(한번 읽는 시간이 느리므로 block 단위로 읽어옴)

 

 

회복(복구)를 위해 데이터베이스 복사본을 만드는 방법 => 데이터 중복!

덤프(dump) = 데이터베이스 전체를 다른 저장장치에 주기적으로 복사

로그(log) = 데이터베이스에서 변경 연산이 실행될 때마다, 데이터를 변경하기 이전값이후값을 별도의 파일에 기록

ex)

5일마다 backup을 한다면, 원본과 복사본 간에 시간차가 생긴다.

DB -(5일 시간차)-> 백업DB 

따라서, log를 사용 =>  5일전 복사본에 log로 변한 것을 적용하면 현재 DB상태가 된다.

 

 

회복(복구)를 위한 기본 연산

redo(재실행) = 가장 최근에 저장한 DB복사본을 가져온 뒤, log를 이용해서 복사본이 생성된 후의 모든 변경 연산을 재실행하여 장애 발생전의 DB상태로 복구

undo(취소) = log를 이용하여 실행된 모든 변경 연산을 취소하여 DB를 원래 상태로 복구(변경중이었거나, 변경된 내용만 신뢰성을 잃은 경우)

* log : 데이터를 변경하기 이전값과 변경한 후의 값을 기록한 파일, 레코드 단위로 트랜잭션 수행과 함께 기록

 

 

 

DB 회복(복구) 기법

- 로그 회복기법(즉시 갱신, 지연갱신 회복기법)

- 검사 시점 회복기법

- 미디어 회복기법

 

1. 로그 회복 - 즉시갱신 회복기법

- 트랜잭션 수행 중 데이터 변경 연산 결과를 DB에 즉시 반영

- 장애 발생에 대비하기 위해, 데이터 변경에 관한 내용을 log에 기록

- 데이터 변경 연산이 실행되면, log파일에 log 레코드를 기록하고 DB에 변경 연산 반영

- 장애 발생 시점에 따라 redo, undo 연산을 하여 DB 복구

바로 바로 반영한다.

 

1) 트랜 잭션이 완료되기 전에 장애가 발생

=> <T1, start>레코드는 있지만 commit레코드는 없다, 따라서 undo 연산

2) 트랜 잭션 완료 후 장애 발생

=> start, commit 로그 레코드 둘다 존재(정상적으로 실행되었다 판단), 따라서 redo 연산

1 => 일부이므로 undo 연산

2 => T2는 일부만 시행했으므로 undo, T1은 commit했으므로 redo

 

2. 로그 회복기법 - 지연갱신 회복

- 트랜 잭션 수행중 데이터 변경 연산 결과를 로그에만 기록

- 트랜 잭션이 부분완료된 후 로그에 기록된 내용을 DB에 한번에 반영 (commit을 만나면 DB에 반영)

- 트랜 잭션 수행중, 장애 발생하면 로그기록을 버리면 DB가 원래 상태 유지하게 됨 (DB에 반영은 나중에 하므로)

- log만 삭제하면 되므로 undo 연산은 필요없고, redo 연산만 사용한다.

- 로그 레코드에는 변경 이후 값만 기록하면 됨.

 

1) 트랜 잭션이 완료되기 전에 장애가 발생

=> <T1, start>레코드는 있지만 commit레코드는 없다, 따라서 기록된 log 버림

2) 트랜 잭션 완료 후 장애 발생

=> start, commit 로그 레코드 둘다 존재(정상적으로 실행되었다 판단) => 데이터베이스에 반영, 따라서 redo 연산

 

 

3. 검사시점 회복 기법

- 로그 기록 이용

- 일정 시간 간격으로 checkpoint생성

- checkpoint 시점이 되면 모든 log 레코드를 log에 기록 => 데이터 변경 내용을 안정저장창지에 기록 => 검사시점을 표시하는 <checkpoint L> 로그 레코드를 로그 파일에 기록

- 백업본 + log로 복구

- 백업후 시행한 것 모두 redo or undo 하여야한다 => 양이 많을 수 있음

- 따라서 일정 시간 마다 안정저장장치에 변경 내용 저장

- 마지막 check point 이후 작업만 처리한다. => 가장 최근 검사 시점 이후의 트랜잭션에만 회복 작업 수행(즉시 갱신 or 지연 갱신 복구)

- 백업후 시행한 것 모두 redo or undo 하여야한다 => log 전체를 회복기법 적용하는 것 보다 효율성이 좋음

- 검사 시점으로 작업 범위가 정해지므로 불필요한 회복 작업이 없어서 시간 단축

 

 

4. 미디어 회복 기법

- 디스크에 발생할 수 있는 장애에 대비

- 덤프(복사본) 이용 => 전체 DB내용을 일정 주기마다 다른 안전한 저장장치에 복사

- 디스크 장애 발생시 => 가장 최근에 복사해둔 덤프를 이용하여 장애 발생 이전의 DB 상태로 복구, 필요에따라 redo연산 수행

 

728x90
반응형

'공부 > 데이터베이스' 카테고리의 다른 글

회복과 병행제어 - 병행제어  (0) 2021.06.04
관계 대수  (0) 2021.06.03
파이썬 연동 예제  (0) 2021.06.02
index  (0) 2021.06.02
데이터 베이스 보안  (0) 2021.06.02
블로그 이미지

아상관없어

,
반응형

관계 데이터 연산 

- 관계형 모델에서 제공하는 데이터를 다루기 위한 방법

- 원하는 데이터를 얻기위해 릴레이션에 필요한 처리 요구를 수행하는 것

- 관계대수: 원하는 결과를 얻기 위해 데이터의 처리과정을 순서대로 기술

- 관계해석: 원하는 결과를 얻기 위해 처리를 원하는 데이터가 무엇인지만 기술

 

관계대수와 관계해석

데이터 언어의 유용성을 검증하는 기준

=> 언어가 적합한지(관계대수/해석으로 할 수 있는 것을 제시한 언어 문법체계로 다 구현가능한지?)

관계 대수나 관계 해석으로 기술할 수 있는 모든 질의를 기술할 수 있는 데이터 언어 = 관계적으로 완전

 

관계 해석

어떻게 검색(X)

무엇을 검색(O)

무엇을 검색할것인가만 기술하는 선언적 표현법을 사용하는 비절차적 질의어

SQL등 많은 상업용 관계언어들이 관계해석에 기반을 두고있음

 

 

관계대수

- 원하는 결과를 얻기 위해 릴레이션의 처리 과정을 순서대로 기술하는 언어(절차 언어)

- 릴레이션을 처리하는 연산자들의 모임

- 폐쇄 특성이 존재(닫힌 성질) => 피 연산자도 릴레이션이고, 연산의 결과도 릴레이션임, input형태 = output형태 동일

 

관계대수와 관계해석 차이

- 관계해석 : 하나의 선언적, 해석식으로 검색질의를 명시, 비절차적 언어

- 관계대수 : 연산들을 순차적으로 사용하므로 절차적인 성질을 가짐

두 표현의 표현력은 동등

 

 

관계대수 연산자

1. 일반 집합 연산자

합집합 => 교환적, 결합적 특징, 차수는 릴레이션들의 차수와 동일, 카디널리티(행의 수)는 두 릴레이션의 카디널리티를 더한 것과 같거나 작음

교집합 => 교환적, 결합적 특징, 차수(컬럼수)는 두 릴레이션의 차수와 동일, 카디널리티(행 수)는 두 릴레이션 중 어떤 카디널리티보다 크지 않다.

차집합 (R-S) => R에는 존재하지만,  S에는 존재하지 않느 투플로 결과 릴레이션 구성, 차수는 R,S의 차수와 같음, 카디널리티는 R의 카디널리티와 같거나 적음, 교환적, 결합적 특징이 없음

 

카티션 프로덕트 => 교환적, 결합적 특징, R에 속한 투플과 S에 속한 투플을 모두 연결함. 차수는 R,S의 차수를 합한것과 동일, 카티널리티는 R과 S의 카디널리티를 곱한것과 같음

 

- 피연산자가 2개 필요하다

- 합집합, 교집합, 차집합은 피연산자인 두 릴레이션이 합병가능해야한다.

(합병가능 : 두 릴레이션의 차수(컬럼의 수)가 동일, 두 릴레이션에서 서로 대응되는 속성(칼럼)의 도메인이 같아야함(자료형이 동일해야)

 

순수 관계 연산자 => 릴레이션의 구조와 특성을 이용

셀렉트 σ(조건)(R) => 릴레이션 R에서 조건을 만족하는 투플들(행)을 반환 (행단위로 반환)

"릴레이션 where 조건식" 과 동일

비교연산자, 논리 연산자(∧, ∨, ¬(and, or, not))를 이용하여 작성

ex) 고객 릴레이션에서 등급이 gold인 투플을 검색하시오

σ(등급 = 'gold')(고객) = 고객 where 등급 = 'gold'

 

프로젝트  π(속성 리스트)(R) => 릴레이션 R에서 주어진 속성들의 값으로만 구성된 투플을 반환 (열단위로 반환)

ex) 고객이름, 등급, 적립금을 검색

π(고객이름, 등급, 적립금)(고객)

 

조인 R⋈S(자연조인) => 공통 속성을 이용하여 R,S의 투플들을 연결함

고객 ⋈ 주문

외래키는 지정이 되지 않아도 조인시 문제가 없지만 무결성 문제가 발생한다.

공통속성인 (고객.고객아이디), (주문.주문고객)은 한번만 나타난다. => 고객 아이디만 나타남

차수(속성)의 개수 = 두차수의 합 - 공통 속성의 개수

 

세타조인 R⋈(JOIN 조건)S => 자연조인에 비해 일반화된 조인, 

주어진 조인조건을 만족하는 두 릴레이션의 모든 투플을 연결하여 생성된 새로운 투플이 결과 릴레이션

결과 릴레이션의 차수는 두 릴레이션의 차수를 더한것

ex) 

고객⋈(고객아이디=주문고객)S

자연조인과 다르게 공통 속성이 둘다 표시된다.

 

디비전 R ÷ S => 릴레이션 S의 모든 투플과 관련 있는 릴레이션 R의 투플 반환

R이 S의 모든 속성을 포함하고 있어야 연산이 가능하다

고객 릴레이션에서 gold 등급을 가진 투플을 고름. 나누기에서 몫과 유사

 

 

 

외부 조인 (R ⋈+ S)=> 자연조인 연산에서 제외되는 투플도 결과 릴레이션에 포함시킴, 즉 두 릴레이션에 잇는 모든 투플을 결과 릴레이션에 포함 시킴

 

 

 

관계대수 예시)

1. 모든 부서의 이름과 지역명을 보이시오

2. 모든 사원의 이름과 담당업무를 보이시오

3. 담당업무가 ‘salesman’ 인 사원의 이름, 입사일자를 보이시오

4. 입사일자가 ‘1999-02-31’ 이후인 사원의 사원번호, 이름, 입사일자를 보이시오

5. 모든 사원의 이름과 부서명을 보이시오

6. 급여액(연봉)1000 이상인 사원의 이름, 급여액, 부서명을 보이시오

7. 입사일자가 ‘1999-02-31’ 이후인 사원의 사원번호, 이름, 부서명을 보이시오.

8. ‘Dalls’ 에 근무하는 사원의 이름, 급여액을 보이시오

9. 입사일자가 ‘1998-01-01’ 이전인 사원중 급여액이 1000 미만인 사원의 사원번호, 이름, 부서명을 보이시오.

 

728x90
반응형

'공부 > 데이터베이스' 카테고리의 다른 글

회복과 병행제어 - 병행제어  (0) 2021.06.04
회복과 병행제어 - 회복  (0) 2021.06.03
파이썬 연동 예제  (0) 2021.06.02
index  (0) 2021.06.02
데이터 베이스 보안  (0) 2021.06.02
블로그 이미지

아상관없어

,
반응형

Mysql my_db 와 연동하여 다음 내용을 실행하는 python 프로그램 

- 사원번호가 7521인 사원의 이름을 출력한다

- 이름이 SCOTT 인 사원의 부서이름을 출력한다

- 담당업무가 SALESMAN 인 모든사원의 이름을 출력한다.

- 모든 부서의 이름을 출력한다.

 

#mysql - python connection test

import pymysql #mysql과 연동하기 위해

#필요한 기본 DB 정보
host = "localhost"
user = "root"
pw = "password"
db = "my_db"

#DB에 접속
conn = pymysql.connect(host= host, user = user, password = pw, db = db)

#사용할 sql문
sql1 = "SELECT ename FROM emp WHERE empno=7521"
sql2 = "SELECT dname FROM emp, dept WHERE dept.deptno=emp.deptno and ename='scott'"
sql3 = "SELECT ename FROM emp WHERE job='salesman'"
sql4 = "SELECT dname FROM dept"

querys = [sql1, sql2, sql3, sql4]

for sql in querys:
    print(sql)
    
    # sql문 실행/데이터 받기
    curs = conn.cursor() #sql 실행시 결과를 담고 있는 버퍼를 정렬
    curs.execute(sql)	#앞의 sql문 실행 
    row = curs.fetchone() #sql실행결과 모두 가져오기, fetchall 모든 행 가져옴, fetchone은 하나의 행만 가져옴
    while(row):
        print(row)
        row	= curs.fetchone()	
        
    print("==========================================================")
    
#db 접속 종료
curs.close()
conn.close()

 

 

 

Mysql world 데이터베이스와 연동하여 다음과 같이 국가명을 입력하면 해당 국가의 정보를 출력하는 윈도우 프로그램

- 매치되는 국가가 없으면 모든 항목에 공백 출력

import sys
import pymysql
from PyQt5.QtWidgets import *

def connectDB():
    #필요한 db 정보
    host = "localhost"
    user = "root"
    pw = "Changmin97"
    db = "world"
    
    #db 접속
    conn = pymysql.connect(host=host, user =user, password =pw, db =db)
    return(conn)  #connection  리턴

def disconnectDB(conn):
    conn.close()
    
    

class MyApp(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()
        
    
    # UI 디자인 함수
       def initUI(self):
        #QLable 문자열 출력
        label1 = QLabel('Country name')
        label2 = QLabel('Continent')
        label3 = QLabel('Population')
        label4 = QLabel('GNP')
        label5 = QLabel('Captial city')
        label6 = QLabel('Language')
    
    

        #text_Country_name
        self.text_Country_name = QTextEdit()
        self.text_Country_name.setFixedWidth(200)
        self.text_Country_name.setFixedHeight(30)
    
    
        #버튼 생성, 버튼 클릭시 btn_1_clicked 실행
        btn_1 = QPushButton('Query')
        btn_1.clicked.connect(self.btn_1_clicked)
    
        #text_Continent
        self.text_Continent = QTextEdit()
        self.text_Continent.setFixedWidth(200)
        self.text_Continent.setFixedHeight(30)
    
        #text_Population
        self.text_Population = QTextEdit()
        self.text_Population.setFixedWidth(200)
        self.text_Population.setFixedHeight(30)
    
        #text_GNP
        self.text_GNP = QTextEdit()
        self.text_GNP.setFixedWidth(200)
        self.text_GNP.setFixedHeight(30)
        
        #text_Captial_city
        self.text_Captial_city = QTextEdit()
        self.text_Captial_city.setFixedWidth(200)
        self.text_Captial_city.setFixedHeight(30)
        
        #text_Language
        self.text_Language = QTextEdit()
        self.text_Language.setFixedWidth(200)
        self.text_Language.setFixedHeight(30)
        
        
        
    
        #화면 배치, grid를 만들어 배치
        gbox = QGridLayout()
    
        gbox.addWidget(label1,0,0)
        gbox.addWidget(self.text_Country_name, 0, 1)
            
        gbox.addWidget(btn_1, 0, 2)
            
        gbox.addWidget(label2,1,0)
        gbox.addWidget(self.text_Continent, 1, 1)
            
        gbox.addWidget(label3,2,0)
        gbox.addWidget(self.text_Population, 2, 1)
        
        gbox.addWidget(label4,3,0)
        gbox.addWidget(self.text_GNP, 3, 1)
        
        gbox.addWidget(label5,4,0)
        gbox.addWidget(self.text_Captial_city, 4, 1)
        
        gbox.addWidget(label6,5,0)
        gbox.addWidget(self.text_Language, 5, 1)
    

        self.setLayout(gbox)
        self.setWindowTitle('Country Info')
        self.setGeometry(300, 300, 480,250) #창뜨는 위치, 크기
        self.show()
        
        
    #버튼 클릭 처리
    def btn_1_clicked(self):
    
        #사용자가 입력한 값 받아서 empno 저장
        Country_name = self.text_Country_name.toPlainText()
            
        sql = "SELECT country.name, continent, country.population, gnp, city.name, language \
                From country, city, countrylanguage\
                where country.code = city.countrycode \
                    and country.code = countrylanguage.countrycode\
                    and country.capital=city.id\
                    and IsOfficial = 'T' \
                    and country.name ="+"'"+Country_name+"'"
        #ex) ename '"+ename+"'" =>문자일 경우 따옴표 주의!
        conn = connectDB()
        curs = conn.cursor()
        curs.execute(sql)
            
        result = curs.fetchone() # sql 실행 결과 가져오기

        if result:    
            self.text_Country_name.setText(result[0])
            self.text_Continent.setText(result[1])
            self.text_Population.setText(str(result[2]))
            self.text_GNP.setText(str(result[3]))
            self.text_Captial_city.setText(result[4])
            self.text_Language.setText(result[5])
        else:
            self.text_Country_name.setText("") #매치되는 국가가 없으면 모든 항목에 공백 출력
            
            
        curs.close()
        disconnect(conn)
            
#END Class


#프로그램 실행, class를 생성하고 실행
if(__name__ == '__main__'):
    app = QApplication(sys.argv)
    ex = MyApp()
    sys.exit(app.exec_())            
    
        

728x90
반응형

'공부 > 데이터베이스' 카테고리의 다른 글

회복과 병행제어 - 회복  (0) 2021.06.03
관계 대수  (0) 2021.06.03
index  (0) 2021.06.02
데이터 베이스 보안  (0) 2021.06.02
DB 파이썬 연동  (0) 2021.05.18
블로그 이미지

아상관없어

,

index

공부/데이터베이스 2021. 6. 2. 23:50
반응형

ex) select ename from emp where empid = 7934;

위 명령을 수행할때

1. 순차적으로 검색한다.

=> 요청이 많을 경우 처리시간이 오래 걸리게 된다.

 

2. 이진 검색 (데이터가 정렬되어 있는 경우)

데이터가 갱신 될때마다 정렬작업을 하여야하므로 비용부담이 크다.

 

3. index 이용 (index = keyword + address)

index는 해당 값의 주소를 가리킨다. 

그리고 index는 항상 sorting된 상태이다.(실제 데이터는 정렬되어 있을수도 있고 아닐수도 있다.)

index가 있는 column의 값을 기준으로 조회하면 빨라진다.

 

대부분의 DBMS는 기본키, 외래키에 대해 자동으로 index를 설정한다.

=> 테이블 생성시 기본키를 생성하면 자동으로 인덱스생성

외래키 컬럼에 대해서도 인덱스가 생김

기본키가 되었단 말은 검색의 기준으로 많이 선택되니 인덱스를 붙이는 것이 속도를 빠르게 할 수 있음

외래키도 테이블과 테이블을 조인하여야되는데, 매치되는 항목을 찾아야하므로 인덱스를 걸어주어 join연산을 빠르게 해줌

기본키 - empno

자기자신참조 - mgr

외래키 - deptno

에 대해 자동으로 인덱스가 생성됨

=> 인덱스가 없는 column을 기준으로 검색시 속도가 느림

따라서 검색 기준이 될만한 column들은 인덱스를 생성하는 것이 좋음

 

만약 모든  column에 index를 생성하면??

인덱스는 항상 정렬된 상태를 유지해야하므로, overhead가 커진다. 따라서 최소한의 index를 유지하는 것이 좋다.

 

 

SQL문으로 index생성하기

create index idx_job on emp (job);
show index on emp;

 

 

728x90
반응형

'공부 > 데이터베이스' 카테고리의 다른 글

관계 대수  (0) 2021.06.03
파이썬 연동 예제  (0) 2021.06.02
데이터 베이스 보안  (0) 2021.06.02
DB 파이썬 연동  (0) 2021.05.18
저장 함수 예제  (0) 2021.05.15
블로그 이미지

아상관없어

,
반응형

DBMS의 목적 중 하나는 데이터 베이스에 저장된 정보를 안전하게 보호하는 것이다.

이를 수행하기 위한 수단으로

추가 로그인

암호화 => 민감한 정보

사용자 관리 => 등록된 계정만

권한 관리

가 있다.

 

사용자 관리

사용자가 DB를 이용하기 위해선 계정이 필요함

사용자가 DBMS에 로그인하면 DBMS는 등록된 사용자인지 검사함

따라서 이를 위해 사전에 계정생성이 필요하다.

 

root

최고권한을 가진 사용자 계정으로 데이터베이스 및 DBMS에 대한 모든 권한을 가진다.

따라서 비밀번호가 노출되면 위험하고 일반 사용자에게 root권한을 주는 것은 위험하다.

그러므로 일반 사용자들은 별도의 계정을 만들어 사용하도록 해야한다.

 

사용자계정 생성시

localhost => DBMS 서버에 직접 접근 -> 원격접속 불가

% => DBMS에 원격 접속 ->직접접근 불가

 

서버에 직접 접속, 원격접속 둘다 하려면 같은이름의 local, remote계정 두가지 많들어야한다. 

 

권한은

1. 모든 DB

2. 패턴에 매칭되는 DB(이름으로 검색), 선택한 DB

에 접근할 수 있는 권한을 줄 수 있고,

select, insert, update, delete, execute, show view, create, alert, index, drop..... 와 같은 권한을 줄 수 있다

 

 

Mysql workbench는 DB단위로 권한을 부여하고 회수한다. => 세부적으로 되지 않는다.

따라서 sql 명령문 (grant, revoke)를 이용하여 테이블 단위로 권한을 부여하고 회수할 수 있다.

 

GRANT select ON my_db.emp TO user_1@localhost;
GRANT select, insert, update ON my_db.dept TO user_1@localhost;

 

 

root 사용자일 경우 sql문을 사용하여 사용자를 생성하고 권한부여, 회수가 가능하다.

localhost 사용자의 경우'

create user user_2@localhost identifited by '4321';

 

원격접속 사용자의 경우

create user 'user_2'@'%' identified by '4321';

 

생성된 사용자 확인

SELECT * from mysql.user;

mysql => system 카탈로그 정보가 있는 데이터 베이스

user => user테이블에 사용자 정보가 저장

 

 

권한의 부여

my_db에 대한 모든 권한 부여
grant all privileges on my_db.* to user_2@localhost;


일부 권한 부여
grant select, insert on my_db.* to user_1@localhost;


테이블에 대한 모든 권한 부여
grant all privilleges on my_db.emp to user_1@localhost;


테이블에 대한 일부 권한 부여
grant select, insert on my_db.emp to user_1@localhost;

 

 

with grant option

자신의 권한을 다른 user에게 부여할 수 있게 된다.

grant all privileges on my_db.* to user_2@localhost with grant option;

user_2로 로그인하여 다른 유저에거 자신의 권한을 grant 할 수  있다.

 

부여된 권한을 확인하려면

flush privileges; //변경된 내용을 메모리에 반영(권한 적용)
show grant for user_1@localhost;

 

 

권한 회수 => revoke

revoke delete on my_db.emp from user_2@localhost;

 

사용자 삭제

drop user user_2@localhost;

 

 

사용자 관리 - role

ex) 영업업무를 하는 user1, user2, user3이 있고 필요한 권한은 select, update일 경우

create role sales_role; //역할 생성
grant select, update on my_db.emp to sales_role; //역할에 권한 부여

grant sales_role to user1@localhost;
grant sales_role to user2@localhost;
grant sales_role to user3@localhost;

user1,2,3에 각각 역할을 준다.

 

 

728x90
반응형

'공부 > 데이터베이스' 카테고리의 다른 글

파이썬 연동 예제  (0) 2021.06.02
index  (0) 2021.06.02
DB 파이썬 연동  (0) 2021.05.18
저장 함수 예제  (0) 2021.05.15
저장 프로시저 예제  (0) 2021.05.15
블로그 이미지

아상관없어

,
반응형

cwe 119

메모리 버퍼의 경계가 있는데 경계와 관련된 연산에 대한 제한, 제약을 적절히 처리하지 못할때 생길 수 있는 약점

어떤 소프트웨어는 메모리 버퍼와 관련된 연산을 할 수 있다.

하지만 그 연산은 버퍼의 의도된 경계 바깥쪽의 영역을 read/wrtie할 수 있음

연산의 제약조건은 버퍼의 의도된 경계내에서 연산해야

버퍼의 경계내의 메모리를 읽고 쓰기 해야됨

 

어떤 언어는 직접적으로 메모리 위치를 참조하는데 그 위치가 실제로 유효한지 아닌지 확인 하지 않음

프로그램이 참조할 수 있는 유효한 주소인지 체크하지 않아 다른 변수나 자료구조 내부 프로그램 메모리 영역을 읽거나 쓸 수 있음 = >연산 제약을 제대로 처리 하지 않았기 때문에

공격으로 연결되면 임의의 코드를 실행할 수 있고 임의의 제어흐름으로 변조, 민감한 정보 읽기, 시스템이 망가짐

 

cwe 119 = > 버퍼 오버플로우라고도 함

버퍼 오버플로우는 사람마다 다른 의미로 사용가능

어떤 도구는 버퍼의끝을 넘어서서 write하는것

다른 개발자는 버퍼의 경계밖(버퍼의 시작점, 끝 밖의 공간)에서 읽거나 쓰는것.

또 어떤 사람들은 버퍼의 끝 이후에 어떠한 행동을 하는 것(읽기, 쓰기 가능)

사람마다 다르기때문에 혼란스러운 용어임

 

따라서 메모리 경계에서 부적절한 연산 제한이 올바른 표현이다.'

 

이러한 약점의 결과는 CIA가 깨짐

인가되지 않은 코드,명령실행, 메모리 변조 가능

한바이트만 조작할 수 있음

 

가용성, 기밀성

어떤 메모리를 읽을수 잇고 시스템이 비정상적으로 종료될수 잇음 (dos) cpu같은 자원을 소모(메모리도 가능)

메모리 경계를 넘어서면 메모리의 붕괴를 가져와 시스템이 붕괴됨

해당 프로그램이 공격을 받아서 무한루프상태로 갈수도 있다.

 

기밀성

read memory

주어진 자료구조 범위를 넘어서서 읽으면 민감한 정보를 읽을 수도 잇다.

메모리의 현재 버퍼의 위치와 같은 정보

 

어떻게 완화??

소프트웨어 보안은 개발생명 전 주기에서 고려

각 단계에서 취약점을 완화할 숭 ㅣㅆ다

요구사항분석 => 언어선택을 잘 해야. cwe119에 강한 언어를 사용하며 ㄴ좋다, c보단 자바와 같은 언어(자체적으로 메모리 관리를 함) ada나 c#은 오버플로우 보호기법을 적용하고 잇음

그렇지만 이러한 언어들은 binary가 아님 실제 실행시 native코드로 변환 되어야함. 따라서 native code와 상호작용하는 인터페이스는 오버플로우 약점에 취약(자바 가상머신은 c로 만들어져잇음)

언어를 윗단에서 좋은 언어를 사용하더라도 완전하게 해결하는 것은 아님

 

아키텍쳐및 설계

라이브러리나 프레임워크를 잘 사용

검증이된 라이브러리나 프레임 워크 사용 => safe c String 라이브러리, strsafe.h

string 관련 오버플로우 문제를 해결 => 완벽X 

많은 오버플로우는 string고 ㅏ연관 없음, 하지만 string관련 문제를 해결가능

cwe119취약점을 방어할 숭 ㅣㅆ다.

 

빌드 컴파일 단계

컴파일 할때 최신 컴파일러사용, 컴파일 옵션을 버퍼 오버플로우를 탐지할 수 잇게 사용

MS visual studio 에선 GS flag, Fedora/red hat에선 fortify source gcc flag사용 

공격이나 취약점을 조기에 탐지할 숭 ㅣㅆ음

하지만 완변하지 ㄴ않음

 

 

구현단계 

자신이 작성중인 버퍼가 원하는 대로 작동하는지 두번이상 확인

strcpy -> strncpy

gets->fgets

memcpy보다 안전한 것 사용

안전한 라이브러리 함수 사용

 

운영단계

운영 환경을 좀더 안전하게 만들어라

관리자는 aslr , position-independent executable (pie)와 같은 기능을 사용해서 특정한 주소를 공격자가 예측하지 못하게 해라

공격자는 버퍼의 주소를 예측하기 어려움

NX비트 활용 (hw기법)

임의의 코드가 스택이나 데이터 세그먼트에 들어갈 확률이 높은데,  data execution protection(nx) 를 하면 코드 세그먼트가 아닌 스택이나 데이터 세그먼트 코드는 실행하기 못하게함.기본적으로 프로세스의 메모리 레이아웃에서는 코드, 텍스트 세그먼트의 코드만 실행해야함. 공격자들은 자기가 실행하고 싶은 코드를 스택이나 ㄴ=데이터 세그먼트에 넣음, 

기본적으로 코드(텍스트) 세그먼트는 read only 여서 코드 주입 불가

 

 

 

 

 

 

 

 

 

 

 

728x90
반응형

'공부 > 보안' 카테고리의 다른 글

Android 앱 난독화 실험 및 분석  (0) 2021.06.24
Widthness bugs  (0) 2021.06.02
암호화 기본 - 2  (0) 2021.06.02
암호화 기본 - 1  (0) 2021.06.01
apk 난독화  (0) 2021.05.17
블로그 이미지

아상관없어

,

Widthness bugs

공부/보안 2021. 6. 2. 15:41
반응형
#include <stdio.h>

int main(){
	int l;
    short s;
    char c;
    
    l = 0xdeadbeef;
    s=l; //short에 int
    c=l; //char에 int
    
    
    printf("l=0x%x (%d bits)\n", l, sizeof(l) * 8);
    printf("l=0x%x (%d bits)\n", s, sizeof(s) * 8);
    printf("l=0x%x (%d bits)\n", c, sizeof(c) * 8);
    
    
    return 0;
}
    

short : 16bit = 2byte이고, b -> 최상위비트가 1이므로 0xffffbeef가 된다.

char : 8bit = 1byte이고, e -> 최상위비트가 1이므로 0xffffffef가 된다.

 

signed int n;

+65535 = 0x0000ffff

+65536 = 0x00010000

 

unsigned short s = +65536 (?)

 

 

./ex2 65536 hello

#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]){
	unsigned short s;
    int i; 
    char buf[80];
    
    if(argc < 3) return -1;
    
    i = atoi(argv[1]); //65536
    s=i; //65536 => 오버플로우로 0이됨
    
    //s는 0이므로 if 통과
    if(s>=80){
    	printf("oh no you don't!\n");
        return -1;
        }
        
    printf("s=%d\n", s);
    memcpy(buf, argv[2], i); //memcpy에선 i가 unsigned int형으로 변환됨
    //buf의 크기는 80인데 65536만큼 복사하려함 (dest, source, size)
    buf[i] = \0';
    printf("%s\n", buf);
    return 0;
}

 

 

65535 = 0x0000ffff

65536 = 0x00010000

 

부동소수점 정밀도 문제 => 실수는 무한히 많은데 이 실수를 유한 개의 비트로 표현하기 위해서는 근삿값으로 표현해야 하기 때문이다. =>부동소수점 반올림 오차

(컴퓨터가 실수를 저장할때 가수부와 지수부로 나누어 저장을 한다.)

(int형으로의 캐스팅은 반올림하지 않고 소수점이하를 잘라버린다.)

 

728x90
반응형

'공부 > 보안' 카테고리의 다른 글

Android 앱 난독화 실험 및 분석  (0) 2021.06.24
cwe119 버퍼 오버플로우 방어  (0) 2021.06.02
암호화 기본 - 2  (0) 2021.06.02
암호화 기본 - 1  (0) 2021.06.01
apk 난독화  (0) 2021.05.17
블로그 이미지

아상관없어

,
반응형

혼돈 : 암호문의 통계적 특성과 암호키 값과의 관계를 가능한 복잡하게 하는 기법, 암호문을 보고 원문을 유추하기 힘들다.

- 평문의 통계적 특성들을 잘 숨겨야한다.

- 복잡한 치환 알고리즘을 사용한다.

- 예시 : hill cipher

- 암호문의 각 문자는 키의 일부분에 의존함.

 

확산 : 암호문의 통계적 특성이 평문의 통계적 특성과 무관하게 하는 기법, 알고리즘의 패턴을 추론하기 힘들다.

- 평문의 통계적인 구조가 암호문에 골고루 흩어지게함

- 암호문에서 평문의 통계적 특성이 안나타남

- 평문 블럭 또는 암호화키의 bit하나가 달라지면 암호문에서 큰 변화가 됨

 

시저암호화 비즈네로 암호화는 혼돈과 확산의 속성을 갖고 있지 않다. 따라서 빈도수 공격에 취약하다.

많은 현대 암호화들은 혼돈과 확산의 속성을 가지고 설계되었다.

 

 

DES : 혼돈과 확산을 가지는 블록 암호화이다.

AES : 혼돈과 확산을 가지며, substituion-permuatation network이다.

 

 

Block 암호화 : 64/128 bit block

- DES(64)

- AES(128)

- SEED

Block 단위로 처리되어 빈도수와 중복패턴을 줄여주기 때문에, block의 크기는 클수록 안전하다. 

=> 시저암호는 블럭단위로 처리하지 않아 빈도수 공격에 취약하고 hill 암호화는 블럭단위로 처리하여 빈도수 공격에 안전하다.

 

Stream 암호화 : 1 bit 혹은 byte 단위로 처리한다.

- RC4 stream cipher

- otp => 빠르게 하기 위해 xor 연산을 한다. 키가 반복될시 위험하다. 

 

Block 암호화 Stream 암호는 처리단위가 다르다.

 

DES와 AES 둘다 대칭키 암호화알고리즘이다.

DES는 64bits block이지만 AES는 128bits block이다.

키의 길이 또한 AES가 더 길다.

DES는 Substituion, permutation을 사용하지만, AES는 substitution, shift, bit mixing을 사용

DES 알고리즘은 비공개이고 AES는 공개되었다.

=> kerckhoff's principle: 키 제외 나머지는 모두 공개,  키의 길이가 길수록 안전성이 높아진다. (전사적 공격이 어려워짐)

 

대칭키

- 키 분배의 문제가 발생된다.

따라서

Diffie-Hellman 키 교환 : 안전하지 않은 통신 채널로도 키를 공유할 수 있게 된다.

Alice는 a, g, p를 정하고 Bob에게 g, p, A를 전달한다.

Bob은 b를 정하고 B를 Alice에게 전달한다.

Bob과 Alice는 각각 A, B로 같은 S를 얻는다.

 

 

위와 같은 방식으로 대칭키를 분배할 수 있다.

 

- 대칭키, 비대칭키 키의 개수

먼저, 대칭키는 n명이 있을때 n(n-1)/2만큼의 키가 필요하다 => O(n^2)

비대칭키는 n명이 있을때 2n만큼의 키가 필요하다 => O(n)

따라서 비대칭키가 필요한 키의 개수가 적다.

 

비대칭키를 사용하지 않고 대칭키를 사용하는 이유는 대칭키는 계산량이 비교적 적은 반면 비대칭키(공개키)는 계산량이 많기 때문이다.

 

비대칭키는 서명에도 사용된다.

A의 개인키로 암호화한다면 A의 공개키로 복호화 가능하므로 A라고 확인 할 수 있다.

 

대칭키 : 서로 비밀키를 공유, 키의 개수 n(n-1)/2, 메시지 암호화에 사용, 덜 복잡하여 빠르다. 기밀성, DES, AES, SEED, IDEA

공개키 : 인증, 서명, 짧은 메시지 암호화에 사용, 공개키로 암호화시 보낸사람을 확인하는 서명이 필요하다. 알고리즘이 복잡하여 느리다. 기밀성, 인증, 부인방지(전자서명), 공개키 관리(Public Key Insfrastructure), RSA, ECC, ElGamal

728x90
반응형

'공부 > 보안' 카테고리의 다른 글

cwe119 버퍼 오버플로우 방어  (0) 2021.06.02
Widthness bugs  (0) 2021.06.02
암호화 기본 - 1  (0) 2021.06.01
apk 난독화  (0) 2021.05.17
Anti-Reverse Engineering  (0) 2021.05.14
블로그 이미지

아상관없어

,
반응형

codebook & chiper

code : 어떤 메시지를 암호화하는데 사용하는 방법(단어나 구가 다른 어떤것으로 변환하게 하는 방법)

codebook : 단어나 구절을 암/복호화 하는데 사용하는 문서

cipher : 개별적인 문자, bit 수준에서 메시지 암호화

메세지가 코드에 의해 변환되고 그 뒤 chiper에 의해 변환된다.

chiper : 암호, 암/복호화 시스템/알고리즘

평문 : plaintext, clear text

암호문 : chipertext, cypertogram

Cryptography : 암호기법 (암호화 방법)

Cryptanalysis : 암호해독 (키 없이 복원) => Cryptanalyst (암호문 깸)

Cryptology : 암호학(키로 암/복호화) => Cryptographers (암호문 생성)

Cryptography : 암호기법 (암호화 방법)

메시지를 쉽게 이해할 수 없는 형태로 바꾸고, 다시 원래의 형태로 복원하는 것.

기밀성, 데이터 무결성, 부인방지, 인증을 포함하는 정보보안을 제공하는 수단이나 방법

Symmetric key, Asymmetric key

key => 기밀성, 무결성, 인증 등을 하기위해 사용하는 암호화 알고리즘의 input

키를 안전하게 보관하는 것이 중요 => TPM(trusted platform module), secure co-processor, smartcards...

keyspace

모든 가능한 키들의 집합이다.

keyspace가 크면 안전하지만 bit길이가 길어지고, 그만큼 계산량도 많아진다.

crypto(암호화)

Only the key is secret => 케르크호프스의 원칙

공격자는 시스템에대해 알고 오직 키만 모른다.

암호화 알고리즘은 비밀이 아니며, 오직 키만 비밀이다.

비밀 알고리즘은 노출 되었을때 위험해지고, 언젠가는 노출된다.

따라서 open하여 취약점들을 없앤다.

Substitution(대치,치환)/Transposition(전치(위치를 바꿈))

Substitution(대치, 치환)

1:1 혹은 1:多 대응

하나의 symbol을 또 다른것으로 대체함

예시)

1. caeasar 암호(= shift chiper, Additive cipher)

shift chiper, Additive cipher

k = key만큼 shift함

ex) key = 7

C = (P + k) mod 26

P = (C - k) mod 26

Brute-force attack

위의 방법으로 암호화된 암호문을 Key가 1일때, 2,3,4,5,...26 일때의 경우를 모두 조사하면 평문을 찾을 수 있다.

따라서 위의 암호화 방법은 안전하지 않으므로 keyword를 추가하여 복잡하게 만들 수도 있다.

2. keyword 추가(전수조사 막기위해)

예를 들어 keyword가 ZEBRAS이면

ZEBRAS를 먼저 놓고, Z, E, B, R, A, S를 제외한 알파벳을 놓아 평문을 치환한다.

=> 가능한 keyCaesar 암호화보단 깨기 어려워진다.

또는

알파벳을 순차적으로 대응하지 않고 섞어서 대응하여도 복잡해진다.

하지만, 위의 방식들은 모두 1대1 대응이므로 문자의 빈도수를 세면 유추가능해진다.

항상 고정적으로 하나의 평문 문자가 하나의 암호문 문자로 대응되어 유추하기 쉽다. => 단일문자 치환 암호

(자주나오는 모음이나 diagram(2개문자), tigram(3개문자))

3. 비즈네로 암호 (빈도수 유추 막기위해)

예시) keyword - pascal

먼저 평문의 알파벳을 순서에 맞는 숫자에 대응하고

키워드 문자를 숫자에 대응하여

C = (P + K) mod 26 하여 암호문을 구한다.

s -> H, h- >H

s -> H, s -> S

와 같이 1대1 대응이 아니라 1대多 대응이 된다.

따라서 빈도수 공격을 완화시킬 수 있다.

비즈네로 암호는 이러한 방법을 사용한다.

실제론, 아래와 같이 비즈네르 table을 이용하여

키워드(Darkly)를 대응시켜 (K, P)와 같이 대응되는 문자를 테이블에서 찾아 암호문을 만든다.

하지만 이 방법도 키워드가 반복되므로 주기(키 길이)를 예측 할 수 있어 유추 가능해진다(암호 원리 파악 가능).

(평문 내용과 키워드 위치가 반복된다, 언어구조와 빈도 정보로 유추)

따라서 keyword의 길이를 평문길이만큼으로 하는 one-time-password을 사용하면 해결할 수 있지만, keyword를 관리하는 것이 어렵다.

4. one time pad

깨질 수 없는 안전한 암호 기법이다. 그 이유는 ...

  1. 키(s)의 길이가 평문과 같거나 길다. => 암호문은 평문에 대한 어떠한 정보도 제공하지 않는 것처럼 보인다.

  2. 키(s) 정보는 두 당사자만 알고 있다.

  3. otp는 랜덤 생성해야하며 한번만 사용하므로 이전에 사용한 키는 사용되지 않는다.

하지만 키의 분배가 어려운 문제가 있다. 따라서 이론적으로만 안전하다.

c= m xor s, 평문을 키와 xor연산하여 암호문을 얻는다.

(평문이 8개의 문자를 사용하여 8bit 키를 사용함)

복호화 역시 같은키로 한다.

하지만 여기서 Alice와 Bob이 키를 주고 받을때, 중간에 이중첩자 Charlie가 다른키를 Bob에게 알려준다면, Bob은 복호화문을 이해하기 어렵거나 확인을 위해 Alice에게 직접 찾아가야한다.

혹은 Alice가 포로로 잡혓을때, 적들에게 잘못된 키를 알려준다면 적들은 해당 키로 복호화한 평문이 진짜인지 아닌지 판단할 수 없다.

다른 방법으론,

5. keyword 뒤 평문을 배치하여 키 길이를 맞춘다. (키 = keyword + 평문) (keyword 반복 문제 해결)

현대 암호에서는 이러한 방식을 응용한다.

2bit의 평문을 S-Box(substitution box)를 통하여 4bit로 확장시킨다.

정리하면,

monoalphabetic cipher(단일문자 치환 암호)는 전체 메시지에 대해 고정된 치환(1대1 대응)을 하여 빈도 수 공격으로 유추 가능해진다.

polyalphabeti cipher(복합 문자 치환 암호)는 평문에서 문자의 위치에 따라 대체되는 문자가 다르다 (1:多 대응),

하지만 기본적으로 문자 단위로 처리되므로, 키워드 반복시 주기를 알 수 있고, (모음), (모음은 자음에 의해 분리된다), (diagrams(연속되는 2개의 문자)), (Q뒤에는 U가 따라옴)과 같은 정보로 유추할 수 있다.

6. polygraphic substituion ciper (다중문자 대치) => Hill Cipher => Block 사용

하나의 평문 문자를 또 다른 암호문자 하나로 대응하면 즉, 문자 하나씩 암호문으로 변환할 경우에 빈도수 공격에 취약해진다.

다중문자 대치는 이웃한 문자를 그룹으로 만들어 그룹단위로 취급한다. => block 단위block의 크기를 n이라 하면

_n = 2일 경우) _

평문 : MISSISSIPPI

Block : MI SS IS SI PP IK

(Block 크기를 위해 더미 k를 추가함)

MI -> EQ, SS->GC ....와 같이 치환한다.

n, 즉 block이 커질 수록 빈도수 공격에 강해진다.

Playfiar cihper (n = 2) => 2x2 hill ciper이다.Y = Ax mod26(Y = 암호문, A = 키, x = 평문)다음과 같이 표현할 수 있다.

평문 : AT, Key : CDDG 인 경우)C -> 3, D->4, D->4, G->6

따라서

k를 표현할 수 있고, 평문 AT를 k로 암호화하면(k는 정방행렬로 만들어야한다. 암호화는 행렬의 곱이고 복호화는 역행렬을 만들어 곱을한다. 따라서 계산식을 쉽게 만들 수 있어야한다.)

5, 10 => FK가 나온다.(mod 26인 이유는 알파벳을 숫자로 표현했기 때문)

n을 3으로한 경우)

3x4 즉, 블럭의 크기를 12로 하여도 된다. => block 크기 가변적

복호화는 k의 역행렬을 곱하고 mod26을 하여 평문을 얻을 수 있다.

긴 평문 예시)

예시 - WANT_HELP.

WAN/ T_H/ ELP/ ... (더미 .. 추가)

22 0 13/ 19 28 7/ 4 11 15/ 26 26 26 (알파벳을 숫자로 바꿈)

키 = A

25 23 21/ 23 14 1/ 17 4 14/ 19 11 12

암호문 : ZWV XOB REO TLM

Transposition(전치(위치를 바꿈))

문자들의 순서를 바꾼다.

Columnar Transposition

1. simple

컬럼의 크기를 정하고 그에 맞게 평문을 자른다.

ENEMY TANKS APPROACHING HILL EIGHT SIX THREE

만약 컬럼의 개수의 배수가 아니면 더미를 추가한다.

그후, 컬럼별로 가져온다.

ENOHHR NKAITE ESCLSE MAHLIS YPIEXT TPNITO ARGGHP

만약 block의 크기가 5라면 5씩 잘라 표현한다.

ENOHH RNKAI TEESC LSEMA HLISY PIEXT TPNIT OARGG HPxxx (더미 추가)

2. 컬럼 순서 지정

컬럼에 순서(key)를 지정하여 순서에 따라 컬럼을 읽는다.

혹은 알파벳(key)으로 순서를 줄 수도 있다.,

=> EATI THIH MEXN ETMG MEDT

3. Double Transposition (행과 열 둘다 사용)

평문 : attackxatxdawnx (공백 대신 x를 사용하였다.)

먼저 행을 (3,5,1,4,2)의 순서로 바꾸고 열을 (1,3,2)순으로 바꾼다.

열로 읽었을 경우 : xwaxa txtak antdc

행으로 읽을 경우 : xta wxn att xad akc

4. Route Transposition Cipher

4.1. Rail-Fence Cipher

예시 rail 2개)

평문 = Meet me after the toga party

예시 rail 3개)

평문 = WE ARE DISCOVERED. FLEE AT ONCE

WECRL TEERD SOEEF EAOCA IVDEN

4.2. 위 방법외에 입력위치를 다르게 할 수 도 있다.

ex)

REINFORCEMENTS ARRIVING NOW

NMRGI FEEAR NNEOC NSIIO RRTVW

혹은 삼각형 모양으로도 할 수 있다.

4.3. Triangular Pattern

RMIFE VEONI RIRTN NCSGE ANROW

P- box

현대의 전치암호는 P(permutaiotion) box를 사용한다.

그냥 순서를 바꿔주는 p-box,

압축을 해주는 p-box

확장을 해주는 p-box

현대 암호인 AES는 Pbox를 사용한다.

튜링

튜링 머신

what can be computed. => 실제로 어디까지 계산가능한가?

어떤것, 어디까지 계산을 할 수 있는지 조사하는데 도움을 줄수 잇는 단순한 추상화된 컴퓨팅 기기

컴퓨터가 어디까지 가능한지(computability)를 나타내는 기본적인 모델임.

튜링 테스트

Can Machine think?

기계가 생각을 할 수 있는 가?

A : 기계 (질문시 사람인척 할 것임)

B : 사람

C(사람) : A, B가 사람인지 기계인지 판단(text기반 질문으로)

만약 C가 A, B를 구분하지 못한다면, A(기계)는 인공지능을 가진것으로 판단한다.

728x90
반응형

'공부 > 보안' 카테고리의 다른 글

Widthness bugs  (0) 2021.06.02
암호화 기본 - 2  (0) 2021.06.02
apk 난독화  (0) 2021.05.17
Anti-Reverse Engineering  (0) 2021.05.14
Reverse Engineering  (0) 2021.05.14
블로그 이미지

아상관없어

,
반응형

HTTP


웹은 HTTP를 이용해서 통신하는 클라이언트와 서버로 구성

 

HTTP 메시지 구조

 

요청 메시지 : 요청라인 - 헤더 - 공백 - 바디

Request line => 요청방식(method) - 요청페이지 - 프로토콜/버전 으로 구성

ex) GET /dir/page.html HTTP/1.1

(공백으로 정보 구분)

  • GET(메소드)
  • /dir/page.html (URL)
  • HTTP/1.1 (프로토콜:HTTP 버전:1.1)

헤더 : General Headers, Response Headers, Entity Headers

바디 : 응답 메시지(HTML)

 

 

 

응답 메시지 : 상태라인 - 헤더 - 공백 - 바디

Status line => 프로토콜/버전 - 응답상태코드 - 응답상태메시지 로 구성

ex) HTTP/1.1 200 OK

  • HTTP버전 1.1
  • 200(상태코드)
  • OK(응답이유)

헤더 : General Headers, Response Headers, Entity Headers

바디 : 응답 메시지(HTML)

 

 

** 요청방식(method)

  • GET : 자원요청(기본값), 요청 파라미터를 URL에 붙여서 전송 , 서버로부터 데이터 획득
GET /HTTP/1.1
Host: foo.com
  • POST : 자원 요청, 요청 파라미터를 Body에 붙여서 전송, 서버에 데이터 추가
POST / HTTP/1.1
Host: foo.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 13

say=Hi&to=Mom
  • HEAD : HTTP Header 정보만 요청
HEAD /index.html
  • PUT : URL 자원을 생성하도록 요청 (파일 업로드 가능), 서버에 데이터 갱신
PUT /new.html HTTP/1.1
Host: example.com
Content-type: text/html
Content-length: 16

<p>New File</p>
  • DELETE : URL 자원을 삭제하도록 요청 (파일 삭제 가능), 서버에 데이터 삭제
DELETE /file.html HTTP/1.1
  • TRACE : 진단 목적, 서버는 응답바디에 요청받은 자료와 동일한 내용 보냄
TRACE /index.html
  • OPTION : 응답 가능한 HTTP 메소드 요청

 

 

 

** RESTful API

http에는 여러 매소드가 있다.

하지만 REST는 CRUD(Create, Read, Update, Delete) 4가지 메소드만 사용한다.

create = post, read = get, update = put, delete =delete

 

 

 

HTTP 응답 상태 코드

1xx : 정보 제공

2xx : 요청 성공적

3xx : 요청한 자원이 다른곳에 있음

4xx : 요청에 문제있음

5xx : 서버에 에러있음


 

 

 

 

세션과 쿠키


HTTP 비연결지향 : 클라이언트-서버 연결 후 하나의 요청과 응답을 처리하고 연결 종료(응답이 끝나면 연결 종료)=> 클라이언트 정보가 서버에서 관리 되지 않음, 연결유지를 위한 리소스를 줄여 더 많은 연결을 가능하게 함, 연결/연결종료에 대한 오버헤드 발생

HTTP 무상태 프로토콜 : 연결을 종료하는 순간 클라이언트-서버 통신 끝, 클라이언트 상태 정보 유지안함(이전 통신 정보 모름)

따라서 쿠키와 세션이 필요

 

 

쿠키

- http 통신시 사용자 정보 유지하기 위해 사용

- 서버에서 생성하여 응답 헤더에 붙이고 클라이언트에 전송

- 쿠키는 요청을 전달할 때 이름=값 형식으로 요청 헤더에 포함되어 서버에 전달

  • 쿠키 제약사항 : 브라우저당 최대 300개, 호스트마다 20개 가능, 크기 4kb\

예시) 인터넷 쇼핑몰 장바구니, 로그인 페이지 ID/PW 자동저장

 

세션 쿠키 : 브라우저가 열려 있는 동안 유효한 쿠키, 서버 이용하는 동안 사용자 정보를 유지하기 위해

 

영속 쿠키 : 디스크에 유효기간 동안 저장되는 쿠키, 재방문시 정보를 기억하기 위해

 

 

쿠키 발행시 옵션 속성 지정 가능

  • Domain : 브라우저가 쿠키 값을 전송할 서버의 도메인 지정

cookie.setDomain("test.com");

  • Path : 브라우저가 쿠키 값을 전송할 URL 지정

cookie.setPath("/경로");

  • Expires : 쿠키 유효기간 설정

cookie.setMaxAge(값);

  • Secure : SSL 통신 채널 연결시에만 쿠키 전송하게 설정

cookie.setSecure(true);

  • HttpOnly : 자바 스크립트에서 쿠키값 읽지 못하게 설정

cookie.setHttpOnly(true);

 

 

세션

  • 클라이언트와 서버의 논리적인 연결
  • 일정 시간동안 같은 클라이언트로부터 송신되는 request를 하나의 상태로 인식하고 상태를 유지함.
  • 브라우저로 웹 서버 접속 후 브라우저 종료될때까지 연결이 유지되는 상태
  • 서버는 사용자 정보를 유지하기 위해(http를 사용하는 경우) 서버의 메모리에 브라우저별 세션 영역 할당
  • 각 영역은 세션 ID로 구분 => 세션 ID = 세션 토큰
  • 각 클라이언트마다 고유 ID 가짐, 서버에 저장하므로 쿠키보다 안전
  • 서버에 저장하므로 서버 저장공간 필요, 서버가 처리하므로 부하 발생

 

세션 ID를 클라이언트에 전달하는 방법

1. HTML 히든 필드 이용

  • 세션 ID를 HTML의 히든 필드로 클라이언트에 전달
  • 히든 필드이므로 웹페이지에서 안보임
  • 소스 보기를 통해 세션 ID값 추출 가능

 

 

2. URL rewriting을 이용

  • 클라이언트 브라우저가 쿠키 사용을 제한한 경우에 사용
  • 웹 서버에 서비스되는 페이지의 모든 URL에 세션 ID를 request parameter로 붙여 사용

https://dololak.tistory.com/579
https://dololak.tistory.com/579

 

3. 쿠키 이용

  • 클라이언트 브라우저가 쿠키 사용을 허용하는 경우

서버가 세션 ID를 생성 -> 쿠키에 저장 -> 헤더에 세션ID 저장하여 전달 -> 클라이언트 식별

 

 

 

세션을 이용한 클라이언트-서버 응답/요청

  • 클라이언트별 유일한 세션 ID 부여 => 클라이언트 식별
  • 클라이언트 첫 요청시 세션ID 생성, 전달
  • 두번째 요청부턴 세션 ID 사용

https://tansfil.tistory.com/58

  쿠키 서버
저장위치 클라이언트 서버
만료시점 쿠키저장시 설정 정확한 시점 모르
리소스 클라이언트 리소스 서버 리소스
용량제한 O X

 

 

 

 

 

정규식


  • 특정한 규칙을 가진 문자열 집합을 표현하는데 사용하는 형식 언어

ex)

String str = "abcdefghijk";

System.out.println(str.replaceAll("[abchij]", "굿"));

=> 정규표현식 "[abchij]"는 a,b,c,h,i,j를 개별적으로 의미함


 

 

 

 

인코딩 스키마


  • 문자 인코딩

문자들의 집합을 컴퓨터에서 저장 or 통신에 사용할 목적으로 부호화하는 방법 = 인코딩

웹 애플리케이션에서 사용되는 데이터들 => 네트워크 통해 여러 종류 시스템으로 전달됨

따라서 인코딩 스키마를 적용하여 안전하게 데이터 사용

 

  1. URL 인코딩

URL에 포함된 문자들이 안전하게 웹 서버에 전달 될 수 있도록 특수한 기능을 가진 메타 문자들을 브라우저가 인코딩해 전달 => 브라우저 특성에 따라 특수문자 표현 변형 오류 막기 위해

 

  1. HTML 인코딩

HTML문서에서 특별한 기능을 수행하는 문자들의 의미를 제거하고 일반적인 문자로 표시하기 위해 사용되는 인코딩 방식

 

  1. Base64 인코딩

모든 바이너리 데이터들을 출력 가능한 ASCII 문자들을 이용해 안전하게 나타내도록 하는 방식 => 이메일 첨부 파일을 인코딩해서 SMTP를 통해 안전하게 전송 or HTTP 승인을 사용하는 경우 사용자 인증서를 인코딩할때 사용

 

  1. 멀티바이트 인코딩

EUC-KR, MS949, 유니코드, UTF-8 등의 인코딩 방식

1~4바이트를 사용하여 다양한 문자를 표시

 

  1. MS 스크립트 인코딩

MS에서 제공하는 인코딩 기법으로 IE에서만 사용가능

 

예시들)

https://ande226.tistory.com/121


728x90
반응형
블로그 이미지

아상관없어

,
반응형
# -*- coding: utf-8 -*-
"""
Created on Mon Feb 22 14:47:47 2021

@author: changmin
"""
'''
msg = "It is Time"
print(msg.upper()) #대문자로 결과물만, msg는 그대로 
print(msg.lower()) # 결과물만 소문자로
print(msg)

tmp = msg.upper()
print(tmp)
print(tmp.find('T')) # 문자열에서 해당 문자 인덱스 번호 반환(처음 발견한)
print(tmp.count('T')) # 문자열에서 해당 문자 개수 반환
print(msg[:2]) # 슬라이싱 => 처음부터 2개만
print(msg[3:5]) # 3번 인덱스부터 4번 인덱스 까지
print(len(msg)) # 문자열 길이 반환

for i in range(len(msg)):
    print(msg[i], end =" ") #  옆으로 출력
    
print()

for x in msg:
    print(x, end = " ")
print()

for x in msg:
    if x.isupper():
        print(x, end =' ')
    elif x.islower():
        print(x, end = ' ')
        
print('\n\n')
for x in msg:
    if x.isalpha():
        print(x, end=' ')

print()        
tmp = 'AZ'
for x in tmp:
    print(ord(x)) # 아스키 넘버 출력
    

tmp =65
print(chr(tmp))
'''

'''
리스트와 내장함수(1)
'''
'''
import random as r
a=[]
print(a)
b = list()

a=[1, 2, 3, 4, 5]
print(a)
print(a[0])

b = list(range(1, 11))
print(b)

c=a+b
print(c)

print('\n\n\n')

print(a)
a.append(6)
print(a)

a.insert(3, 7) # 3번 인덱스에 7넣음
print(a)

a.pop() # 맨 뒤 인덱스 없앰
print(a)

a.pop(3) # 3번 인덱스 없앰
print(a)

a.remove(4) # 4라는 값 제거
print(a)

print(a.index(5)) # 5라는 값이 있는 인덱스 번호를 반환

d=list(range(1, 11))
print(d)

print(sum(d)) # 리스트 안의 합을 반환

print(max(d)) # 리스트중 가장 큰값 찾아줌

print(min(d)) # 작은값 반환

print(min(7, 5)) # 인자값들 중 최소값을 찾아줌

print(min(7, 3, 5))

print(d)
r.shuffle(d) # 값 섞음
print(d)

d.sort() # 오름차순
print(d)

d.sort(reverse = True) # 내림차순
print(d)

d.clear() # 리스트 값들 다 삭제
print(d)
'''



'''

'''
#리스트와 내장함수 2
'''

a =[23, 12, 36, 53, 19]
print(a[:3]) # 슬라이싱
print(a[1:4]) 
print(len(a)) # 길이 출력

for i in range(len(a)):
    print(a[i], end=' ')    
print()

for x in a:
    print(x, end = ' ')
print()

for x in a:
    if x%2 == 1:
        print(x, end = ' ')
print()
    
# 튜플로 출력
# enumerate => (0,23) (1,36) ..... (4,19) 
for x in enumerate(a):
    print(x[0], x[1])
    
for index, value in enumerate(a):
    print(index, value)
print()

# all => 모두 참이면 참을 리턴
if all(50>x for x in a):
    print('Yes')
else:
    print('No')
    
# any => 한번이라도 참이면 참
if any(15>x for x in a):
    print('Yes')
else:
    print('No')

'''
#튜플
'''

b=(1, 2, 3, 4, 5)
print(b[0])
#b[0]=7 # 에러 튜플의 값은 변경 불가, 리스트의 값은 변경가능
#print(b[0])


'''

"""
'''
2차원 리스트 생성과 접근
'''

a= [0]*3
print(a)

a = [[0]*3 for _ in range(3)] # 크기가 3인 일차원 리스트 언더바는 변수없이 반복문만 돔 => 일차원 리스트 3번 만듦

a[0][1] = 2
print(a)
print()
#표처럼 출력
for x in a:
    print(x)

for x in a:
    for y in x:
        print(y, end =' ')

"""

'''
람다 함수 => 함수 이름이 없음
'''
'''

def plus_one(x):
    return x+1

print(plus_one(1))
'''

plust_two = lambda x: x+2

print(plust_two(1))


a = [1, 2, 3]
# map => 함수명, 자료 => 
def plus_one(x):
    return x+1

print(plus_one(1))

print(list(map(plus_one, a))) # a에 대해 plus one을 함

print(list(map(lambda x:x+1, a))) # a에 대해 plus one을 함
728x90
반응형

'공부 > 파이썬 알고리즘' 카테고리의 다른 글

문자열  (0) 2021.09.16
연결리스트  (0) 2021.09.15
배열  (0) 2021.09.15
etc  (0) 2021.07.01
파이썬 문법  (0) 2021.06.28
블로그 이미지

아상관없어

,
반응형

mysql연동위해 pymysql 설치

 

conda install pymysql

 

 

#mysql - python connection test

import pymysql #mysql과 연동하기 위해

#필요한 기본 DB 정보
host = "localhost"
user = "root"
pw = "XXXX"
db = "my_db"

#DB에 접속
conn = pymysql.connect(host= host, user = user, password = pw, db = db)

#사용할 sql문
sql = "SELECT * FROM emp LIMIT 10"

# sql문 실행/데이터 받기
curs = conn.cursor() #sql 실행시 결과를 담고 있는 버퍼를 정렬
curs.execute(sql)	#앞의 sql문 실행

data = curs.fetchall() #sql실행결과 모두 가져오기, fetchall 모든 행 가져옴, fetchone은 하나의 행만 가져옴
type(data)				#data 자료구조
data					#data 내용출력
data[0]					#첫번째 행
str(data[0][0])			#첫번째 행의 첫번째 컬럼

#db 접속 종료
curs.close()
conn.close()

sql = "SELECT * FROM emp LIMIT 10"

curs = conn.cursor()
curs.execute(sql)

row = curs.fetchone()
while(row):
	print(row)
    row = curs.fetchone()
    
# cursor는 한행씩 내려간다

 

 

GUI DB 프로그램

import sys
import pymysql
from PyQt5.QtWidgets import *

def connectDB():
    #필요한 db 정보
    host = "localhost"
    user = "root"
    pw = "Changmin97"
    db = "my_db"
    
    #db 접속
    conn = pymysql.connect(host=host, user =user, password =pw, db =db)
    return(conn)  #connection  리턴

def disconnectDB(conn):
    conn.close()
    
    

class MyApp(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()
        
    
    # UI 디자인 함수
    def initUI(self):
        #QLable 문자열 출력
        label1 = QLabel('ID')
        label2 = QLabel('ename')
        label3 = QLabel('job')
        label4 = QLabel('department')
    
    
        #self => 외부에서 접근 가능
        #text박스 생성 = QTextEdit
        self.text_id = QTextEdit()
        self.text_id.setFixedWidth(200)
        self.text_id.setFixedHeight(30)
    
    
        #버튼 생성, 버튼 클릭시 btn_1_clicked 실행
        btn_1 = QPushButton('Query')
        btn_1.clicked.connect(self.btn_1_clicked)
    
        #text박스 생성 = QTextEdit
        self.text_ename = QTextEdit()
        self.text_ename.setFixedWidth(200)
        self.text_ename.setFixedHeight(30)
    
        #text박스 생성 = QTextEdit
        self.text_job = QTextEdit()
        self.text_job.setFixedWidth(200)
        self.text_job.setFixedHeight(30)
    
        #text박스 생성 = QTextEdit
        self.text_dept = QTextEdit()
        self.text_dept.setFixedWidth(200)
        self.text_dept.setFixedHeight(30)
    
        #화면 배치, grid를 만들어 배치
        gbox = QGridLayout()
    
        gbox.addWidget(label1,0,0)
        gbox.addWidget(self.text_id, 0, 1)
            
        gbox.addWidget(btn_1, 0, 2)
            
        gbox.addWidget(label2,1,0)
        gbox.addWidget(self.text_ename, 1, 1)
            
        gbox.addWidget(label3,2,0)
        gbox.addWidget(self.text_job, 2, 1)
        
        gbox.addWidget(label4,3,0)
        gbox.addWidget(self.text_dept, 3, 1)
    

        self.setLayout(gbox)
        self.setWindowTitle('My Program')
        self.setGeometry(300, 300, 480,250) #창뜨는 위치, 크기
        self.show()
        
        
    #버튼 클릭 처리
    def btn_1_clicked(self):
    
        #사용자가 입력한 값 받아서 empno 저장
        empno = self.text_id.toPlainText()
            
        sql = "SELECT ename, job, danme \
                From emp e, dept d\
                where e.deptno = d.deptno\
                and empno = "+ empno
        #ex) ename '"+ename+"'" =>문자일 경우 따옴표 주의!
        conn = connectDB()
        curs = conn.cursor()
        curs.execute(sql)
            
        result = curs.fetchone() # sql 실행 결과 가져오기
            
        self.text_ename.setText(result[0])
        self.text_job.setText(result[1])
        self.text_dept.setText(restul[2])
            
        curs.close()
        disconnect(conn)
            
#END Class


#프로그램 실행, class를 생성하고 실행
if(__name__ == '__main__'):
    app = QApplication(sys.argv)
    ex = MyApp()
    sys.exit(app.exec_())            
    

 

ex 1) 

- 사원번호가 7521인 사원의 이름을 출력한다

- 이름이 SCOTT 인 사원의 부서이름을 출력한다

- 담당업무가 SALESMAN 인 모든사원의 이름을 출력한다.

- 모든 부서의 이름을 출력한다.

import pymysql #mysql과 연동하기 위해

#필요한 기본 DB 정보
host = "localhost"
user = "root"
pw = "Changmin97"
db = "my_db"

#DB에 접속
conn = pymysql.connect(host= host, user = user, password = pw, db = db)

#사용할 sql문
sql1 = "SELECT ename FROM emp WHERE empno=7521"
sql2 = "SELECT dname FROM emp, dept WHERE dept.deptno=emp.deptno and ename='scott'"
sql3 = "SELECT ename FROM emp WHERE job='salesman'"
sql4 = "SELECT dname FROM dept"

querys = [sql1, sql2, sql3, sql4]

for sql in querys:
    print(sql)
    
    # sql문 실행/데이터 받기
    curs = conn.cursor() #sql 실행시 결과를 담고 있는 버퍼를 정렬
    curs.execute(sql)	#앞의 sql문 실행 
    row = curs.fetchone() #sql실행결과 모두 가져오기, fetchall 모든 행 가져옴, fetchone은 하나의 행만 가져옴
    while(row):
        print(row)
        row	= curs.fetchone()	
        
    print("==========================================================")
    
#db 접속 종료
curs.close()
conn.close()

 

 

 

 

ex 2)

Mysql world 데이터베이스와 연동하여 다음과 같이 국가명을 입력하면 해당 국가의 정보를 출력하는 윈도우 프로그램을 작성하시오

- 매치되는 국가가 없으면 모든 항목에 공백 출력

import sys
import pymysql
from PyQt5.QtWidgets import *

def connectDB():
    #필요한 db 정보
    host = "localhost"
    user = "root"
    pw = "Changmin97"
    db = "world"
    
    #db 접속
    conn = pymysql.connect(host=host, user =user, password =pw, db =db)
    return(conn)  #connection  리턴

def disconnectDB(conn):
    conn.close()
    
    

class MyApp(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()
        
    
    # UI 디자인 함수
    def initUI(self):
        #QLable 문자열 출력
        label1 = QLabel('Country name')
        label2 = QLabel('Continent')
        label3 = QLabel('Population')
        label4 = QLabel('GNP')
        label5 = QLabel('Captial city')
        label6 = QLabel('Language')
    
    

        #text_Country_name
        self.text_Country_name = QTextEdit()
        self.text_Country_name.setFixedWidth(200)
        self.text_Country_name.setFixedHeight(30)
    
    
        #버튼 생성, 버튼 클릭시 btn_1_clicked 실행
        btn_1 = QPushButton('Query')
        btn_1.clicked.connect(self.btn_1_clicked)
    
        #text_Continent
        self.text_Continent = QTextEdit()
        self.text_Continent.setFixedWidth(200)
        self.text_Continent.setFixedHeight(30)
    
        #text_Population
        self.text_Population = QTextEdit()
        self.text_Population.setFixedWidth(200)
        self.text_Population.setFixedHeight(30)
    
        #text_GNP
        self.text_GNP = QTextEdit()
        self.text_GNP.setFixedWidth(200)
        self.text_GNP.setFixedHeight(30)
        
        #text_Captial_city
        self.text_Captial_city = QTextEdit()
        self.text_Captial_city.setFixedWidth(200)
        self.text_Captial_city.setFixedHeight(30)
        
          #text_Language
        self.text_Language = QTextEdit()
        self.text_Language.setFixedWidth(200)
        self.text_Language.setFixedHeight(30)
        
        
        
    
        #화면 배치, grid를 만들어 배치
        gbox = QGridLayout()
    
        gbox.addWidget(label1,0,0)
        gbox.addWidget(self.text_Country_name, 0, 1)
            
        gbox.addWidget(btn_1, 0, 2)
            
        gbox.addWidget(label2,1,0)
        gbox.addWidget(self.text_Continent, 1, 1)
            
        gbox.addWidget(label3,2,0)
        gbox.addWidget(self.text_Population, 2, 1)
        
        gbox.addWidget(label4,3,0)
        gbox.addWidget(self.text_GNP, 3, 1)
        
        gbox.addWidget(label5,4,0)
        gbox.addWidget(self.text_Captial_city, 4, 1)
        
        gbox.addWidget(label6,5,0)
        gbox.addWidget(self.text_Language, 5, 1)
    

        self.setLayout(gbox)
        self.setWindowTitle('Country Info')
        self.setGeometry(300, 300, 480,250) #창뜨는 위치, 크기
        self.show()
        
        
    #버튼 클릭 처리
        def btn_1_clicked(self):
    
        #사용자가 입력한 값 받아 저장
        Country_name = self.text_Country_name.toPlainText()
            
        sql = "SELECT country.name, continent, country.population, gnp, city.name, language \
                From country, city, countrylanguage\
                where country.code = city.countrycode \
                    and country.code = countrylanguage.countrycode\
                    and country.capital=city.id\
                    and IsOfficial = 'T' \
                    and country.name ="+"'"+Country_name+"'"
        #ex) ename '"+ename+"'" =>문자일 경우 따옴표 주의!
        conn = connectDB()
        curs = conn.cursor()
        curs.execute(sql)
            
        result = curs.fetchone() # sql 실행 결과 가져오기

        if result:    
            self.text_Country_name.setText(result[0])
            self.text_Continent.setText(result[1])
            self.text_Population.setText(str(result[2]))
            self.text_GNP.setText(str(result[3]))
            self.text_Captial_city.setText(result[4])
            self.text_Language.setText(result[5])
        else:
            self.text_Country_name.setText("") #매치되는 국가가 없으면 모든 항목에 공백 출력
            
            
        curs.close()
        disconnect(conn)
            
#END Class


#프로그램 실행, class를 생성하고 실행
if(__name__ == '__main__'):
    app = QApplication(sys.argv)
    ex = MyApp()
    sys.exit(app.exec_())            
    	

728x90
반응형

'공부 > 데이터베이스' 카테고리의 다른 글

index  (0) 2021.06.02
데이터 베이스 보안  (0) 2021.06.02
저장 함수 예제  (0) 2021.05.15
저장 프로시저 예제  (0) 2021.05.15
뷰 예제  (0) 2021.05.15
블로그 이미지

아상관없어

,