본문 바로가기

Algorithm/암호화 알고리즘

[암호학] 단일치환 암호_Affine 암호

Affine 암호

  • 곱셈 암호와 덧셈 암호를 병합하여 구현한 것으로 2개의 Key를 갖는다. 
  • 첫번째 Key는 곱셈 암호의 키로서 역원을 갖는 곱셈 암호의 키 집합인 Z26*의 요소이고, 두번째 Key는 덧셈 암호의 키로서 알파벳 집합 Z26의 요소이다. 

       C = (K1 * P + K2) mod 26

       f(x) = (a * x + b) % 26 => 기울기가 a 이고, y 절편이 b인 직선의 방정식 또는 일차 함수

 

  • Affine 암호식은 다음과 같은 3가지 조건을 가진다. 

      1) 곱셈 암호키 a(K1)는 곱셈에 대한 역원을 가져야 하므로 26과 서로소이어야 한다. gcd(a,26) = 1

      2) a는 0이 아니어야 하고, 1~25 사이의 값이다

      3) b는 0 ~25 사이의 값이다.

 

   public class AffineCipher
    {
        private int k1;
        private int k2;

        public AffineCipher(int k1, int k2) {
            this.k1 = k1;
            this.k2 = k2;
        }

        //Affine 암호화
        public string Encrypt(string message)
        {
            char[] a = message.ToCharArray();

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

            return new string(a);
        
        }

        //Affine 복호화
        public string Decrypt(string cipher)
        {
            char[] a = cipher.ToCharArray();
            
            //곱셈 역원을 계산
            int k1_inverse = Enumerable.Range(1, 25).Single(i =>(k1 * i) % 26 == 1);

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

            return new string(a);
        }

        internal static void HowToTest()
        {
            var affine = new AffineCipher(7, 5);

            string message = "ATTACK WEST CASTLE".ToUpper();
            var caesar = new CaesarCipher();
            string cipher = affine.Encrypt(message);
            string plain = affine.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(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);

            var affine = new AffineCipher(7, 5);
            var encryptAffine = affine.Encrypt("HELLO");
            var decryptAffine = affine.Decrypt(encryptAffine);

            Console.WriteLine("아핀 암호화:" + encryptAffine);
            Console.WriteLine("아핀 복호화:" + decryptAffine);

        }

 

결과