Hash Function(해시 함수)
- 임의의 길이를 가진 입력 데이터를 받아,
고정된 길이의 출력값(Hash, Digest) 을 생성하는 함수
- 출력값은 보통 메시지 다이제스트(Message Digest) 또는 체크섬(Checksum) 이라고 불린다.
- 입력 데이터의 크기에는 제한이 없다.
- 출력은 Hash algorithm에 따라 항상 고정된 길이이다.
- SHA-256 → 256비트
- SHA-384 → 384비트
MongoDB Checksum
- mongodb-macos-x86_64-7.0.24.tgz 패키지 파일을 다운로드 후 mongoDB의 해당 패키지로 공지된 sha256 값을 비교한 무결성 검사
import requests
import hashlib
BASE_URL = "https://fastdl.mongodb.org/osx"
MONGODB_FILE = "mongodb-macos-x86_64-7.0.24.tgz"
CHECKSUM_FILE = MONGODB_FILE + ".sha256"
MONGODB_URL = f"{BASE_URL}/{MONGODB_FILE}"
CHECKSUM_URL = f"{BASE_URL}/{CHECKSUM_FILE}"
def download_file(url, output_path):
response = requests.get(url, stream=True)
response.raise_for_status()
with open(output_path, "wb") as f:
for chunk in response.iter_content(chunk_size=8192):
if chunk:
f.write(chunk)
print(f"[+] Downloaded: {output_path}")
def calculate_sha256(file_path):
sha256 = hashlib.sha256()
with open(file_path, "rb") as f:
for chunk in iter(lambda: f.read(4096), b""):
sha256.update(chunk)
return sha256.hexdigest()
def read_expected_hash(sha256_file):
with open(sha256_file, "r") as f:
return f.read().split()[0]
if __name__ == "__main__":
download_file(MONGODB_URL, MONGODB_FILE)
download_file(CHECKSUM_URL, CHECKSUM_FILE)
expected_hash = read_expected_hash(CHECKSUM_FILE)
downloaded_hash = calculate_sha256(MONGODB_FILE)
print("\n[*] Expected SHA-256 :", expected_hash)
print("[*] Downloaded SHA-256:", downloaded_hash)
if downloaded_hash == expected_hash:
print("\n[✔] File integrity verified (hash match)")
else:
print("\n[✘] Hash mismatch! File may be corrupted or tampered with")
[+] Downloaded: mongodb-macos-x86_64-7.0.24.tgz
[+] Downloaded: mongodb-macos-x86_64-7.0.24.tgz.sha256
[*] Expected SHA-256 : 5e84567b3d11690d4da8cf7f7fb9f98e2e0119a2cd32a78590f134215b455e5b
[*] Downloaded SHA-256: 5e84567b3d11690d4da8cf7f7fb9f98e2e0119a2cd32a78590f134215b455e5b
[✔] File integrity verified (hash match)
Salt
- Salt는 비밀번호를 해시할 때
비밀번호에 추가되는 랜덤 데이터를 의미한다.
- 모든 사용자는 서로 다른 salt를 가진다.
- Salt는 해시와 함께 저장된다
- Rainbow Table
* 공격자가 미리 계산해 둔
(비밀번호 후보 → 해시 값) 의 테이블이다.
- salt는 비밀번호 역추적을 완전히 차단하지는 않지만,
해시 결과의 재사용(Rainbow Table)을 방지함으로써 공격 비용을 크게 증가시킨다.
Digital Signature
- 메시지가 변조되지 않았음을 증명하고,
해당 메시지가 누가 보냈는지를 확인하며,
송신자가 나중에 부인할 수 없도록 하기 위한
암호학적 검증 메커니즘이다. (암호화 및 복호화 연산은 하지 않는다.)
- 전자서명 생성 (Sign)
- 메시지 생성
- 메시지 해시 계산
- 해시값을 개인키로 서명
- 메시지 + 서명 전송
- 전자서명 검증 (Verify)
- 메시지 수신
- 메시지 해시 재계산
- 서명을 공개키로 검증
- 두 해시 값 비교
- 일치 → 유효 / 불일치 → 무효
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.asymmetric.utils import Prehashed
from cryptography.exceptions import InvalidSignature
import binascii
private_key = ec.generate_private_key(ec.SECP256R1())
public_key = private_key.public_key()
def sign_message(message: bytes, private_key):
print("Message:", message.decode())
digest = hashes.Hash(hashes.SHA256())
digest.update(message)
hashed = digest.finalize()
print("Hash (SHA-256):", binascii.hexlify(hashed).decode())
signature = private_key.sign(hashed, ec.ECDSA(Prehashed(hashes.SHA256())))
print("Signature:", binascii.hexlify(signature).decode())
packet = {"message": message, "signature": signature}
return packet
def verify_message(packet, public_key) -> bool:
message = packet["message"]
signature = packet["signature"]
print("\nReceived message:", message.decode())
print("Received signature:", binascii.hexlify(signature).decode())
digest = hashes.Hash(hashes.SHA256())
digest.update(message)
hashed = digest.finalize()
print("Recomputed Hash (SHA-256):", binascii.hexlify(hashed).decode())
try:
public_key.verify(signature, hashed, ec.ECDSA(Prehashed(hashes.SHA256())))
return True
except InvalidSignature:
return False
message = b"You're hired, Bob"
packet = sign_message(message, private_key)
result = verify_message(packet, public_key)
print("\nSignature valid:", result)
Message: You're hired, Bob
Hash (SHA-256): ef8b68a4b1e0d561814359be6633b70d6e28b7c3457c18013eda59de2cbbda2a
Signature: 30450220546c94c5e0da970fad0bb1a7cd453cfec4cadfc4733ae839e5c8ee8ee7f691b9022100e0fe3eed73e4f830f8483873d0bfce4d0875894691d0107edc3a7162021eb915
Received message: You're hired, Bob
Received signature: 30450220546c94c5e0da970fad0bb1a7cd453cfec4cadfc4733ae839e5c8ee8ee7f691b9022100e0fe3eed73e4f830f8483873d0bfce4d0875894691d0107edc3a7162021eb915
Recomputed Hash (SHA-256): ef8b68a4b1e0d561814359be6633b70d6e28b7c3457c18013eda59de2cbbda2a
Signature valid: True