1. PBKDF2의 이해

  • 의사 난수 기능을 적용하여 키 파생
  • 파생된 키 길이는 제한 없음
    • 그러나 파생된 키의 최대 유효 검색 공간은 기본 의사 난수 함수의 구조에 의해 제한 될 수 있다.

 

2. PBKDF2의 동작과정

 

 

 

 

 

INT(i) : i를 4byte로 인코딩

 

 

 

 

 

 

 

 

3. PBKDF2 소스코드 구현

[ 모듈 이용 ] 

1
2
3
4
5
6
7
### 모듈 이용 ###
from hashlib import pbkdf2_hmac
import base64
 
= pbkdf2_hmac('sha1', password='password'.encode(), salt='salt'.encode(), iterations=1000, dklen=32)
print('[ 모듈 이용 ] DK =', base64.b64encode(K).decode())
 
cs

 

 

[ 동작원리 이용 ]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
### 동작원리 이용 ###
import hashlib
import hmac
import base64
import math
import operator
 
def pbkdf2(password, salt, iteration, dklen):
    hlen = hmac.new(password, msg=None, digestmod=hashlib.sha1).digest_size  
    len = math.ceil(dklen/hlen)
    r = dklen-(len-1)*hlen
    DK = b''
    for i in range(1len+1):
        T = bytes(hlen)
        INT = i.to_bytes(4, byteorder='big')
        U_0 = salt + INT
        for j in range(iteration):
            U_N = hmac.new(password, U_0, hashlib.sha1).digest()
            T = bytes(map(operator.xor, T, U_N))
            U_0 = U_N
        if (i == len):
            DK += T[:r]
            return DK
        DK += T
    return DK
    
DK = pbkdf2('password'.encode(), 'salt'.encode(), 100032)
print('[ 동작원리 이용 ] DK =', base64.b64encode(DK).decode())
cs

 

 

=== 실행결과 ===

 

 

== Github 소스코드 파일 ==

github.com/K-subin/PBKDF

1. PBKDF1의 이해

  • MD2, MD5, SHA-1인 해시함수 적용
  • 파생된 키 길이는 제한
    • MD2, MD5 – 16byte
    • SHA-1 – 20byte

 

 

 

 

Salt와 iteration은 공격자의 사전공격을

어렵게 하는 중요한 요소

 

 

 

 

 

2. PBKDF1의 동작과정

 

3. PBKDF1 소스코드 구현

1
2
3
4
5
6
7
8
9
10
11
12
import hashlib
import base64
 
def pbkdf1(password, salt, iteration, dklen):
    T_0 = password + salt
    for i in range(iteration):
        T_N = hashlib.sha1(T_0).digest()
        T_0 = T_N
    return T_0[:dklen]
 
DK = pbkdf1('password'.encode(), 'salt'.encode(), 100020)
print(base64.b64encode(DK).decode('utf-8'))
cs

 

 

==실행결과==

 

 

== Github 소스코드 파일 ==

github.com/K-subin/PBKDF

[ FBE(File-Based Encryption)의 동작 과정 ]

  • 파일 시스템 수준에서 수행
  • ext4 파일 시스템 암호화

 

1. FDE와 유사하게 User key와 salt를 이용해서 KDF를 이용해 KEK, IV를 생성

 

 

 

 

 

 

 

 KEK는 TEE에 안전하게 보관된다.

 

 

 

 

 


2. KEK와 IV를 사용하여 AES-256-GCM으로 DEK를 암호화

  

     - DEK : dev/urandom에서 읽은 64byte 난수

     - 상위 32byte는 파일 내용 암호화하는데 사용

     - 하위 32byte는 파일 이름 암호화하는데 사용

 

 

      TEE에서 KEK를 가져오려면 3가지 요구사항을 충족해야 한다.

      (1) 확장된 사용자 자격증명

               :  KDF(scrypt)로 사용자 인증을 확장

      (2) Secdiscardable hash (사용자 SID)

               :  임의의 16KB 파일로 이루어진 512bit 해시

      (3) 인증 토큰

               :  사용자가 정상적으로 로그인했을 때 게이트키퍼에 의해

                  생성되는 암호화방식으로 인증된 토큰


3. DEK와 nonce를 사용하여 AES-ECB-128로 암호화해서 각 파일별 키 생성 

 

 

 

  • 각 파일에는 연결된 16byte nonce가 dentry에 저장
  • dentry는 ext4 파일 시스템 구조에 inode항목에 연결하는 데이터 구조

 

  • DEK 상위 32byte -> AES-ECB-128 -> 파일 이름 암호화 키 생성
  • DEK 하위 32byte -> AES-ECB-128 -> 파일 내용 암호화 키 생성


