Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions 008. KeyStore System and Security/Part0_KeywordList.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# 암호학 (Cryptography, Cryptology)

정보를 보호하기 위한 언어학적 및 수학적 방법론을 다루는 학문으로, 수학을 중심으로 컴퓨터, 통신 등 여러 학문 분야에서 공동으로 연구, 개발되고 있다. 현대 암호학은 암호 시스템, 암호 분석, 인증 및 전자 서명 등을 주요 분야로 포함한다.

암호학을 이용해 보호해야 할 메시지를 **평문(plaintext)**라 하며, 평문을 암호학적 방법으로 변환하는 것을 **암호문(ciphertext)**라고 한다. 이 때 평문을 암호문으로 변환하는 과정을 **암호화(Encryption)**이라 하며, 암호문을 다시 평문으로 변환하는 과정을 **복호화(Decryption)**이라 한다.

### Symmetric key (대칭키)

암호화할 때와 복호화할 때 사용하는 키가 동일한 암호 시스템이다. 그렇기에 당연히 키의 안전한 관리에 상대적으로 의존성이 높다. 암호문의 작성자와 수신자가 동일한 키를 **비밀리에 관리**해야 하므로 폐쇄적인 특성을 갖는 곳에 적합한 암호 시스템이다.

하지만, 시스템에 가입한 사용자들는 작성자와 수신자끼리 같은 키를 공유해야 하기에, 각 사용자끼리 n-1개의 키를 관리해야 하는 부담이 있다.(2명일 경우 1개의 키, 3명일 경우 각각 2개의 키... 이므로, n(n-1)/2 개의 키가 필요) 그렇기에 키 관리가 상대적으로 용이한 **공개키 암호 시스템(= 비대칭 키)**이 나타났다.

암호화하는 단위에 따라 스트림 암호(Stream cipher)와 블록 암호(Block cipher)로 나눌 수 있다.

