[windows] pysqlcipher3 사용하기

[windows] pysqlcipher3 사용하기

2024년 10월 18일

pysqlcipher3 #

분석을 하다보면 sqlcipher로 암호화된 데이터베이스를 자주 볼 수 있다.
처음 복호화에 사용할땐 ubuntu를 깔아서 설치했는데 문제 없이 사용할 수 있었지만, 다시 환경을 세팅하려 하니 windows 에서 pip install pysqlcipher3 으로는 아주 많은 에러가 발생해서 직접 빌드를 해야한다. c8827408-17bd-4910-a910-40441c7788f9

환경 #

  • Windows 11
  • Python 3.10.5

참고 링크 #


설치 #

  1. github에서 pysqlcipher3 레포 클론

  2. Win64 OpenSSL 설치 (lite 버전 X)

    • https://slproweb.com/products/Win32OpenSSL.html
    • 시스템 환경변수 추가 OPENSSL_CONF=C:\OpenSSL-Win64\bin\openssl.cfg
    • libcrypto.def/lib, libssl.def/lib 파일 복사 후 → libeay32.def/lib, ssleay32.def/lib 로 이름 변경하고
      C:\Program Files\OpenSSL-Win64\lib 로 이동 64bit openssl이 32bit와 하위 호환이 안되는 것 같다. 06c4593c-b96f-4ffd-830f-28abc1273c73
  3. sqlite-amalgamation.zip 다운로드

  4. ActiveTcl 설치

  5. visual studio 설치 (x64 Native Tools Command)

  6. x64 Native Tools 터미널에서 sqlcipher clone 경로로 이동 후 nmake /f Makefile.msc 명령실행.
    빌드는 실패하지만 sqlite3.c, sqlite3.h 파일만 생기면 된다.

  7. pysqlcipher 클론 폴더에 amalgamation 폴더를 생성하고 바로 위에서 만들어낸 sqlite3.c, sqlite3.h 파일을 옮긴다. amaligamation\sqlcipher 폴더를 생성하고 sqlite-amalgamation.zip 을 압축 해제해서 나온 파일들을 집어넣는다.

     1pysqlcipher3
     2├─amalgamation
     3│  │  sqlite3.c
     4│  │  sqlite3.h
     5│  │
     6│  └─sqlcipher
     7│          shell.c
     8│          sqlite3.c
     9│          sqlite3.h
    10│          sqlite3ext.h
    
  8. $ python setup.py build_amalgamation 명령을 실행하면 에러가 발생할텐데 고치면서 빌드를 완료한다.

  9. 빌드가 완료되면 $ python setup.py install 명령으로 설치한다. (관리자 권한 터미널이여야 함)
    에러 없이 import 되면 성공! 0c92b343-4125-4038-998f-20946cff0d53

error C2017: illegal escape sequence #

모듈네임이 파싱이 안돼서 생기는 문제기 때문에 에러가 발생하고 있는 파일에서 MODULE_NAME 부분을 전부 "pysqlcipher3.dbapi2" 로 수정해주면 된다.
처음엔 cache.c 겠지만, 계속 실행하다보면 connection.c 등 거의 모든 .c 파일에서 에러가 발생한다.


사용법 #

 1from pysqlcipher3 import dbapi2 as sqlite
 2
 3key_bytes = bytes.fromhex("8e 51 0b 47 c7 25 16 39 4c f4 3d b7 9f bf 41 6f  61 2d b5 3e 43 ad 5f f2 dd 03 ee 4c a8 14 4b 5e ".replace(" ", ""))
 4
 5conn = sqlite.connect('test.db')
 6c = conn.cursor()
 7c.execute(f"PRAGMA key = \"x'{key_bytes.hex()}'\";")
 8c.execute("PRAGMA cipher_compatibility = 3")
 9c.execute('''create table stocks (date text, trans text, symbol text, qty real, price real)''')
10c.execute("""insert into stocks values ('2006-01-05','BUY','RHAT',100,35.14)""")
11conn.commit()
12
13c.execute("select * from stocks")
14t = c.fetchall()
15for f in t:
16    print(f)
17
18c.close() 

