본문 바로가기
지난 학기들의 기록/C 기초

[C실습] 함수 예제 - 시저암호화 및 복호화(Caesar cipher,카이사르 암호)+수정(파이썬코드 추가)

by 아메리카노와떡볶이 2020. 6. 1.
728x90
함수예제 - 시저 암호화 및 복호화 ( Caesar cipher, 카이사르 암호)

이번 포스트에서는 대표적인 암호학 예제인 시저암호를 C언어와 파이썬으로 구현해보겠습니다.

문제는 다음과 같습니다.

아이디어 생각하기

문자형 배열에서 자주 등장하는 문제입니다. 아스키코드표에서 대문자와 소문자 범위는 정해져있는데

M을 입력받아 M칸을 이동한 알파벳을 출력하는 것입니다 . 예시로 들면 apple 라는 문자열이 주어졌을때

3칸씩 이동시키게 되면 d s s o h 가 출력되게 되는것입니다. 여기서 주의해야할 점을 말하자면 M칸씩 이동시켰는데

z를 넘어버리면 다시 a로 돌아와야합니다. 위의 알고리즘을 소문자,대문자에 적용하여

암호화 함수 encrypt와 복호화 함수 decrypt를 구현합니다.

 

먼저 코드 작성전에 앞서말한 다음과 같은 사항을 고민해봅니다.

encrypt함수에서 문자char형 변수 ch가 있을때 ch에서 M칸을 이동했는데 M값이 커서 ch+M이 'z'를 넘어버릴수있습니다.

이때 'a'로 되돌아간뒤 거기서 다시 추가되어야합니다. 

y에서 3 일 경우 y > z > a >b 과정을 거쳐 b가 출력되어야합니다. 이것을 어떻게 구현해야할까요?

간단하게 생각해보면 쉬운 내용입니다 . 

ch+M 이 'z'를 넘었을때 ==> if(ch+M>'z')

변수 ch가 소문자라는 가정하에 ch-'z'는 ch가 'z'를 기준으로 몇칸 떨어져있는지 나타냅니다.

ch-'z'에 +M을 해주면 몇칸이동을 해야하는지 구할수있습니다. 그 값을 'a'에 더해주게되면 완성입니다

result= 'a'+( ch-'z'+M) -1 //  'a'도 'z'다음으로 넘어가는 카운트가 있어야하는데 'a'를 기준으로 잡았으므로 -1을 해주어야합니다.

 

위의 사항은 복호화 함수인 decrypt함수에도 그대로 적용됩니다 . 만약 M칸을 이동했는데 'a'보다 작아진다면 ? 다시 'z'로 되돌아가야합니다

if(ch-M<'a') ??? 

위와 마찬가지 아이디어로

ch-'a'-M 값이 몇칸을 이동해야하는지 값이고, 'z'에 그 값을 더해주면 완성입니다

result= 'z' + (ch-'a'-M)+1

 

그리고 다음 고려해야할 사항은 M이 지나치게 큰수가 입력될 경우입니다. 알파벳은 26글자로 이루어져있기때문에 1과 27은 같은 출력값을 나타낼것입니다.

이 내용을 코드로 그대로 구현하게 되면 M=M%26 입니다.

 

시저 암호화 및 복호화 - C language

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#pragma warning(disable:4996)
#include <stdio.h>
 
char decrypt(char ch, int M);
char encrypt(char ch, int M);
 
int main() {
    char ch_array[100], origin_array[100= { 0 };
char decrypted_char = '0', encrypted_char = '0';
    int M1, M2, i;
    for (i = 0; ; i++) {
        scanf("%c"&ch_array[i]);
        if (ch_array[i] == '*'break;
    }
    scanf("%d %d"&M1, &M2);
    for (int p = 0; p < i; p++) {
        origin_array[p] = decrypt(ch_array[p], M1);
        printf("%c", origin_array[p]);
    } // 복호화함수실행과 복호화한 문자 출력파트
 
    puts("");
    for (int p = 0; p < i; p++) {
        ch_array[p] = encrypt(origin_array[p], M2);
        printf("%c", ch_array[p]);
    }// 암호화함수실행과 암호화한 문자 출력파트
}
char decrypt(char ch, int M)
{
    int i, j, k;
    char result = '0';
    if ('a' <= ch && ch <= 'z') {
        M = M % 26;
        if ((ch - M) < ('a')) { 
            result = 'z' + (ch - 'a' - M) + 1;
            return result; //결과값 반환
        }
        else {//'a'를 넘어가지않는다면 그대로 출력
            result = ch - M;
            return result;//결과값 반환
        }
    }
    else if ('A' <= ch && ch <= 'Z') {
        M = M % 26;
        if ((ch - M) < 'A') {//'A'를 넘어간다면
            result = 'Z' + (ch - 'A' - M) + 1;.
            return result;//결과값 반환
        }
        else {//'A'를 넘어가지않는다면 그대로 반환
            result = ch - M;
            return result;//결과값 반환
        }
    }
    else return ch; // ch가 알파벳문자가 아닐경우 그냥 ch반환
}
char encrypt(char ch, int M) {
    char result = '0';
    if ('a' <= ch && ch <= 'z') {//ch가 소문자일경우
        M = M % 26;
        if (ch + M > 'z') {
            result = 'a' + (ch - 'z' + M) - 1;
        }
        else return ch + M;
    }
    else if ('A' <= ch && ch <= 'Z') {//ch가 대문자일경우
        M = M % 26;
        if (ch + M > 'Z') {
            result = 'A' + (ch - 'Z' + M) - 1;
            return result;//결과값 반환
        }
        else return ch + M;
    }
    else return ch;// ch가 알파벳문자가 아닐경우 그냥 ch반환
 
}
cs

시저 암호화 및 복호화 - Python

파이썬 코드를 추가했습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def caesar(s,n):
    s=list(s)
    n1=n%26
    for i in range(len(s)):
 
        if s[i].isupper():#대문자이면
            if ord(s[i])+n1 > ord('Z'):
                s[i] =chr(ord('A')+ ord(s[i])-ord('Z')+n1-1)
            else:
                s[i]=chr(ord(s[i])+n1)
        elif s[i].islower(): #소문자이면
            if ord(s[i])+n1 > ord('z'):
                s[i]=chr(ord('a'+ ord(s[i])-ord('z')+n1-1)
            else:
                s[i]=chr(ord(s[i])+n1)
    return s
#출력확인용 예시입니다.
s1="bluescreen"
(caesar(s1,20))
cs

 

 

728x90

댓글