본문 바로가기

알고리즘 & 자료구조/암호화 알고리즘

[암호학] 단일치환 암호_곱셈 암호

  • 곱셈 암호(Multiplicative Cipher) 

      - 문자에 일정한 수(Key)를 곱해서 암호를 생성하는 방식

  • 모듈러 연산 (Modular Arithmetic)

      -  모듈러 연산 "mod n" 에서 모듈러 곱셈이 역원을 갖기 위한 조건은 모듈러스 n과 서로소인 수만 역원을 가질 수 있               다.

      - 알파벳의 경우 mod 26 인 집합  Z26 = {0, 1, 2...25} 에서 26과 임의의 수 K의 최대공약수가 1이되면 이들은 서로소가         되고 K는 모듈러 곱셈의 역원을 갖게 된다. 

       즉, 1, 3, 5, 7, 9, 11, 15,17,19, 21,23, 25 를  Key 로 사용할 수 있다. 

 

 /// <summary>
    /// 곱셈 암호
    /// </summary>
    public class MultiCipher
    {
        public static string Encrypt(string message, int key)
        {
            char[] a = message.ToCharArray();

            for (int i = 0; i < a.Length; i++) {
                if (!char.IsWhiteSpace(a[i])) {
                    a[i] = (char)('A' + ((a[i] - 'A') * key) % 26);

                }
            }

            return new string(a);
        }

        public static string Decrypt(string cipher, int key) {
            char[] a = cipher.ToCharArray();

            //곱셈 역원 계산
            int? inverseKey = null;

            try {
                inverseKey = GetMultiplicativeInverse(key);

                if (inverseKey != null) {
                    for (int i = 0; i < a.Length; i++) {
                        if (!char.IsWhiteSpace(a[i])) {
                            a[i] = (char)('A' + ((a[i] - 'A') * inverseKey) % 26);
                        }
                    }
                }

            } catch 
            { 
                
            }
                           
            return new string(a);
        }

        private static int GetMultiplicativeInverse(int key) {
            // 1~25 까지 순차적으로 대입
            for (int i = 0; i < 26; i++) {
                if ((key * i) % 26 == 1) {
                    return i;
                }
            }

            throw new InvalidOperationException();           
        }

        internal static void HowToTest()
        {
            string message = "ATTACK WEST CASTLE".ToUpper();
            var caesar = new CaesarCipher();
            string cipher = caesar.Encrypt(message);
            string plain = caesar.Decrypt(cipher);

            Console.WriteLine($"{message},{cipher},{plain}");
            Debug.Assert(message == plain);

        }

    }

- 메인메서드

  static void Main(string[] args)
        {
            // 시저 암호
            CaesarCipher caesarCipher = new CaesarCipher();
            var encryptStr = caesarCipher.Encrypt("HELLO");
            var decryptStr = caesarCipher.Decrypt(encryptStr);

            Console.WriteLine("Caesar 암호화:" + encryptStr);
            Console.WriteLine("Caesar 복호화:" + decryptStr);

            var encryptRot13Str = ROT13Cipher.Encrypt("HELLO");
            var decryptRot13Str = ROT13Cipher.Decrypt(encryptStr);

            RandomCipher randomCipher = new RandomCipher();
            Console.WriteLine("ROT13 암호화:" + encryptRot13Str);
            Console.WriteLine("ROT13 복호화:" + decryptRot13Str);

            var encryptRandomStr = randomCipher.Encrypt("HELLO");
            var decryptRandomStr = randomCipher.Decrypt(encryptStr);

            Console.WriteLine("Random 암호화:" + encryptRandomStr);
            Console.WriteLine("Random 복호화:" + decryptRandomStr);

            var encryptMulti = MultiCipher.Encrypt("HELLO", 12);
            var decryptMulti = MultiCipher.Decrypt(encryptStr, 12);

            Console.WriteLine("곱셈 암호화:" + encryptMulti);
            Console.WriteLine("곱셈 복호화:" + decryptMulti);
        }

 

- 결과

 

    static void Main(string[] args)
        {
            // 시저 암호
            CaesarCipher caesarCipher = new CaesarCipher();
            var encryptStr = caesarCipher.Encrypt("HELLO");
            var decryptStr = caesarCipher.Decrypt(encryptStr);

            Console.WriteLine("Caesar 암호화:" + encryptStr);
            Console.WriteLine("Caesar 복호화:" + decryptStr);

            var encryptRot13Str = ROT13Cipher.Encrypt("HELLO");
            var decryptRot13Str = ROT13Cipher.Decrypt(encryptRot13Str);

            RandomCipher randomCipher = new RandomCipher();
            Console.WriteLine("ROT13 암호화:" + encryptRot13Str);
            Console.WriteLine("ROT13 복호화:" + decryptRot13Str);

            var encryptRandomStr = randomCipher.Encrypt("HELLO");
            var decryptRandomStr = randomCipher.Decrypt(encryptRandomStr);

            Console.WriteLine("Random 암호화:" + encryptRandomStr);
            Console.WriteLine("Random 복호화:" + decryptRandomStr);

            var encryptMulti = MultiCipher.Encrypt("HELLO", 3);
            var decryptMulti = MultiCipher.Decrypt(encryptMulti, 3);

            Console.WriteLine("곱셈 암호화:" + encryptMulti);
            Console.WriteLine("곱셈 복호화:" + decryptMulti);
        }

- 결과