파일을 hxd로 열어보면 암호화되어 있고, 같은 비밀번호로 다시 복호화가 잘 된다. 42c94f49-d1f8-4d06-b02d-5b7e16ef9e1c


PRAGMA 세팅법 #

암호화할 때 PRAGMA를 세팅할 수 있다. key 세팅 이후에 적용해야 적용되는 듯 하다.

이중에 cipher 라고 암호화 방식을 지정하는게 있는데, sqlcipher는 사실상 AES-256-CBC 하나의 암호화 방식만 지원한다.

 1import pysqlcipher3.dbapi2 as sqlite
 2
 3# 이 값들을 반복문으로 돌려볼 수도 있다.
 4page_sizes = [512, 1024, 2048, 4096, 8192, 16384, 32768, 65536]  # 다양한 페이지 크기
 5kdf_iters = [1000, 4000, 10000, 64000, 128000, 256000, 512000]  # KDF 반복 횟수
 6hmac_algorithms = ["HMAC_SHA1", "HMAC_SHA256", "HMAC_SHA512"]  # HMAC 알고리즘
 7kdf_algorithms = ["PBKDF2_HMAC_SHA1", "PBKDF2_HMAC_SHA256", "PBKDF2_HMAC_SHA512"]  # KDF 알고리즘
 8
 9# 데이터베이스 연결
10conn = sqlite.connect('encrypted_database.db')
11
12# 커서 생성
13cursor = conn.cursor()
14
15# 키를 설정하여 데이터베이스 암호화/복호화
16cursor.execute("PRAGMA key = 'your_password';")
17
18# 데이터베이스가 새로 만들어졌다면 암호화 시작
19cursor.execute("PRAGMA cipher_page_size = 4096;")  # 페이지 크기 설정
20cursor.execute("PRAGMA cipher_plaintext_header_size = 32;")  # 헤더 크기 설정 (32의 배수, 페이지 크기 미만)
21cursor.execute("PRAGMA kdf_iter = 64000;")  # PBKDF2 키 스트레칭 설정
22cursor.execute("PRAGMA kdf_iter;")  # 잘 세팅 됐는지 확인 
23t = cursor.fetchone()
24print(f"kdf_iter 세팅 확인: {t}")
25cursor.execute("PRAGMA cipher_hmac_algorithm = HMAC_SHA512;")  # HMAC 알고리즘 설정
26cursor.execute("PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA512;")  # KDF 알고리즘 설정
27cursor.execute("PRAGMA cipher_use_hmac = ON;")  # HMAC 사용 여부 설정
28
29# 데이터 삽입 예시
30cursor.execute("CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, data TEXT);")
31cursor.execute("INSERT INTO test (data) VALUES ('Hello, SQLCipher!');")
32
33# 변경 사항 저장
34conn.commit()
35
36# 연결 종료
37cursor.close()
38conn.close()

복호화 할때도 동일하게 PRAGMA를 세팅해줘야 복호화가 정상적으로 동작한다.
처음 키만 연결하고 PRAGMA값을 확인해보면 그냥 기본값이 들어가있다.

 1import pysqlcipher3.dbapi2 as sqlite
 2
 3# 암호화된 데이터베이스 연결
 4conn = sqlite.connect('encrypted_database.db')
 5
 6# 커서 생성
 7cursor = conn.cursor()
 8
 9# 복호화 키 설정
10cursor.execute("PRAGMA key = 'your_password';")
11cursor.execute("PRAGMA cipher_page_size = 4096;")
12cursor.execute("PRAGMA cipher_plaintext_header_size = 32;")
13cursor.execute("PRAGMA kdf_iter = 64000;")
14cursor.execute("PRAGMA cipher_hmac_algorithm = HMAC_SHA512;")
15cursor.execute("PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA512;")
16# cursor.execute("PRAGMA cipher_use_hmac = ON;")
17
18# 데이터 조회 예시
19cursor.execute("SELECT * FROM test;")
20rows = cursor.fetchall()
21
22for row in rows:
23    print(row)
24
25# 연결 종료
26cursor.close()
27conn.close()
comments powered by Disqus