๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ’ป IT·๊ธฐ์ˆ ·ํ†ต๊ณ„

Python์œผ๋กœ ๊ฐœ์ธ์ •๋ณด ๊ฐ€๋ช… ์ฒ˜๋ฆฌํ•˜๊ธฐ (SHA-256)

by nowgeun 2023. 3. 16.
728x90

SNS ์‚ฌ์šฉ ์ฆ๊ฐ€์™€ ๋ฐ์ดํ„ฐ ๊ธฐ๋ฐ˜ ์„œ๋น„์Šค๊ฐ€ ๋งŽ์ด ์ถœ์‹œ๋˜๋ฉด์„œ ๊ฐœ์ธ์ •๋ณด ๊ฐ€๋ช… ์ฒ˜๋ฆฌ์˜ ์ค‘์š”์„ฑ์ด ๋†’์•„์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. 

๊ฐœ์ธ์ •๋ณด ๊ฐ€๋ช…ํ™”๋Š” ๊ฐœ์ธ์ •๋ณด๋ฅผ ๋‹ค๋ฅธ ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•ด์„œ ๊ฐœ๊ฐœ์ธ์„ ํŠน์ •ํ•  ์ˆ˜ ์—†๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. 

๊ธˆ์œต ๋ฐ ์ฆ๊ถŒํšŒ์‚ฌ์—์„œ๋Š” ๊ณ ๊ฐ์˜ ๊ฐœ์ธ์ •๋ณด๋ฅผ ์—„๊ฒฉํ•˜๊ฒŒ ๊ฐ๋… ๋ฐ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐœ์ธ์˜ ์‹ ์ƒ ์ •๋ณด์™€ ์‹ ์šฉ ์ •๋ณด๋Š” ๋งค์šฐ ๋ฏผ๊ฐํ•œ ๋ฐ์ดํ„ฐ์ด๊ธฐ ๋•Œ๋ฌธ์—, ์ด๋Ÿฌํ•œ ๋ฐ์ดํ„ฐ๋Š” ๊ฐ€๋ช…ํ™”์ฒ˜๋ฆฌ๋ฅผ ํ•ด์„œ ์‚ฌ์šฉ์„ ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. 

 

๋ฐ์ดํ„ฐ ๊ฐ€๋ช…์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ•

๋ฐ์ดํ„ฐ๋Š” ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ ๊ฐ€๋ช…์ฒ˜๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

1. ์ผ๋ฐ˜ํ™”/๋ฒ”์ฃผํ™”
์ผ๋ฐ˜ํ™”๋Š” ๊ฐœ์ธ์ •๋ณด์˜ ํŠน์ • ๋ถ€๋ถ„์„ ๋Œ€ํ‘œํ•˜๋Š” ์ผ๋ฐ˜์ ์ธ ๊ฐ’์œผ๋กœ ๋Œ€์ฒดํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ๋Œ€ํ‘œ์ ์ธ ์˜ˆ์‹œ๊ฐ€ ๋‚˜์ด ์ž…๋‹ˆ๋‹ค.

๊ตฌ์ฒด์ ์ธ ๋‚˜์ด ๋Œ€์‹  10๋Œ€, 20๋Œ€, 30๋Œ€๋กœ ๋ณ€ํ™˜์„ ํ•œ๋‹ค๋ฉด ๊ฐœ์ธ์˜ ๋‚˜์ด์— ๋Œ€ํ•œ ๋Œ€๋žต์ ์ธ ์ •๋ณด๋Š” ์œ ์ง€ํ•˜๋ฉด์„œ๋„, ์‹ค์ œ ๋‚˜์ด๋Š” ๋…ธ์ถœํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2. ์ต๋ช…ํ™”
์ต๋ช…ํ™”๋Š” ๊ฐœ์ธ์ •๋ณด๋ฅผ ์™„์ „ํžˆ ์‚ญ์ œํ•˜๊ฑฐ๋‚˜, ์ต๋ช…ํ™”๋œ ์ƒˆ๋กœ์šด ๊ฐ’์œผ๋กœ ๋Œ€์ฒดํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์ด๋ฆ„์„ ๋ณ„ํ‘œ(*)๋กœ ๋Œ€์ฒดํ•˜๋Š” ๊ฒฝ์šฐ ์ž…๋‹ˆ๋‹ค. 

