(數位簽章的原理,圖的出處:https://dlan3xcpo7oaf.cloudfront.net/wp-content/uploads/2021/02/Digital-Signature-Flow-Chart.jpeg)
程式設計說明:
利用 Python 程式碼使用 cryptography 函式庫來實現了數位簽章(Digital Signature)的功能。首先,先成金鑰對(generate_key_pair),再依照上圖來簽署訊息(sign_message)和驗證簽章(verify_signature),來實現三個函式,說明如下:
1.生成金鑰對(generate_key_pair):
使用 rsa.generate_private_key 函數生成一對私鑰(private_key)和公鑰(public_key)。- 公鑰通常用於驗證數位簽章,私鑰用於創建數位簽章。
2.簽署訊息(sign_message):
- 使用私鑰對給定的訊息(message)進行數位簽章。
- 簽章過程使用了 PSS padding 和 SHA-256 hash 函數。
3.驗證簽章(verify_signature):
- 使用公鑰對簽章進行驗證,確保簽章是由對應的私鑰創建的。
- 如果驗證成功,返回 True,否則捕捉例外並輸出錯誤訊息,然後返回 False。
程式碼如下:
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import rsa, padding def generate_key_pair(): private_key = rsa.generate_private_key( public_exponent=65537, key_size=2048, backend=default_backend() ) public_key = private_key.public_key() return private_key, public_key def sign_message(private_key, message): signature = private_key.sign( message.encode('utf-8'), padding.PSS( mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH ), hashes.SHA256() ) return signature def verify_signature(public_key, message, signature): try: public_key.verify( signature, message.encode('utf-8'), padding.PSS( mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH ), hashes.SHA256() ) return True except Exception as e: print(f"驗證失敗: {e}") return False # Example usage: private_key, public_key = generate_key_pair() message_to_sign = "虎尾鎮,舊稱「大崙腳」,位於臺灣雲林縣中心,是一個因糖廠而興起的城鎮。" signature = sign_message(private_key, message_to_sign) print(f"數位簽章: {signature.hex()}") if verify_signature(public_key, message_to_sign, signature): print("有效的數位簽章") else: print("無效的數位簽章") |
數位簽章: 7006f8b687e8a0b93915822731f5bd74833a1bfc1b4bb610dbee5c6eb5ed5b99059ec9a7a6727b6dfffeb7f772079ada05f9c804abc31b13834429c1b4cc5b82719f08f6665a05211205f5f74365e0eb19f543c02139d09417fe1a7befd248face6ae8e9173d5b6a9ac5347ca0fad9fce0f5df3e7949811c786e0ff1ce389074f2e15bdf44efd46a3e420079312bad276a0322a95a538518828e9c6fa6f2cb392776ad6768524628721f311a4f7f41a8cb6019c6ff7668fe4fc96c2d64a24f43891144a96bf68e9373a26813beea80943b2a9c3bc69f966689e9c8ef93d0dfb5115b93308621b8024c9e591132fcc59cfa2dffbd6090f0f65027ab61a53e6564
有效的數位簽章
第二次執行結果:
數位簽章: 64c1c967c1f3e2866d3e4fb724e0fb74401e623be0c0f14d07ae6569edf09ca509613aa051ef5e467b6548fa6084f61fa067812832f1eabb750a1454e082cb9c03886f4e68958bdba785d3dac4a2405b3bf79e47f769c6d5b1a4dca782a280ec81337ce30b7104230058c7b61f97f2793a6b1ef63b685a59c355f05b1a9dd822094685c8445269540063120ca84356017ef3bdcf74fc4176e7704a794bb508764eb09cea3f491daac4f8adb3b958a10c279c056331147d9d0c712003bdb0a2366c487576e2916fc3fe111086c9630fbcad207a04b4f2773234248cccbbf7b191d2928fcb7db38c82f8611373b5c7843681d955a290e0784e7213ccf580bd6fae
有效的數位簽章
以上兩次執行會發現數位簽章都不同,但執行結果是一樣的,都是有效的數位簽章。
若在第47行插入下列程式:
message_to_sign = "虎尾鎮是一個因糖廠而興起的城鎮。"
修改後的程式碼如下: 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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 | from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import rsa, padding def generate_key_pair(): private_key = rsa.generate_private_key( public_exponent=65537, key_size=2048, backend=default_backend() ) public_key = private_key.public_key() return private_key, public_key def sign_message(private_key, message): signature = private_key.sign( message.encode('utf-8'), padding.PSS( mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH ), hashes.SHA256() ) return signature def verify_signature(public_key, message, signature): try: public_key.verify( signature, message.encode('utf-8'), padding.PSS( mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH ), hashes.SHA256() ) return True except Exception as e: print(f"驗證失敗: {e}") return False # Example usage: private_key, public_key = generate_key_pair() message_to_sign = "虎尾鎮,舊稱「大崙腳」,位於臺灣雲林縣中心,是一個因糖廠而興起的城鎮。" signature = sign_message(private_key, message_to_sign) print(f"數位簽章: {signature.hex()}") message_to_sign = "虎尾鎮是一個因糖廠而興起的城鎮。" if verify_signature(public_key, message_to_sign, signature): print("有效的數位簽章") else: print("無效的數位簽章") |
執行結果:
數位簽章: 2498811122ad6bd65cfd4fcaee18c30cc75ee3007571ab8c17438cbc8b4ef1c347df20866c0e77ced3d63d19bb5a2dc87362ea76a6050429b19538ec5f416c6ea058ffc5c003e95f0aa06c15a29869190e438a72a216b226470bd5652bdc2a9949a6b51159a574eb9cfcddb77fa11617d11dcc9e55c3711088079da8bb06d80a658dc041bde272e2a1bd96a0eb80561410701aed2f22d93e68ea71a390e391093f43d9a8952005e526c174c406d9b5624298d105854282d9cf116d246075cc0b748b5f75ec7f0d860757ae16cf860c1791cef2ba3fab6a52bf6ec45c171d7cd38f5360dba55c0d23ed3e837ccc639bec923f207cc71ba9f42fbff6905fe714d7
驗證失敗:
無效的數位簽章
以上範例告訴我們若文件內容被修改,則驗證將失敗。
沒有留言:
張貼留言