在开始构建区块链档案管理系统之前,必须准备好所有必要的运行环境。本方案采用Python作为后端开发语言,利用Ganache搭建本地以太坊区块链网络,使用IPFS作为去中心化存储层。请严格按照以下步骤操作,确保环境版本一致以避免兼容性问题。
首先需要安装Python 3.8及以上版本。打开终端或命令提示符,输入以下命令检查Python版本:
python --version
如果未安装,请前往Python官网下载对应操作系统的安装包并安装。安装时务必勾选"Add Python to PATH"选项。
Ganache用于快速搭建本地区块链网络,方便测试智能合约。请直接访问https://trufflesuite.com/ganache/下载Windows或Mac版本。安装完成后启动Ganache,点击"QUICKSTART"按钮启动一个默认的本地网络,默认RPC端口为7545。保持Ganache运行状态,不要关闭。
IPFS用于存储档案文件实体。访问https://docs.ipfs.tech/install/command-line/official-distributions下载对应系统的IPFS安装包。安装完成后,在终端输入以下命令初始化节点:
ipfs init
启动IPFS守护进程(这步必须做,否则无法上传文件):
ipfs daemon
注意:请开启一个新的终端窗口运行上述命令,并保持该窗口运行。此时IPFS服务将在127.0.0.1:5001监听API请求。
在项目目录下,使用pip安装Web3.py(用于与区块链交互)和ipfshttpclient(用于与IPFS交互)。执行以下命令:
pip install web3==6.11.3 ipfshttpclient==0.8.0
智能合约是区块链档案系统的核心,负责记录档案的哈希指纹,确保数据不可篡改。我们将编写一个Solidity合约,并使用Remix IDE进行编译和部署。
打开浏览器访问https://remix.ethereum.org/。在左侧文件管理栏中,新建一个文件名为ArchiveRegistry.sol。将以下完整的Solidity代码复制进去,不要遗漏任何分号或括号:
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract ArchiveRegistry {
// 定义档案结构体
struct Archive {
string ipfsHash; // IPFS存储地址
uint256 timestamp; // 上传时间戳
address uploader; // 上传者地址
string fileHash; // 文件内容的SHA256哈希值,用于验证完整性
}
// 映射:档案ID => 档案详情
mapping(string => Archive) private archives;
// 记录所有档案ID的数组
string[] public archiveList;
// 事件:档案上传时触发,便于前端监听
event ArchiveUploaded(string id, string ipfsHash, address indexed uploader);
// 上传档案函数
function uploadArchive(string memory _id, string memory _ipfsHash, string memory _fileHash) public {
require(bytes(_id).length > 0, "ID cannot be empty");
require(bytes(archives[_id].ipfsHash).length == 0, "Archive already exists");
archives[_id] = Archive({
ipfsHash: _ipfsHash,
timestamp: block.timestamp,
uploader: msg.sender,
fileHash: _fileHash
});
archiveList.push(_id);
emit ArchiveUploaded(_id, _ipfsHash, msg.sender);
}
// 验证并获取档案信息
function getArchive(string memory _id) public view returns (fileHash, uint256, address) {
require(bytes(archives[_id].ipfsHash).length > 0, "Archive not found");
return (archives[_id].ipfsHash, archives[_id].timestamp, archives[_id].uploader, archives[_id].fileHash);
}
// 检查档案是否存在
function archiveExists(string memory _id) public view returns (bool) {
return bytes(archives[_id].ipfsHash).length > 0;
}
}
```
在Remix界面中,点击左侧第三个图标(Solidity Compiler),确保Compiler版本选择为0.8.0或更高版本,点击Compile ArchiveRegistry.sol按钮。如果编译成功,按钮下方会出现绿色对勾。

接着点击左侧第四个图标(Deploy & Run Transactions)。在Environment下拉菜单中选择Web3 Provider,弹出框中输入http://127.0.0.1:7545,点击OK。此时你会看到Account列表与Ganache中的账户一致。
点击Deploy按钮。部署成功后,下方会出现Deployed Contracts区域,展开后可以看到我们编写的uploadArchive和getArchive函数。记录下该合约的地址(在Deployed Contracts标题下方,以0x开头的字符串),后续Python代码需要用到。
现在我们编写Python脚本来连接区块链和IPFS,实现档案的上传和验证逻辑。请在本地创建一个名为archive_manager.py的文件,并填入以下代码。
请将代码中的YOUR_CONTRACT_ADDRESS替换为上一步在Remix中部署得到的合约地址。
```python
import hashlib
import json
import os
from web3 import Web3
import ipfshttpclient
配置部分
GANACHE_URL = "http://127.0.0.1:7545"
CONTRACT_ADDRESS = "YOUR_CONTRACT_ADDRESS" 请替换为实际合约地址
CONTRACT_ABI = json.loads('''[
{
"inputs": [{"internalType": "string", "name": "_id", "type": "string"}, {"internalType": "string", "name": "_ipfsHash", "type": "string"}, {"internalType": "string", "name": "_fileHash", "type": "string"}],
"name": "uploadArchive", "outputs": [], "stateMutability": "nonpayable", "type": "function"
},
{
"inputs": [{"internalType": "string", "name": "_id", "type": "string"}],
"name": "getArchive", "outputs": [{"internalType": "string", "name": "ipfsHash", "type": "string"}, {"internalType": "uint256", "name": "timestamp", "type": "uint256"}, {"internalType": "address", "name": "uploader", "type": "address"}, {"internalType": "string", "name": "fileHash", "type": "string"}],
"stateMutability": "view", "type": "function"
},
{
"inputs": [{"internalType": "string", "name": "_id", "type": "string"}],
"name": "archiveExists", "outputs": [{"internalType": "bool", "name": "", "type": "bool"}],
"stateMutability": "view", "type": "function"
}
]
''')
连接节点
def connect_nodes():
连接Ganache
w3 = Web3(Web3.HTTPProvider(GANACHE_URL))
if not w3.is_connected():
raise Exception("无法连接到Ganache,请确认软件已运行")
连接IPFS
client = ipfshttpclient.connect('/ip4/127.0.0.1/tcp/5001')
初始化合约实例
contract = w3.eth.contract(address=CONTRACT_ADDRESS, abi=CONTRACT_ABI)
return w3, client, contract
计算文件SHA256哈希
def calculate_file_hash(file_path):
sha256_hash = hashlib.sha256()
with open(file_path, "rb") as f:
for byte_block in iter(lambda: f.read(4096), b""):
sha256_hash.update(byte_block)
return sha256_hash.hexdigest()
上传档案函数
def upload_archive(file_path, archive_id):
w3, client, contract = connect_nodes()
1. 计算文件哈希
file_hash = calculate_file_hash(file_path)
print(f"文件哈希计算完成: {file_hash}")
2. 上传文件到IPFS
res = client.add(file_path)
ipfs_hash = res['Hash']
print(f"文件已上传至IPFS, Hash: {ipfs_hash}")
3. 构建交易并上链
w3.eth.default_account = w3.eth.accounts[0] 使用Ganache第一个账户
tx_hash = contract.functions.uploadArchive(archive_id, ipfs_hash, file_hash).transact()
等待交易确认
tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
print(f"交易成功打包,区块号: {tx_receipt.blockNumber}")
print(f"档案ID [{archive_id}] 归档成功!")
验证档案函数
def verify_archive(archive_id, file_path_to_check):
w3, client, contract = connect_nodes()
1. 从链上获取档案信息
if not contract.functions.archiveExists(archive_id).call():
print("错误:该档案ID不存在于区块链上")
return
data = contract.functions.getArchive(archive_id).call()
chain_ipfs_hash = data[0]
chain_file_hash = data[3]
print(f"链上记录IPFS Hash: {chain_ipfs_hash}")
print(f"链上记录文件Hash: {chain_file_hash}")
2. 计算本地待验证文件的哈希
local_file_hash = calculate_file_hash(file_path_to_check)
print(f"本地文件计算Hash: {local_file_hash}")
3. 对比验证
if local_file_hash == chain_file_hash:
print("【验证成功】文件完整未被篡改,且来源可信。")
else:
print("【验证失败】文件已被篡改或不匹配。")
if __name__ == "__main__":
测试用例:确保当前目录下有一个test.txt文件
创建测试文件
with open("test.txt", "w") as f:
f.write("这是重要的机密档案文件内容。")
print(" 开始上传档案 ")
upload_archive("test.txt", "ARCHIVE_001")
print("\n 开始验证档案 ")
verify_archive("ARCHIVE_001", "test.txt")
```
代码编写完成后,我们进行实际的上传和篡改测试,以验证区块链系统的防篡改能力。
确保Ganache和IPFS Daemon都在运行。在终端中进入archive_manager.py所在目录,执行以下命令:
python archive_manager.py
观察终端输出。你将看到脚本自动计算文件哈希,将文件上传至本地IPFS节点,然后通过Web3.py向Ganache发起交易。稍等几秒,Ganache界面上的TRANSACTIONS栏会出现新的交易记录,且Python终端会提示"交易成功打包"和"归档成功"。
脚本在执行上传后会自动执行验证步骤。此时,本地文件哈希与链上记录哈希一致,终端会输出【验证成功】文件完整未被篡改,且来源可信。
为了证明区块链的作用,我们手动修改刚才上传的文件。打开test.txt,修改其中的内容并保存(例如改为"这是被黑客修改后的虚假内容")。
修改Python脚本底部的if __name__ == "__main__":部分,注释掉上传代码,只保留验证代码:
```python
if __name__ == "__main__":
upload_archive("test.txt", "ARCHIVE_001") 注释掉上传
verify_archive("ARCHIVE_001", "test.txt")
```
再次运行脚本:
python archive_manager.py
此时终端输出的本地文件哈希已经改变,不再等于链上存储的原始哈希。系统将输出【验证失败】文件已被篡改或不匹配。这证明了即使文件存储在本地服务器,只要链上的哈希指纹对不上,任何篡改行为都能被立即识别。
在实操过程中,如果遇到报错,请参考以下解决方案:
GANACHE_URL端口号。ipfs daemon命令正在终端运行。如果在Windows上遇到防火墙提示,请允许Python。
访问私有网络。archive_id参数,使用一个新的ID(如"ARCHIVE_002")进行测试。pip install web3 ipfshttpclient,确保安装目录与运行脚本的Python环境一致。