3. ๋Œ€์ฒด ํ† ํฐ ์ƒ์„ฑ / ์ผ๋ จ๋ฒˆํ˜ธ ์ƒ์„ฑ
๊ณ ๊ฐ ์‹๋ณ„ ๋ฒˆํ˜ธ๋ฅผ ์ผ๋ จ๋ฒˆํ˜ธ๋กœ ๋Œ€์ฒดํ•˜์—ฌ ๊ฐœ์ธ์ •๋ณด๋ฅผ ๊ฐ€๋ช…ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๊ฐœ์ธ์˜ ์‹ค์ œ ์ •๋ณด๋ฅผ ์œ ์ง€ํ•˜๋ฉด์„œ๋„, ๊ฐœ์ธ์„ ์‹๋ณ„ํ•  ์ˆ˜ ์—†๋Š” ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

4. ๋…ธ์ด์ฆˆ ์ถ”๊ฐ€
๋…ธ์ด์ฆˆ ์ถ”๊ฐ€๋Š” ๋ฐ์ดํ„ฐ์— ์ž„์˜์˜ ๋…ธ์ด์ฆˆ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ์™œ๊ณก์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๊ฐœ์ธ์˜ ์†Œ๋“ ์ •๋ณด์— ์ž„์˜์˜ ์ˆซ์ž๋ฅผ ๋”ํ•˜๊ฑฐ๋‚˜, ๋นผ์„œ ์›๋ž˜ ์ •๋ณด๋ฅผ ์™œ๊ณกํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ปค๋ฎค๋‹ˆํ‹ฐ๋‚˜ SNS์— ์ธ์ฆ ์‚ฌ์ง„์„ ์˜ฌ๋ฆด ๋•Œ, ๊ฐœ์ธ์ •๋ณด๋ฅผ ๊ฐ€๋ฆฌ๊ฑฐ๋‚˜ ์ƒ‰์น ํ•ด์„œ ์˜ฌ๋ฆฌ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋Œ€ํ‘œ์ ์ธ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.

 

SHA (Secure Hash Algorithm)

 

SHA๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๋ช…์ฒ˜๋ฆฌํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋˜๋Š” ์•”ํ˜ธํ™” ๊ธฐ์ˆ  ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ์ฃผ๋กœ ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ์˜ ์•”ํ˜ธํ™”์— ์‚ฌ์šฉ๋˜๋ฉฐ, ๋‹จ๋ฐฉํ–ฅ ๋ณ€ํ™˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด๊ธฐ ๋•Œ๋ฌธ์— ์•”ํ˜ธํ™”๋œ ๊ฐ’์€ ์—ญ์œผ๋กœ ๋ณตํ˜ธํ™” ํ•˜๊ฑฐ๋‚˜ ์ถ”์ ํ•˜๋Š” ๊ฒƒ์ด ๊ฑฐ์˜ ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์•”ํ˜ธํ™” ์ „์˜ ๊ฐ’๊ณผ ์•”ํ˜ธํ™” ๋œ ์ดํ›„์˜ ๊ฐ’์„ ํ‘œ์˜ ํ˜•ํƒœ๋กœ ๋ฏธ๋ฆฌ ์ €์žฅํ•œ๋‹ค๋ฉด (์ด๋ฅผ ๋ ˆ์ธ๋ณด์šฐ ํ…Œ์ด๋ธ” ์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค) ๊ฐ€๋Šฅํ•œ ์–˜๊ธฐ์ด์ง€๋งŒ, ์™ธ๋ถ€์ธ์ด ๋ชจ๋“  ๊ฒฝ์šฐ์— ์ˆ˜์— ๋Œ€ํ•ด SHA ๊ฐ’์„ ๊ณ„์‚ฐํ•˜๊ณ  ์ €์žฅํ•˜๋Š” ๊ฒƒ์€ ๋งค์šฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ์ถœ๋ ฅ๋œ ๊ฐ’์„ ํ•œ๋ฒˆ์— ์•”ํ˜ธํ™” ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ์˜ ๊ธธ์ด ๋˜ํ•œ ์ตœ๋Œ€ ์•ฝ 18EB(์—‘์‚ฌ๋ฐ”์ดํŠธ)๋กœ ๊ฑฐ์˜ 300ํŽ˜์ด์ง€ ์งœ๋ฆฌ ์ฑ… 30์กฐ ๊ถŒ ์ •๋„๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. 

