1. 암호화 / 복호화에 대한 정리
암호화(Encryption): 평문 데이터를 인가되지 않은 사람이 읽지 못하도록 암호화된(암호문) 형태로 변환하는 과정
복호화(Decryption): 암호화된 데이터를 다시 원래의 평문 데이터로 되돌리는 과정
2. Flutter에서 지원하는 암호화 알고리즘
알고리즘 | 특징 |
AES | 정부, 금융기관 등에서 널리 사용하는 대칭키(비밀키) 암호화 방식. 빠르고 안전함. |
Fernet | 대칭키 방식. 128비트 AES CBC 모드와 HMAC-SHA256 인증을 결합하여 데이터 변조 방지. |
Salsa20 | 스트림 암호화 방식. 빠르고 안전하며, 다양한 분야에서 사용됨. |
3. Flutter에서 구현
1) encrypt 패키지 설치
# pubspec.yaml
encrypt: ^5.0.3 # 현 시점 최신버전
2) 사용하는 코드에서 import
import 'package:encrypt/encrypt.dart';
3) 예제코드 구현
import 'package:encrypt/encrypt.dart';
class EncryptData {
static Encrypted? aesEncrypted;
static String? aesDecrypted;
// AES 암호화
static void encryptAES(String plainText) {
final key = Key.fromUtf8('my 32 length key................'); // 32바이트 키
final iv = IV.fromLength(16); // 16바이트 IV
final encrypter = Encrypter(AES(key));
aesEncrypted = encrypter.encrypt(plainText, iv: iv);
print(aesEncrypted!.base64); // 암호문 출력
}
// AES 복호화
static void decryptAES(String plainText) {
final key = Key.fromUtf8('my 32 length key................');
final iv = IV.fromLength(16);
final encrypter = Encrypter(AES(key));
aesDecrypted = encrypter.decrypt(aesEncrypted!, iv: iv);
print(aesDecrypted); // 복호화된 평문 출력
}
}
- Key: 32바이트(256비트) 길이의 문자열이어야 AES-256이 정상 동작한다.
- IV(초기화 벡터): 16바이트 길이로 지정한다.
- 암호화된 데이터는 base64 형태로 출력된다.
4) Fernet 암호화/복호화 예제
import 'package:encrypt/encrypt.dart';
import 'dart:convert';
void main() {
final plainText = '암호화할 평문 데이터';
// 32바이트 길이의 키를 생성
final key = Key.fromUtf8('my32lengthsupersecretnooneknows1');
// Fernet은 base64 인코딩된 키를 사용해야 함
final b64key = Key.fromUtf8(base64Url.encode(key.bytes).substring(0,32));
// Fernet 알고리즘 객체 생성
final fernet = Fernet(b64key);
// Encrypter 객체 생성
final encrypter = Encrypter(fernet);
// 암호화
final encrypted = encrypter.encrypt(plainText);
print('암호문(base64): ${encrypted.base64}');
// 복호화
final decrypted = encrypter.decrypt(encrypted);
print('복호화된 평문: $decrypted');
// 암호화된 데이터의 타임스탬프 추출
print('타임스탬프: ${fernet.extractTimestamp(encrypted.bytes)}');
}
- Fernet은 AES-128 CBC + HMAC-SHA256 조합으로, 키를 base64로 인코딩하여 사용한다.
- 사용법은 AES와 유사하며, 암호화/복호화 시 별도의 Fernet 객체를 생성한다.
5) Salsa20 암호화/복호화 예제
import 'package:encrypt/encrypt.dart';
void main() {
final plainText = '암호화할 평문 데이터';
// 32바이트 길이의 랜덤 키와 8바이트 IV 생성
final key = Key.fromSecureRandom(32);
final iv = IV.fromSecureRandom(8);
// Salsa20 알고리즘 객체 생성
final encrypter = Encrypter(Salsa20(key));
// 암호화
final encrypted = encrypter.encrypt(plainText, iv: iv);
print('암호문(base64): ${encrypted.base64}');
// 복호화
final decrypted = encrypter.decrypt(encrypted, iv: iv);
print('복호화된 평문: $decrypted');
// 암호화된 데이터의 바이트, base16, base64 출력
print('암호문(bytes): ${encrypted.bytes}');
print('암호문(base16): ${encrypted.base16}');
}
- Salsa20은 스트림 암호화 방식으로, 대용량 데이터나 실시간 암호화에 적합합니다.
- 사용법은 AES와 비슷하나, 알고리즘 객체만 변경하면 됩니다.
4. 주의사항
- Key와 IV는 반드시 동일해야 복호화가 제대로 동작한다.
- Key 길이가 16, 24, 32바이트 중 하나여야 하며, 그렇지 않으면 오류가 발생한다.
- 암호화/복호화에 사용하는 알고리즘, 키, IV는 반드시 보안에 유의해서 관리해야 한다.
- 실제 서비스에서는 키와 IV를 코드에 하드코딩하지 않고, 안전한 저장소(예: 환경변수, secure storage 등)에 보관하는 것이 좋습니다. 개인적으로는 .env를 주로 사용하고 있다. (https://honken.tistory.com/168 참고)
5. 결론
Flutter에서 데이터 암호화와 복호화는 encrypt 패키지를 이용해 손쉽게 구현할 수 있으며, AES, Fernet, Salsa20 등 다양한 알고리즘을 지원하므로, 서비스 특성에 맞게 선택하여 사용할 수 있다. 앱의 민감 정보 보호와 네트워크 보안을 위해 반드시 암호화/복호화 기능을 적용하는 것이 권장한다.
'Personal Posting > Flutter' 카테고리의 다른 글
Extension Method in Dart (0) | 2025.05.22 |
---|---|
Flutter에서의 Permission Handler 사용 (1) | 2025.05.21 |
Dart의 Event Loop 정리 (0) | 2025.04.03 |
Flutter TextFormFields 사용 시 체크사항 (0) | 2025.04.03 |
Dart 프로그래밍에서의 애노테이션(Annotations) (0) | 2025.01.07 |