4.  파일 이름은 각 파일별 키와 IV를 사용하여                                                                                                          AES-256-CBC-CTS로 암호화 된다.

  • IV는 0으로 채워진다.
  • 결과 암호문은 base62 인코딩을 사용하여 인코딩 된다.
  • 암호화된 파일 이름은 dentry에 저장된다.

 

5. 파일 내용은 각 파일별 키를 사용하여                                                                                                                    AES-256-XTS로 암호화된다.

  • 암호화된 파일 내용은 inode에 저장된다.

6.  Key Store

‘crypto footer’ 유추  ->  /data/misc/vold/user_keys 디렉터리

‘de’와 ‘ce’ 두 개의 하위 디렉터리로 나뉜다.

 

=================================================

 

“encrypted_key”   :  암호화된 DEK 포함

“keymaster_key_blob   :  암호화된 RSA-2048 개인키 포함

“salt”   :  DEK를 복호화할 때 사용자 인증과 결합하여 사용

                   -> de 디렉터리는 사용자 입력이 필요하지 않으므로 salt 없음

“secdiscardable   :  임의의 16KB 파일의 512bit 해시 값

“stretching”   :   KDF에 사용되는 매개변수 포함

                   -> “scrypt X : Y : Z” 형식

                   ->  N = 2^X,  r = 2^Y,  p = 2^Z

1. FBE(File-Based Encryption)란?

  • 여러 키를 사용하여 여러 파일을 암호화 가능
  • 안드로이드 7.0부터 FBE 추가
  • 직접 부팅(Direct Boot) 기능 추가
    • 인증하지 않은 상태에서 바로 부팅 가능
    • 그러나 중요한 데이터는 복호화되지 않음
  • DE와 CE로 나눠서 각각 암호화하고 각각의 접근 범위를 설정한다.
    • CE(Credential Encrypted) storage  :  기본 저장공간, 사용자 인증 이후로만 사용 가능한 저장소
    • DE(Device Encrypted) storage  :  사용자 인증과 상관없이 사용 가능한 저장소(직접 부팅, 인증 이후 모두 가능)
  • 접근성이 설정된다면?
    • DE영역만 접근하도록 하여 데이터 보호 -> 암호화 무력화 문제 해결

 

2. FBE Decryption

• 파일 수준에서 암,복호화

• 기본 ext4 파일 시스템이 지원하는 fscrypt 암호화를 사용.

• 별도의 암호화된 두 가지 스토리지 영역

    - DE : 사용자 인증 전에 사용 가능.

    - CE : 사용자 인증 후에만 사용 가능.

1. 먼저 KEK를 생성하는데, FDE와 비슷한 방식으로 생성.

2. AES-256-GCM을 이용하여 CE, DE 별도의 마스터키가 생성.

3. AES-128-ECB와 128bit nonce를 이용하여 file key를 생성.

4. AES-256-CTS를 사용하여 파일 이름 복호화, AES-256-XTS를 사용하여 파일 내용 복호화.

 

 

[ FDE(Full-Disk Encryption)의 동작 과정 ]

1. user key와 salt를 scrypt 입력값으로 사용하여 32byte 중간 키 IK1을 생성

 

 

 

 

 

 

 

  • user key : pin/password/pattern
  • salt : dev/urandom에서 읽은 32byte 난수

 

 

 

 

 

 

*  Scrypt란?

    구조 :  PBKDF2 - SMIX - PBKDF2 

 

 

IK1 = scrypt(password, salt, N, r, p, dklen)

 

[input]

password

salt

N : CPU/memory cost (2의 배수)

r : blocksize parameter

p : 병렬화 (p <= (2^32)*hlen/MFLen)

dklen : 원하는 키 값 (dklen <= (2^32-1)*hlen)

 

[output]

IK1

 

 

 

 

2. IK1을 256byte(2048bit)까지 zero padding

 

 

 

 

00 || IK1 || 00 || 00 ... 00 || 00

( '00' 1byte || 'IK1' 32byte || '00' 223byte )  => 256byte

 

 

 

 

 

 

 

 

 

3.  패딩된 IK1에 HBK(hardware bound key)를 이용해 데이터를 서명해서 256byte IK2를 생성.

 

 

 

 

 

Android 5.0부터 Keymaster라는 하드웨어 지원 키 저장 기능 지원

- 암호화 키를 보호하기 위해 안전한 TEE 영역에서 구현

- dm-crypt는 FDE 수행을 담당하는 모듈

 

 

 

 

 

 

 

 

 

