🐦 Flutter

AES-256 암호화

ji-hyun 2023. 4. 1. 11:58

회사 프로젝트에서 AES-256 암호화 방식을 사용하여 다른 업체와 유저 정보를 주고 받아야 하는 업무가 있었다

 

 

 

좀 더 자세히 말하자면 다음과 같은 과정이 진행되어야 했다

 

Client : 유저 정보를 AES-256 암호화하여 @@업체의 url 의 parameter 에 포함시켜 웹뷰로 띄움

@@업체 : 유저의 액션을 받을 시, 유저의 정보를 우리 Backand 에 request parameter 에 담아서 전달 (유저의 정보는 Client -> @@업체 -> 백엔드 이렇게 넘어가게 된다는 뜻)
Backand : @@업체에서 받은 유저 정보를 AES-256 복호화하여 유저의 정보를 파악 가능

 

 

 

 

 

업체의 요구사항은 다음과 같다

 

UserKey 값은 매체사 회원의 개인정보 및 중요한 회원정보 값이 그대로 넘어오는 것을 권장하지 않습니다. 반드시 AES-256(Base64)으로 암호화 후 전달 부탁드립니다

 

그래서 업체는 우리의 회원 정보를 알 수 없는 것이다.

즉, 안전하게 Client 와 Backand 가 유저의 정보를 주고 받을 수 있다.

 

 

 

 

 

그래.. 그럼 AES-256 방식으로 암호화 하자!! 라고 생각했는데

다른 암호화 방식과 어떤 점이 다른 건지 궁금해서 찾아보았고 이를 기록을 해두고 싶어서 포스팅 해본다.

 

 

 

암호화 방식에는 단방향 암호화 알고리즘과 양방향 암호화 알고리즘이 존재한다.

그럼 이 둘의 차이점이 뭘까

 

 

 

 

 

 

 

단방향 암호화 알고리즘과 양방향 암호화 알고리즘 차이점

  • 단방향 암호화 알고리즘 : 평문을 암호화했을 때 다시 평문으로 되돌리는 것(복호화)을 할 수 없는 암호화 방식으로 패스워드 암호화에 사용되며 대표적으로 SHA-256 가 있습니다

  • 양방향 암호화 알고리즘 : 평문에서 암호문으로, 암호문에서 평문으로 변환할 수 있는 방식으로 대표적으로 아래에서 쌀펴볼 AES-256 이 있습니다

 

그래서 우리는 양방향 암호화 알고리즘을 사용하는 것이었다.

그럼 이 중에서도 여러가지 암호화 방식이 있는데 AES 암호화 방식은 무엇일까

 

 

 

 

 

 

 

 

 

'AES(Advanced Encryption Standard) 고급 암호화 표준'

AES는 암호화 및 복호화에 동일한 키를 사용하는 대칭키 알고리즘으로 높은 안전성과 빠른 속도로 인해 양방향 암호화에서 가장 많이 사용되는 방식이다. AES 암호화의 종류는 AES-128, AES-192, AES-256이 있으며 뒤에 붙은 숫자는 키의 길이를 의미한다.

(128bit = 16byte, 192bit = 24byte, 256bit = 32byte)

 

* 대칭키(Symmetric Key)는 암호화하고 복호화 하는데 사용되는 키가 동일한 것임을 의미하며, 반대로 비대칭키(Asymmetric Key)는 암호화와 복호화에 각각 다른 키가 사용되는 것이다.

 

 

 

그래서 Client 와 backand 는 같은 키를 사용해서 Client 는 암호화를, backand 는 복호화하는 것이다.

그러므로 키를 서로 합의해서 공유해야 한다.

 

 

(AES-256 암호화 방식을 이용할거니까, 키의 길이는 32byte 라는거~ )

 

 

 

 

 

 

 

 

 

 

AES-256 사용 방법

다음은 암호화, 복호화 예시이다

 

암호화 : 'plain text  ->  pain bytes  ->  encrypt  ->  encrypted bytes  ->  encrypted base64 test'
복호화 : 'encrypted base64 text  ->  encrypted bytes  ->  decrypt  ->  plain bytes  ->  plain text' 

base64 로 전달하는 까닭은 아래 포스팅에 정리해두었다

2023.04.01 - [💻 컴퓨터 개론] - Base64 인코딩

 

 

 

⭐️ AES 암호화에는 아래 네가지가 꼭 필요하다

SecretKey,  IV(Initialize Vector),  Cipher Mode(EBC/CBC/...),  Padding Mode(PKCS5/PKCS7/...)

 

패딩(padding)이란, 블록의 암호화를 진행하기 위해 필요한 기법으로

데이터를 특정 크기로 맞추기 위해서 사용되며, 특정 크기보다 부족한 부분의 공간을 의미 없는 문자들로 채워서 비트수를 맞추는 것이다. (암호화 시에는 반드시 필요)

 

 

 

 

 

 

 

Cipher Mode 란?

Cipher Mode(암호화 모드)는 암호화 과정에서 사용되는 알고리즘에서 데이터를 처리하는 방법을 지정하는 방식이다.