스트림 암호는 연속적인 비트/바이트를 계속해서 입력받아, 그에 대응하는 암호화 비트/바이트를 생성하는 방식이다. 자세한 사항은 [해당 url](https://ko.wikipedia.org/wiki/%EC%8A%A4%ED%8A%B8%EB%A6%BC_%EC%95%94%ED%98%B8)을 참고하자.

**블록 암호(Block cipher)**는 *기밀성있는 정보를 정해진 블록 단위로 암호화하는 대칭키 암호 시스템이다. 해당 구조에는 Feistel과 SPN구조가 있다.

- Feistel : 암복호화 과정에서 역함수가 필요 없다는 장점이 있지만, 구현 시 swap 단계 때문에 연산량이 많이 소요되며, 암호에 사용되는 *라운드 함수를 안전하게 설계해야 한다는 단점이 있다. 대표적으론 DES가 있으며, Single DES는 안정성 문제로 사용되고 있지 않다. 한국에선 SEED 암호가 있다.
- SPN : 암복호화 과정에서 역함수가 필요하도록 설계해야 하는 단점이 있지만, 중간에 비트 이동 없이 한 번에 암복호화가 가능하기에 Feistel보다 효율적이라고 말할 수 있다. 대표적으론 AES가 있으며 널리 상용되고 있다.

**대칭키(비밀키) 암호 시스템 종류**

- [DES (Data Encryption Standard)](https://ko.wikipedia.org/wiki/%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%95%94%ED%98%B8%ED%99%94_%ED%91%9C%EC%A4%80)
- [AES (Advanced Encryption Standard)](https://ko.wikipedia.org/wiki/%EA%B3%A0%EA%B8%89_%EC%95%94%ED%98%B8%ED%99%94_%ED%91%9C%EC%A4%80)
- [ARIA](https://ko.wikipedia.org/wiki/%EC%95%84%EB%A6%AC%EC%95%84_(%EC%95%94%ED%98%B8))
- [SEED](https://ko.wikipedia.org/wiki/SEED)

### Asymmetric Key (비대칭 키)

대칭키 암호 시스템의 약점인 키의 수로 인한 관리의 어려움을 보완하기 위한 시스템으로, 각 사용자는 2개의 키를 부여 받는다. 하나는 공개키(public key)이며, 다른 하나는 사용자에 의해 비밀리에 관리되어야 하는 비밀키(private key)이다. 즉, 자신의 비밀 키만 관리하면 되므로 키 관리의 어려움이 줄며, 각 사용자의 공개키를 관리하는 공개키 시스템(공개키 디렉토리)이 필요하며, 이는 자유롭게 접근하고 열람할 수 있다.

이는 수학적인 연산이 추가된 시스템으로, 대칭키 암호 시스템에 비해 속도가 매우 느리다.

**비대칭키(공개키) 암호 시스템 종류**

- Diffie-Hallman (Diffie–Hellman key exchange)
암호 키를 교환하는 하나의 방법으로, 두 사람이 암호화되지 않은 통신망을 통해 공통의 비밀 키를 공유할 수 있도록 하는 방법이다. 이산 로그 연산을 기반으로 공유한다.
- DES
- AES
- RSA (Rivest, Shamir, Adleman 의 약자)
암호화뿐만 아니라 전자서명이 가능한 최초의 알고리즘으로, 전자 상거래 등에 광범위하게 사용됐다.
큰 숫자를 소인수 분해하는 것이 어렵다는 것에 기반을 두고 있다.
- ECC (Elliptic curve cryptography, 타원 곡선 암호)
타원 곡선 이론에 기반한 공개 키 암호화 방식이다. 장점으론 보다 짧은 키를 사용하면서도 다른 종류와 비슷한 수준의 안전성을 제공한다는 것이지만, 배경 이론이 복잡하며 구현이 어렵다.

### Hash (해시)

Hash 는 단반향 암호화 기법으로 해시 함수(해시 알고리즘)를 이용하여 가변 길이의 데이터를 고정된 길이의 암호화된 문자열로 바꿔버리는 것을 의미한다. 여기서 **해시 함수**는 임의의 길이의 데이터를 고정된 길이의 데이터로 매핑하는 함수이며, 매핑 전 원 데이터 값을 Key, 매핑 후 데이터 값을 Hash value, 매핑하는 과정을 Hashing 이라 한다.

입력은 무한정으로 가능하지만, 출력인 해시 값은 고정된 길이기에 중복이 될 수도 있다. 이를 충돌이라 부르며, 이를 보완하기 위해 salt라는 특정 값을 넣는 방법과 해시 함수를 여러 번 돌리는 방법, 두 가지 방법을 섞은 방법까지 총 3가지 방법이 있다.

**MessageDigest**

MessageDigest 클래스는 SHA-1 또는 SHA-256과 같은 메세지 다이제스트 알고리즘의 기능을 애플리케이션에 제공한다. 메세지 다이제스트는 임의의 크기의 데이터를 가져와 고정된 길이의 해시 값으로 출력하는 안전한 단방향 해시 함수이다.

표준 MessageDigest 알고리즘은 다음과 같다.

- MD5
MD5 (Message-Digest 5) 는 메세지 축약 알고리즘으로써, 파일 *무결성 검사용도로 많이 쓰이고 있다.
128bit 의 해쉬를 제공하며, 암호와와 복호화를 통하여 보안용도로도 많이 쓰인다.
하지만 암호화 결함이 발견되어 보안 용도로 사용할때에는 SHA와 같은 다른 알고리즘을 사용하는것이 권장되고 있다고 한다.
- SHA-1
SHA(Secure Hash Algorithm, 안전한 해시 알고리즘) 함수들은 서로 관련된 암호학적 해시 함수들의 모음이다. 여러 종류가 존재하며 그중 SHA-1은 SHA 함수들 중 가장 많이 쓰이며, TLS, SSL, PGP, SSH, IPSec 등 많은 보안 프로토콜과 프로그램에서 사용되고 있다. SHA-1은 이전에 널리 사용되던 MD5를 대신해서 쓰이기도 한다. 좀 더 중요한 기술에는 SHA-256이나 그 이상의 알고리즘을 사용할 것을 권장한다.
- SHA-256
충돌 공격에 대해 128비트 보안을 제공하기 위한 256비트 해시 함수이다.(SHA-512같은 경운, 256비트 보안을 제공하기 위한 512비트 해시 함수)

**Checksum**

중복 검사의 한 형태로, 오류 정정을 통해 공간(전자 통신)이나 시간(기억 장치) 속에서 송신된 자료의 무결성을 보호하는 방법이다.

### MAC (**Message Authentication Code)**

메세지의 인증에 쓰이는 작은 크기의 정보를 의미한다. MAC 알고리즘은 비밀 키를 입력받고, 임의 길이의 메시지를 인증한다. 그리고 출력으로써 MAC을 출력한다. MAC 값은 검증자(비밀 키를 소유한 사람)의 허가에 의해서 메세지의 데이터 인증과 더불어 무결성을 보호한다.

MAC의 종류는 다음과 같다.

- HMAC (Hash-based Message Authentication Code)
비밀키와 결합된 **암호화 해시 기능을 사용**해 MAC을 계산하는 방법으로, 무결성과 신뢰성 모두 확인할 수 있다. 이는 메세지의 암호화 여부와 관계가 없다.
- CMAC (Cipher-based Message Authentication Code)
비밀키와 결합된 **블록 암호를 사용**하여 MAC을 계산하는 방법으로, 무결성과 신뢰성 모두 확인할 수 있다. 이는 메시지 암호화를 수행해야 한다.

---

용어 설명

- 기밀성(Confidentiality) : 부적절한 노출 방지, 허가받은 사용자가 아니면 내용에 접근할 수 없어야 한다.
- 무결성(Integrity) : 부적절한 변경 방지, 허가받은 사용자가 아니면 내용을 변경할 수 없어야 한다.
- 라운드 함수 (round function) : 암호화 방식이 특정 계산 함수의 반복으로 이뤄지며, 이 때 각 과정에 사용되는 함수를 의미한다.
59 changes: 59 additions & 0 deletions 008. KeyStore System and Security/Part2_AndroidSecurityCrypto.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
### SharedPreferences

저장하려는 key-value 의 모음이 상대적으로 작으면 사용하는 API

Context.getSharedPreferences(String, int)에 의해 반환된 preference 데이터에 접근하고 수정하기 위한 인터페이스.

preferences의 모든 특정 셋에 대해, 모든 클라이언트가 공유하는 이 클래스의 단일 인스턴스가 있다.

preferences에 대한 수정은 preferences의 값이 일관된 상태로 유지되고 저장소에 커밋될 때 제어가 유지되도록 Editor 객체를 만들어야 한다. (즉, Editor는 SharedPreferences 객체의 값을 수정하기 위해 사용되는 인터페이스이다. ) 다양한 get 메서드에서 반환된 객체는 어플리케이션에서 변경 불가능한 것으로 처리해야만 한다.

이 클래스는 강력한 일관성을 보장한다. 비싼 작업을 사용하므로 앱 속도를 저하시킬 수 있다. 손실을 묵인할 수 있는 속성 또는 자주 변경하는 속성은 다른 메카니즘을 사용해야 한다.

### EncryptedSharedPreferences

key와 value를 암호화하는 SharedPreference의 구현으로, Android 6.0(API 23) 이상에서만 사용 가능하다.

MasterKey를 AES256_GCM_SPEC 를 통해 생성해 해당 키를 토대로 값을 암호화해 저장한다.

단순 사용법은 아래와 같다.

```java
String masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC);

SharedPreferences sharedPreferences = EncryptedSharedPreferences.create(
"secret_shared_prefs",
masterKeyAlias,
context,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
);

// use the shared preferences and editor as you normally would
SharedPreferences.Editor editor = sharedPreferences.edit();
```

EncryptedSharedPreferences에서 제공하는 메서드는 thread에 안전하지 않다.

### DataStore

*프로토콜 버퍼를 사용해 key - value 또는 객체를 저장할 수 있는 데이터 저장 솔루션이다. Kotlin Coroutines or Flow를 사용해 비동기적이고 일관된 트랜잭션 방식으로 데이터를 저장한다. 소규모 단순 데이터 세트에 적합하며 부분 업데이트나 참조 무결성은 지원하지 않는다.

- Preferences DataStore : 키를 사용해 데이터를 저장하고 접근한다. 이 구현은 유형 안전성을 제공하지 않으며, 사전 정의된 스키마가 필요 없다.
- Ptoro DataStore : 맞춤 데이터 유형의 인스턴스로 데이터를 저장한다. 이 구현은 유형 안전성을 제공하며, 프로토콜 버퍼를 사용해 스키마를 정의해야 한다.

그래들 설정 방법 : [https://developer.android.com/topic/libraries/architecture/datastore?hl=ko#groovy](https://developer.android.com/topic/libraries/architecture/datastore?hl=ko#groovy)

### Google Tink Library

애플리케이션에서 암호화를 사용하는 것이 어둠 속에서 전기톱을 저글링하는 것처럼 느껴질 필요는 없다. Tink는 구글의 암호학자와 보안 엔지니어 그룹에 의해 작성된 암호화 라이브러리이다. 구글의 제품 팀과 함께 작업하며, 구현의 약점을 수정하고, 암호화 배경 필요 없이 안전하게 사용할 수 있는 간단한 API를 제공하는 확장된 경험을 바탕으로 만들어졌다.

Tink는 올바르게 사용하기 쉽고 오용하기 어려운 보안 APIs를 제공한다. 사용자 중점 설계, 신중한 구현과 코드 리뷰, 확장된 테스트를 통해 일반적인 암호화 위험을 줄인다. 구글에서 Tink는 표준 암호화 라이브러리 중 하나이며, 수백 가지의 제품과 시스템에 배포되어 있다.

설정 방법 : [https://github.com/google/tink](https://github.com/google/tink)

---

참고

- Protocol buffers : 구조화된 데이터를 직렬화하기 위한 구글의 언어 중립적, 플랫폼 중립적, 확장 가능한 메커니즘이다. XML을 생각할 수 있지만, 더 작고 더 빠르고 더 간단하다. 데이터가 구조화되는 방법을 한 번 정의한 다음, 특별히 생성된 소스 코드를 사용해 다양한 데이터 스트림과 다양한 언어를 사용하여 구조화된 데이터를 쉽게 쓰고 읽을 수 있다.