(1)  TEE 영역에서 Keymaster Key가 생성되면 HBK키를 사용하여 암호화됨.

           ->  ‘Key blob’ 암호화된 키 생성

           ->  안드로이드로 반환 

                    : 암호화되지 않은 영역인 ‘Crypto Footer’에 저장

(2) 안드로이드가 키를 사용하여 작업을 수행하려는 경우 ‘Key blob’를 keyMaster에 제공

 

(3) ‘key blob’를 HBK로 복호화

 

(4) 그 후 그 안에 포함된 RSA-2048 개인키로 데이터(패딩 된 IK1)를 서명

 

(5) 안드로이드로 반환  ->  IK2 생성 완료

 

 

 

4. 256byte IK2와 salt를 scrypt 입력값으로 사용해 32byte 중간키 IK3를 생성

 

 

 

 

 

처음 16byte를 KEK로 사용

마지막 16byte를 IV로 사용

 

 

 

 

 

 

 

 

 

5. 키 KEK와 초기화 벡터 IV를 사용하여 AES-CBC-128로 DEK를 암호화.

  - DEK : dev/urandom에서 읽은 32byte 난수

  - 암호화된 DEK는 “Crypto Footer”라는 암호화되지 않은 영역에 저장.

 

6. 암호화된 DEK로 DB를 암호화

    복호화하려면 암호화된 DEK를 복호화한 값으로 암호화된 DB를 복호화

FDE(Full-Disk Encryption)란?

  • 동일한 키를 사용하여 전체 디스크 암호화
  • : 사용자의 인증(패턴, 비밀번호)을 통해 암호화
    • 이 키는 사용자가 비밀번호나 패턴을 바꾸더라도 바뀌지 않는다.
    • 따라서 공장 초기화를 하기 전까지는 무슨 일이 있어도 데이터를 암호화하는 데에 동일한 키가 사용
    • 암호화된 키는 파티션의 특정부분(Crypto Footer)에 저장
  • 데이터 : 암호화된 키로 전체를 암호화
  • 암호화 두 번 하는 이유 : 인증으로 바로 데이터를 암호화하면 인증이 바뀔 때마다 암호화가 재수행 되어야한다.
  • FDE는 사용자가 인증하기 전에는 대부분의 기본 동작도 할 수 없다.
  • 접근성이 설정된다면?
    • 암호화되지 않은 것과 마찬가지, 포렌식 통해 복호화 가능
    • 무력화시키는 방법 : 단순히 사용자 인증을 default_password로 설정하여 암호화 키를 암호화시키는 것

 

2. FDE Key Store

 

1. 사용자 인증과 난수 SALT를 이용해서 256비트 중간키 IK1을 생성, 패딩으로 2048비트.

2. 하드웨어 바인딩 RSA 개인키로 2048비트 IK2를 생성.

3. IK2와 SALT에 scrypt를 적용하여 IK3을 생성.

4. IK3의 처음 16바이트를 KEK로 사용하고 마지막 16바이트를 IV로 사용.

5. 임의로 생성된 128비트 DEK를 KEK와 IV를 사용하여 AES-CBC-128로 암호화.

6. “Crypto Footer”라는 암호화되지 않은 영역에 저장.

 

 

3. FDE Decryption

 

  • TEE(안전한 영역)을 사용하여 KeyMaster라는 키 저장 기능을 지원.
  • 안드로이드가 키를 사용하여 복호화를 수행하려는 경우 암호화된 RSA 공개키를 keyMaster에 제공
  • KeyMaster는 키를 해독하고 데이터에 서명한 다음 결과를 반환

안드로이드는 APK라는 파일 압축 형태로 이루어져 있다.

Apk를 압축 프로그램으로 열어보면 크게 AndroidManifest.xml, resources.arsc, classes.dex가 있다.

때에 따라서는 asset, lib 폴더도 존재하여 Native code나 java library 등이 있다.

 

1. androidManifest.xml

안드로이드 앱의 속성을 다룬다.

Activity, service, receiver, permission 등의 속성은 이 파일에서 정의된다.

apk파일을 단순히 압축해제 하였을 때 androidManifest.xml은 바이너리 형태의 xml로 인코딩 되어 형태를 알아보기 어렵지만, 이를 디컴파일러를 통해 확인하면 디코딩된 xml 정보를 얻을 수 있다. 

 

2. resource 

안드로이드의 Image, Style 등과 같은 정보를 관리한다.

이것 또한 툴을 통해 확인이 가능하다.

 

3. Classes

DEX(Dalvik Executable) : 달빅 코드

Dex는 안드로이드에서 앱이 구동하기 위한 핵심적인 파일 포맷이다.

Dalvil VM에서 실행되는 Bytecode이며 명시적인 class, method 형태이다.

 

 

+ Recent posts