You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Solidity智能合约中如何用私钥解密加密字符串实现乐透代币动态返回tokenURI

乐透类NFT盲盒解密方案实现

核心选型说明

你这个场景更适合用对称加密算法实现,不要用非对称加密的私钥:非对称加密私钥一旦上链公开就完全失去作用,而对称加密的密钥只需要在活动结束后公开,完全匹配你的需求,你参考逻辑里的privateKey实际对应对称加密的密钥。

具体实现步骤

  • 链下预生成所有代币对应的原始URI,使用选定的对称加密算法(推荐AES-128-CTR,gas消耗低、解密速度快)和提前生成的密钥加密所有URI得到密文,将密文批量存入合约的_tokenURIs映射中
  • 活动未结束时,密钥字段为空,调用tokenURI统一返回预设的盲盒默认URI
  • 所有代币售卖完成、活动正式结束后,管理员调用专用的密钥设置接口将对称密钥写入合约
  • 密钥写入后,所有tokenURI调用会自动运行解密逻辑,返回对应代币的真实URI

完整代码示例

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
// 这里导入已经过审计的Solidity AES实现库即可
import "./AES.sol";

contract LottoNFT is ERC721 {
    mapping(uint256 => string) private _tokenURIs;
    string public defaultUri;
    string public encryptionKey;
    address public owner;

    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;
    }

    constructor(string memory name_, string memory symbol_, string memory _defaultUri) ERC721(name_, symbol_) {
        defaultUri = _defaultUri;
        owner = msg.sender;
    }

    // 管理员批量设置加密后的URI
    function setBatchEncryptedURI(uint256[] calldata tokenIds, string[] calldata encryptedUris) external onlyOwner {
        require(tokenIds.length == encryptedUris.length, "Length mismatch");
        for (uint256 i = 0; i < tokenIds.length; i++) {
            _tokenURIs[tokenIds[i]] = encryptedUris[i];
        }
    }

    // 活动结束后管理员设置加密密钥
    function revealKey(string calldata key) external onlyOwner {
        require(bytes(encryptionKey).length == 0, "Key already revealed");
        encryptionKey = key;
    }

    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        _requireMinted(tokenId);
        if (bytes(encryptionKey).length == 0) {
            return defaultUri;
        }
        // 解密逻辑需和链下加密逻辑完全匹配,IV可选择拼接在密文前/后,解密时先拆分
        return AES.decrypt(_tokenURIs[tokenId], encryptionKey);
    }
}

关键注意事项

  • 加密时用到的初始向量(IV)可以选择拼接在密文的开头或结尾,存入_tokenURIs,解密时先拆分出IV再进行解密,避免固定IV被暴力破解
  • 密钥写入合约后是完全公开的,必须确认所有代币都已售出、没有剩余未售代币后再调用revealKey接口,避免用户提前根据解密后的URI筛选高价值代币
  • 提前测试解密逻辑的gas消耗,避免URI过长时解密操作超出块gas限制导致tokenURI调用失败
  • 链下加密完成后务必先用测试环境验证链上解密结果和原始URI完全一致,再部署正式合约

内容的提问来源于stack exchange,提问作者ssk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 17:15:01