암호화 알고리즘은 일반적으로 블록 암호화(block cipher) 방식으로 동작한다. 블록 암호화 방식은 입력된 데이터를 고정된 길이의 블록(block) 단위로 나누어서 처리한다.

예를 들어, 64비트 블록 크기를 가진 블록 암호화 알고리즘은 64비트 크기의 블록 단위로 데이터를 처리한다.

 

Cipher Mode는 이러한 블록 암호화 알고리즘에서 각 블록을 어떤 순서로 암호화하고 연결하는지를 결정한다.

암호화된 블록은 다음 블록의 암호화에 사용된다. Cipher Mode는 이러한 블록 암호화 과정에서 데이터의 보안성, 무결성, 인증 등을 보장하는 역할을 한다.

 

 

 

 

 

Cipher Mode 의 종류

Cipher Mode에는 다양한 종류가 있으며, 대표적으로 ECB(Electronic Codebook), CBC(Cipher Block Chaining), CTR(Counter), OFB(Output Feedback), CFB(Cipher Feedback) 등이 있다. 각 Cipher Mode는 고유한 특징을 가지고 있으며, 암호화 알고리즘과 함께 적절하게 선택하여 사용해야 한다.

 

 

 

 

CBC 방식 

나는 프로젝트에서 CBC 방식을 사용했고 보통 이걸 많이 사용하는 것 같았다.

 

AES/CBC 방식의 경우 128bit의 고정된 블록 단위로 암호화를 수행하게 되는데, CBC mode는 위 이미지에서 볼 수 있는 것처럼 이전에 암호화했던 블록화 XOR 연산을 한 다음에 암호화를 수행한다.

그런데 첫 블록은 이전 암호화가 없기 때문에 이를 위해 IV(초기화 벡터)를 이용한다. AES는 128bit(16byte) 단위로 암호화하기 때문에 IV도 16byte의 크기가 필요하다.

 

 

IV 란?
IV(Initialize Vector), 초기화 벡터입니다. 
위와 같은 원리로 매번 다른 IV를 생성하면 같은 평문이라도 다른 암호문을 생성할 수 있습니다. 또한 IV는 암호를 복호화할 사람에게 미리 제공되어야 하고 키와 달리 공개되어도 상관없습니다.
(미리 송신자와 수신자가 IV를 어떤 것으로 사용할지 정해두거나 파일에 IV를 기록해두는 방식으로 공유합니다.)

 

 

 

 

 

 

 

 

AES-256 암호화 방식도 IV 크기가 16byte 인걸까? 왜??

맞다.

AES-256 암호화 방식에서 블록 크기는 128비트(16바이트)이다.

AES-256은 256비트(32바이트)의 키를 사용하므로, 입력된 데이터를 256비트로 암호화하는 것이 아니라, 128비트씩 블록으로 나누어 16바이트 단위로 암호화한다.

 

 

 

블록 크기가 128 비트인 까닭은 뭘까?

블록 크기가 128비트인 이유는

AES가 Rijndael 알고리즘에서 발전하여 128비트 블록 크기를 사용하는 AES-128이 가장 보편적으로 사용되고 있고, 이를 그대로 유지하면서 키 크기만 늘린 것이 AES-256이기 때문이다.

 

128비트 블록 크기는 보안성과 속도 간의 균형을 맞춘 크기로 여겨지고 있다.

 

 

 

 

 

 

 

 

** 정리

따라서 정리해보면

AES-256 암호화 방식은 블록 단위로 암호화를 하는 방식이다.

이때 이전 암호화 값을 바탕으로 블록화 XOR 연산을 한 다음, 암호화를 수행한다.

근데 여기서 처음에는 이전 암호화 값이 존재하지 않는다. 여기서 필요하게 되는 값이 IV 값 (초기화 벡터)인  것이다.

 

IV 값은 16 byte 이어야 하는데 그 이유는 AES 암호화 방식은 키 길이에 상관 없이 블록이 128 비트 단위이다.

(128 비트는 16 byte 이다.)

그래서 AES-256 암호화는 키 길이는 32 바이트, IV 값은 16 바이트여야 한다

(256은 키 길이를 나타낸다고 했다. = 32바이트)

 

 

 

 

 

 

 

 

❗️ AES-256 적용

다음은 내가 프로젝트에서 썼던 코드이다.

키와 IV 는 임의의 값이다. 키와 IV 값은 Client 와 backand 가 서로 공유해야 암호화, 복호화된 값이 일치하여 유저 정보를 확인할 수 있다.

 

 

[Dart]

 

  String aes256(String userKey) {
    final key = Key.fromUtf8('a00aa00000aaaaaaafdfdfdf98989889'); // 키 길이 - 32 byte
    final iv = IV.fromUtf8('aa00aaaa00aadfff'); // IV - 16 byte

    final encrypter = Encrypter(AES(key, mode: AESMode.cbc)); // cbc 모드 사용

    final encrypted = encrypter.encrypt(userKey, iv: iv); // 암호화
    final decrypted = encrypter.decrypt(encrypted, iv: iv); // 복호화

    print(decrypted);
    print(encrypted.base64);

    return encrypted.base64; // base64 인코딩 상태로 전달
  }