SHA256 image
SHA256

 

Python์œผ๋กœ ๊ตฌํ˜„ํ•˜๊ธฐ

Python์œผ๋กœ ๋ฐ์ดํ„ฐ ๊ฐ€๋ช…ํ™”๋ฅผ ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋งค์šฐ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. ๋‚ด์žฅ๋œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ hashlib์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์†”ํŠธ๊ฐ’(Salt) ๊ฐ’์€ SHA256 ๊ฐ’์— ๋žœ๋คํ•œ ๋…ธ์ด์ฆˆ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฐ’์ด๋ผ๊ณ  ์ดํ•ดํ•˜์‹œ๋ฉด ๋  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋™์ผํ•œ ์ž…๋ ฅ๊ฐ’์ด๋ผ๋„ ์„œ๋กœ ๋‹ค๋ฅธ ์†”ํŠธ๊ฐ’์„ ์‚ฌ์šฉํ•˜๋ฉด ์ถœ๋ ฅ๊ฐ’์ด ๋‹ฌ๋ผ์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋ ˆ์ธ๋ณด์šฐ ํ…Œ์ด๋ธ” ๊ณต๊ฒฉ(Rainbow Table Attack) ๋“ฑ์„ ๋ฐฉ์ง€ํ•˜์—ฌ ๋ณด์•ˆ์„ฑ์„ ๊ฐ•ํ™”ํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

import os
import pandas as pd
from hashlib import sha256

# ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„ ์„ค์ •
pd.set_option('display.max_columns', None)
pd.set_option('display.expand_frame_repr', False)
pd.set_option('max_colwidth', -1)


def SHA(text, salt=None):
    # ๋ฌธ์ž์—ด์„ ๋ฐ”์ดํŠธ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜
    byte_str = text.encode('utf-8')

    # hashlib ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ SHA-256 ํ•ด์‹œ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœ
    hash_obj = sha256()

    # ์†”ํŠธ๊ฐ’์ด ์žˆ๋‹ค๋ฉด ํ•ด์‹œ ํ•จ์ˆ˜์— ์ถ”๊ฐ€ ์ž…๋ ฅ๊ฐ’์œผ๋กœ ์ œ๊ณต
    if salt:
        salt_bytes = salt.encode('utf-8')
        byte_str += salt_bytes

    # ์ž…๋ ฅ๊ฐ’์„ ํ•ด์‹œ ํ•จ์ˆ˜์— ์ž…๋ ฅํ•˜์—ฌ ์ถœ๋ ฅ๊ฐ’์„ ์ƒ์„ฑ
    hash_obj.update(byte_str)

    # ์ถœ๋ ฅ๊ฐ’์„ 16์ง„์ˆ˜ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ๋ฐ˜ํ™˜
    return hash_obj.hexdigest()

# ์†”ํŠธ๊ฐ’ ์ƒ์„ฑ ํ•จ์ˆ˜
def generate_salt(length=16):
    return os.urandom(length).hex()

def data_hash(text, salt=None):
    salt = generate_salt() # ๋ฌด์ž‘์œ„ ์†”ํŠธ๊ฐ’ ์ƒ์„ฑ
    hashed_str = SHA(text, salt)
    return hashed_str

# ๋งคํ•‘๊ฐ’์„ ์ €์žฅํ•˜๋Š” ๊ฒƒ์€ ๋ณด์•ˆ ์ƒ ๋งค์šฐ ์ทจ์•ฝํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ์‹œ๋กœ๋งŒ ๋ณด์‹œ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค
hash_table = pd.DataFrame(["Hello World", "Hello World!", "Hello People"], columns=["๋ฐ์ดํ„ฐ ์›๋ณธ"])
hash_table['SHA256 ๊ฐ€๋ช…์ฒ˜๋ฆฌ'] = hash_table['๋ฐ์ดํ„ฐ ์›๋ณธ'].apply(lambda x: data_hash(x))

hash_table
 
SHA ๋ณ€ํ™˜ ๊ฒฐ๊ณผ๋ฌผ
๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€