-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsearch.xml
139 lines (139 loc) · 211 KB
/
search.xml
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title><![CDATA[FISCO-BCOS 源代码研读(一) —— 共识算法模块]]></title>
<url>%2F2019%2F12%2F02%2FFISCO-BCOS-source-code-reading-libconsensus%2F</url>
<content type="text"><![CDATA[一、版本 fisco-bcos:2.1.0 commit:cb68124d4fbf3df563a57dfff5f0c6eedc1419cc branch:master 二、共识模块框架 FISCO BCOS实现了一套可扩展的共识框架,可插件化扩展不同的共识算法,目前支持 PBFT(Practical Byzantine Fault Tolerance) 和 Raft(Replication and Fault Tolerant) 共识算法,共识模块框架如下图: 共识模块框架 Sealer线程 交易打包线程,负责从交易池取交易,并基于节点最高块打包交易,产生新区块,产生的新区块交给Engine线程处理,PBFT和Raft的交易打包线程分别为PBFTSealer和RaftSealer。 Engine线程 共识线程,负责从本地或通过网络接收新区块,并根据接收的共识消息包完成共识流程,最终将达成共识的新区块写入区块链(BlockChain),区块上链后,从交易池中删除已经上链的交易,PBFT和Raft的共识线程分别为PBFTEngine和RaftEngine。 三、依赖模块 四、共识算法模块文件结构 ConsensusInterface Common ConsensusEngineBase 1. 构造函数 2. 继承重写函数 3. 其他成员函数 4. protect属性成员 Sealer 1. 构造函数/析构函数 2. 成员函数 3. protect属性成员 五、BCOS中PBFT模块是如何使用这些接口的 Common PBFTMsgCache PBFTReqCache TimeManager PBFTSealer 1. 构造函数 2. 重写继承成员函数 3. 其他重要成员函数 PBFTEngine 1. 构造函数 2. 其他重要函数 持续监听消息队列 handleMsg判断请求类型 处理Prepare请求 处理Sign请求 处理Commit请求 处理ViewChange请求 checkAndCommit checkAndSave checkAndChangeView 三、依赖模块 sync blockverifier p2p security 四、共识算法模块文件结构 123456789101112131415161718192021222324.├── CMakeLists.txt # cmake 构建配置├── Common.h # 基础数据结构、异常处理├── ConsensusEngineBase.cpp # 共识基础引擎的实现├── ConsensusEngineBase.h # 共识基础引擎的头文件├── ConsensusInterface.h # 共识接口/基类├── Sealer.cpp # 共识打包提交实现├── Sealer.h # 共识打包提交接口├── pbft # PBFT共识模块│ ├── Common.h│ ├── PBFTEngine.cpp│ ├── PBFTEngine.h│ ├── PBFTMsgCache.h│ ├── PBFTReqCache.cpp│ ├── PBFTReqCache.h│ ├── PBFTSealer.cpp│ ├── PBFTSealer.h│ └── TimeManager.h└── raft # Raft共识模块 ├── Common.h ├── RaftEngine.cpp ├── RaftEngine.h ├── RaftSealer.cpp └── RaftSealer.h ConsensusInterface ConsensusInterface.h作为一个基类为最顶端类包,其他类继承该类的虚函数进行override。 Class ConsensusInterface主要包含了以下两种: 共识模块控制 12345678910111213141516171819// 共识模块的开关virtual void start() = 0;virtual void stop() = 0;// 共识模块状态virtual const std::string consensusStatus() = 0;// 协议ID,当handler注册为p2p模块时使用virtual PROTOCOL_ID const& protocolId() const = 0;/// update the context of PBFT after commit a block into the block-chainvirtual void reportBlock(dev::eth::Block const& block) = 0;// 群组IDvirtual GROUP_ID groupId() const { return 0; };// 一个块内最多交易数(默认1000)virtual uint64_t maxBlockTransactions() { return 1000; }// view/view changevirtual VIEWTYPE view() const { return 0; }virtual VIEWTYPE toView() const { return 0; } 共识节点控制 12345678// 共识节点列表virtual h512s sealerList() const = 0;virtual void appendSealer(h512 const& _sealer) = 0;// 节点类型 共识节点/观察者节点virtual NodeAccountType accountType() = 0;virtual void setNodeAccountType(NodeAccountType const&) = 0;virtual IDXTYPE nodeIdx() const = 0; Common Common.h文件主要定义了命名空间consensus的共识与节点的状态、异常处理,以及节点的类型NodeAccountType、打包成块结构体Sealing : 1234567struct Sealing{ dev::eth::Block block; /// hash set for filter fetched transactions h256Hash m_transactionSet; dev::blockverifier::ExecutiveContext::Ptr p_execContext;}; ConsensusEngineBase 定义了ConsensusEngineBase类,该类继承了 Woker 类和 ConsensusInterface 类: 1. 构造函数 1234567891011121314151617181920212223242526272829// ConsensusEngineBase类构造函数ConsensusEngineBase(std::shared_ptr<dev::p2p::P2PInterface> _service, // 指定p2p服务 std::shared_ptr<dev::txpool::TxPoolInterface> _txPool, // 指定交易池 std::shared_ptr<dev::blockchain::BlockChainInterface> _blockChain,// 指定区块链 std::shared_ptr<dev::sync::SyncInterface> _blockSync, // 区块同步机制 std::shared_ptr<dev::blockverifier::BlockVerifierInterface> _blockVerifier, PROTOCOL_ID const& _protocolId, // 协议id KeyPair const& _keyPair, // 密钥对 dev::h512s const& _sealerList = dev::h512s()) // 共识节点,默认为空 : Worker("ConsensusEngine", 0), // Worker类初始化,类似于监听 m_service(_service), // 对protected成员进行赋值 m_txPool(_txPool), m_blockChain(_blockChain), m_blockSync(_blockSync), m_blockVerifier(_blockVerifier), m_consensusBlockNumber(0), m_protocolId(_protocolId), m_keyPair(_keyPair), m_sealerList(_sealerList) { assert(m_service && m_txPool && m_blockChain && m_blockSync && m_blockVerifier); if (m_protocolId == 0) BOOST_THROW_EXCEPTION(dev::eth::InvalidProtocolID() << errinfo_comment("Protocol id must be larger than 0")); m_groupId = dev::eth::getGroupAndProtocol(m_protocolId).first; std::sort(m_sealerList.begin(), m_sealerList.end()); // 对sealerList排序 }// 析构函数virtual ~ConsensusEngineBase() { stop(); } 2. 继承重写函数 1234567891011121314151617// 共识节点操作dev::h512s sealerList() const override;void appendSealer(h512 const& _sealer) override;const std::string consensusStatus() override;PROTOCOL_ID const& protocolId() const override { return m_protocolId; }GROUP_ID groupId() const override { return m_groupId; }// 节点类型:共识节点/观察者节点NodeAccountType accountType() override { return m_accountType; }void setNodeAccountType(dev::consensus::NodeAccountType const& _accountType) override;// 当前节点在sealerList所在位IDXTYPE nodeIdx() const override { return m_idx; }virtual void reportBlock(dev::eth::Block const&) override {}void start() override;void stop() override; 3. 其他成员函数 1234567891011121314151617181920212223242526272829303132// 构造一个JSON object,内含共识的基本属性void getBasicConsensusStatus(Json::Value& status_obj) const;// 设定是否允许增加区块void setAllowFutureBlocks(bool isAllowFutureBlocks);// 最小的有效节点数量 m_nodeNum所有节点,m_f至少有效节点数IDXTYPE minValidNodes() const { return m_nodeNum - m_f; }// 更新sealer节点数量virtual void resetConfig() { m_nodeNum = m_sealerList.size(); }// 交易进入交易池void dropHandledTransactions(dev::eth::Block const& block);// 通过index获取Sealerinline h512 getSealerByIndex(size_t const& index) const// message/session/data -> requestinline bool decodeToRequests(T& req, std::shared_ptr<dev::p2p::P2PMessage> message, std::shared_ptr<dev::p2p::P2PSession> session)inline bool decodeToRequests(T& req, bytesConstRef data)// 执行打包区块dev::blockverifier::ExecutiveContext::Ptr executeBlock(dev::eth::Block& block); // 检查block是否有效:区块交易数量、时间戳、区块高度、父区块存在virtual void checkBlockValid(dev::eth::Block const& block);// 更新共识节点/p2p监听节点list/区块包含最大交易数virtual void updateConsensusNodeList();virtual void updateNodeListInP2P();virtual void updateMaxBlockTransactions();private:// 区块是否已经存在,使用hash查询bool blockExists(h256 const& blockHash) 4. protect属性成员 12345678910111213141516171819202122232425262728293031 std::atomic<uint64_t> m_maxBlockTransactions = {1000}; /// 主要参数 std::shared_ptr<dev::p2p::P2PInterface> m_service; // p2p服务handler std::shared_ptr<dev::txpool::TxPoolInterface> m_txPool; // 交易池handler std::shared_ptr<dev::blockchain::BlockChainInterface> m_blockChain; // 区块链handler std::shared_ptr<dev::sync::SyncInterface> m_blockSync; // 区块同步handler std::shared_ptr<dev::blockverifier::BlockVerifierInterface> m_blockVerifier; // 区块验证 PROTOCOL_ID m_protocolId; // 定义用哪一种协议 KeyPair m_keyPair; // 密钥对(私钥/公钥/地址) mutable SharedMutex m_sealerListMutex; // seal list 独占锁 dev::h512s m_sealerList; // seal list 共识节点列表/// 其他参数// 记录区块 std::atomic<int64_t> m_consensusBlockNumber = {0}; // 等待交易的区块 dev::eth::BlockHeader m_highestBlock; // 最高区块// 关于节点 std::atomic<IDXTYPE> m_nodeNum = {0}; // 节点个数 std::atomic<IDXTYPE> m_f = {0}; // 至少正确的节点个数 GROUP_ID m_groupId; // 群组号,一般是从protocolID得出 std::atomic<NodeAccountType> m_accountType = {NodeAccountType::ObserverAccount};//该节点类型 std::atomic<IDXTYPE> m_idx = {0}; // 该节点id// flags bool m_allowFutureBlocks = true; // 是否允许添加新区块 bool m_startConsensusEngine = false; // 共识是否启动 bool m_omitEmptyBlock = true; // 是否删除空区块 std::atomic_bool m_cfgErr = {false}; // 是否有错误 /// node list record when P2P last update std::string m_lastNodeList; // 记录上一次P2P通信的节点列表 std::atomic<IDXTYPE> m_connectedNode = {0}; // 已连接的节点ID Sealer 定义了Sealer 类,继承 Worker ,开启shared_ptr支持。 1. 构造函数/析构函数 1234567891011121314151617181920// 构造函数Sealer(std::shared_ptr<dev::txpool::TxPoolInterface> _txPool, // 交易池模块 std::shared_ptr<dev::blockchain::BlockChainInterface> _blockChain, // 区块链模块 std::shared_ptr<dev::sync::SyncInterface> _blockSync) // 区块同步模块 : Worker("Sealer", 0), // Worker监听 m_txPool(_txPool), m_blockSync(_blockSync), m_blockChain(_blockChain), m_consensusEngine(nullptr){ assert(m_txPool && m_blockSync && m_blockChain); if (m_txPool->status().current > 0) { m_syncTxPool = true; } // 注册一个handler,一旦新的交易进入,引发调用 m_tqReady = m_txPool->onReady([=]() { this->onTransactionQueueReady(); }); m_blockSubmitted = m_blockChain->onReady([=](int64_t) { this->onBlockChanged(); });}virtual ~Sealer() noexcept { stop(); } 2. 成员函数 123456789101112131415161718192021222324252627282930313233343536373839// Sealer模块的开关virtual void start();virtual void stop();// 回调函数 通知所有线程virtual void onTransactionQueueReady();virtual void onBlockChanged();// 打包时添加额外的数据void setExtraData(std::vector<bytes> const& _extra) { m_extraData = _extra; }std::vector<bytes> const& extraData() const { return m_extraData; }// 判断是否需要重置打包virtual bool shouldResetSealing();// 重新打包inline void resetSealingBlock(h256Hash const& filter, bool resetNextLeader);void resetSealingBlock(Sealing& sealing, h256Hash const& filter, bool resetNextLeader);void resetBlock(dev::eth::Block& block, bool resetNextLeader = false);// 返回共识接口std::shared_ptr<dev::consensus::ConsensusInterface> const consensusEngine();void reportNewBlock();// 是打包还是继续等待virtual bool shouldSeal();virtual bool shouldWait(bool const& wait) const;// 从交易池取交易void loadTransactions(uint64_t const& transToFetch);virtual bool checkTxsEnough(uint64_t maxTxsCanSeal)// 以免下一个leader打包好了,最新的区块还没达成共识virtual bool canHandleBlockForNextLeader() { return true; }virtual bool reachBlockIntervalTime() { return false; }virtual void handleBlock() {}virtual bool shouldHandleBlock() { return true; }virtual void doWork(bool wait);void doWork() override { doWork(true); }bool isBlockSyncing(); 3. protect属性成员 123456789101112131415161718192021222324252627/// 主要参数 std::shared_ptr<dev::txpool::TxPoolInterface> m_txPool; // 交易池模块 std::shared_ptr<dev::sync::SyncInterface> m_blockSync; // 区块同步模块 std::shared_ptr<dev::blockchain::BlockChainInterface> m_blockChain; // 区块链模块 std::shared_ptr<dev::consensus::ConsensusInterface> m_consensusEngine;// 所属共识引擎/// 其他参数 Sealing m_sealing; // 目前正在打包的块,包括头、交易、执行上下文 mutable SharedMutex x_sealing; // 打包独占锁 std::vector<bytes> m_extraData; // 额外的数据// 同步相关 std::condition_variable m_signalled; // 通知其他所有线程的信号量 std::condition_variable m_blockSignalled; // 通知其他所有线程区块的信号量 Mutex x_signalled; // 信号独占锁 Mutex x_blocksignalled; // 信号独占锁 std::atomic<bool> m_syncTxPool = {false}; // 是否在调用 syncTransactionQueue std::atomic<bool> m_syncBlock = {false}; // 是否有新的区块提交到区块链 bool m_remoteWorking = false; // 远程的worker是否有被重置 bool m_startConsensus = false; // 共识是否开启 Handler<> m_tqReady; // 消息列表就绪 Handler<int64_t> m_blockSubmitted; // 有区块提交 uint64_t m_maxBlockCanSeal = 1000; // 单个区块最高可打包多少个交易 mutable SharedMutex x_maxBlockCanSeal; // 独占锁 五、BCOS中PBFT模块是如何使用这些接口的 先看PBFT模块的文件结构,和共识模板相似,有common,有Engine,有Sealer。 12345678910pbft├── Common.h├── PBFTEngine.cpp├── PBFTEngine.h # 共识引擎接口├── PBFTMsgCache.h # 消息缓存├── PBFTReqCache.cpp├── PBFTReqCache.h # 请求缓存 ├── PBFTSealer.cpp├── PBFTSealer.h # 块打包└── TimeManager.h # 时间管理模块,主要记录上次共识/签名的时间 PBFT共识主要包括Pre-prepare、Prepare和Commit三个阶段: Pre-prepare:负责执行区块,产生签名包,并将签名包广播给所有共识节点; Prepare:负责收集签名包,某节点收集满2*f+1的签名包后,表明自身达到可以提交区块的状态,开始广播Commit包; Commit:负责收集Commit包,某节点收集满2*f+1的Commit包后,直接将本地缓存的最新区块提交到数据库。 Common Common 定义了PBFT的几种消息形式:PBFTMsgPacket、PBFTMsg、PreapareReq、SignReq 、CommitReq、ViewChangeReq 。 PBFTMsgPacket 定义了PBFT整个消息的属性,有发送节点的id、所在位、消息类型(prepare、commit、sign)、TTL、data、时间戳,并定义了消息的编码和解码,使用到了 libdevcore 的RLP 类型; PBFTMsg 是消息基础结构,定义了区块链高度、当前view、发送节点所在位,时间戳、区块哈希、签名等,并定义了消息的编码和解码,使用到了 libdevcore 的RLP 类型; PreapareReq 是在PBFTMsg基础上的扩展,并给出四种不同的构造方法: 使用PBFTMsg模板,参数为keyPair、区块链高、当前view、节点所在位、区块哈希值; 从另一个特定的PrepareReq进行构造,参数为另一个prepareReq、keyPair、当前view、节点所在位; 从给定的区块、keypair、view、idx进行构造; 从给定区块以及执行打包结果,更新PrepareReq; SignReq是在PBFTMsg基础上的扩展, 定义了一种构造方法,参数为PrepareReq、keyPair、idx; CommitReq是在PBFTMsg基础上的扩展,定义了一种构造方法,参数为PrepareReq、keyPair、idx; ViewChangeReq是在PBFTMsg基础上的扩展,定义了一种构造方法,参数为 keyPair、区块链高、view、idx、区块哈希; PBFTMsgCache 定义了消息缓存的结构PBFTMsgCache,都是以消息队列的形式实现,并实现了插入缓存的方式,类成员有: 1234567891011121314151617/// 四种消息的缓存QueueSet<std::string> m_knownPrepare;QueueSet<std::string> m_knownSign;QueueSet<std::string> m_knownCommit;QueueSet<std::string> m_knownViewChange;// 缓存读写锁mutable SharedMutex x_knownPrepare;mutable SharedMutex x_knownSign;mutable SharedMutex x_knownCommit;mutable SharedMutex x_knownViewChange;// 缓存最大值static const unsigned c_knownPrepare = 1024;static const unsigned c_knownSign = 1024;static const unsigned c_knownCommit = 1024;static const unsigned c_knownViewChange = 1024; 此外,定义了广播消息缓存类 PBFTBroadcastCache ,根据发送节点id的哈希存储收到的消息缓存(hashmap)。 PBFTReqCache 定义了请求缓存类型 PBFTReqCache ,有以下成员: 123456789101112131415161718192021/// prepare请求缓存PrepareReq m_prepareCache = PrepareReq();/// raw prepare请求缓存PrepareReq m_rawPrepareCache;/// 签名请求signReq(maps between hash and sign requests) 缓存std::unordered_map<h256, std::unordered_map<std::string, SignReq>> m_signCache;/// cache for received-viewChange requests(maps between view and view change requests)std::unordered_map<VIEWTYPE, unordered_map<IDXTYPE, ViewChangeReq>> m_recvViewChangeReq;/// cache for commited requests(maps between hash and commited requests)std::unordered_map<h256, std::unordered_map<std::string, CommitReq>> m_commitCache;/// cache for prepare request need to be backup and savedPrepareReq m_committedPrepareCache;/// cache for the future prepare cache/// key: block hash, value: the cached future prepearestd::unordered_map<uint64_t, std::shared_ptr<PrepareReq>> m_futurePrepareCache; 此外还实现了对请求缓存进行增删改查的方法,以及判断是否要进入viewchange。 TimeManager 该模块主要作用是记录时间,设定timeout。 PBFTSealer 定义了PBFTSealer类,该类直接继承Sealer。 在继承Sealer类的同时,增加了几个新的成员变量 12345678std::shared_ptr<PBFTEngine> m_pbftEngine; // 指向特定的PBFT共识引擎uint64_t m_lastTimeoutTx = 0; // 能产生timeout的最小交易数uint64_t m_maxNoTimeoutTx = 0; // 不产生timeout的最大交易数int64_t m_timeoutCount = 0; // 记录有多少次timeoutuint64_t m_lastBlockNumber = 0; // 最后一个Block数bool m_enableDynamicBlockSize = true; // 是否动态调整区块大小float m_blockSizeIncreaseRatio = 0.5; // 区块大小增长率 1. 构造函数 构造函数调用基类Sealer 的构造函数,并对PBFTSealer指向的PBFTEngine进行初始化。 1234567891011121314151617// 略去函数名和函数参数{ // 初始化指定engine m_consensusEngine = std::make_shared<PBFTEngine>(_service, _txPool, _blockChain, _blockSync, _blockVerifier, _protocolId, _baseDir, _key_pair, _sealerList); m_pbftEngine = std::dynamic_pointer_cast<PBFTEngine>(m_consensusEngine); /// 绑定回调函数,当timeout的时候重置block m_pbftEngine->onViewChange(boost::bind(&PBFTSealer::resetBlockForViewChange, this)); /// 绑定回调函数,当下一个leader收到了prepare block时重置block m_pbftEngine->onNotifyNextLeaderReset( boost::bind(&PBFTSealer::resetBlockForNextLeader, this, _1)); /// set thread name for PBFTSealer std::string threadName = "PBFTSeal-" + std::to_string(m_pbftEngine->groupId()); setName(threadName);} 2. 重写继承成员函数 在这里对继承的Sealer成员函数进行了重写: 12345678910111213141516171819202122232425262728void start() override{ // 判断是否使用区块大小动态调整 // 启用Engine // 启用Sealer}void stop() override{ // 关闭Sealer // 关闭Engine}bool shouldResetSealing() override{ // 只有leader需要重置sealing}/// 关键入口void handleBlock() override{ // 1. 判断是否打包过多交易了,是的话重置sealing,通知其他线程 // 2. setBlock,填充区块头,计算默克尔树 // 3. 调用Engine的generatePrepare方法,该方法即为PBFT中Pre-Prepare阶段}bool shouldSeal() override{ // 该节点是否能产生块}bool shouldHandleBlock() override{ // 只有leader节点可以产生最新的区块}bool reachBlockIntervalTime() override;bool canHandleBlockForNextLeader() override; 3. 其他重要成员函数 123456789// 回调函数void resetBlockForViewChange(){ /// view change时重置block // }void resetBlockForNextLeader(dev::h256Hash const& filter){ /// 为下一个leader重置block} PBFTEngine 定义了PBFTEngine类,直接继承了共识模板 ConsensusEngineBase 类,增加了几个成员变量 123456789101112131415161718192021222324252627282930313233343536373839404142434445protected: std::atomic<VIEWTYPE> m_view = {0}; std::atomic<VIEWTYPE> m_toView = {0}; std::string m_baseDir; std::atomic_bool m_leaderFailed = {false}; std::atomic_bool m_notifyNextLeaderSeal = {false}; // 备份msg到数据库 std::shared_ptr<dev::db::LevelDB> m_backupDB = nullptr; /// static vars static const std::string c_backupKeyCommitted; static const std::string c_backupMsgDirName; static const unsigned c_PopWaitSeconds = 5; // 广播消息/请求缓存 std::shared_ptr<PBFTBroadcastCache> m_broadCastCache; std::shared_ptr<PBFTReqCache> m_reqCache; TimeManager m_timeManager; PBFTMsgQueue m_msgQueue; // 消息队列 mutable Mutex m_mutex; // 线程信号 std::condition_variable m_signalled; Mutex x_signalled; // 回调函数 std::function<void()> m_onViewChange = nullptr; std::function<void(dev::h256Hash const& filter)> m_onNotifyNextLeaderReset = nullptr; std::function<void(uint64_t const& sealingTxNumber)> m_onTimeout = nullptr; std::function<void( uint64_t const& blockNumber, uint64_t const& sealingTxNumber, unsigned const& changeCycle)> m_onCommitBlock = nullptr; /// for output time-out caused viewchange /// m_fastViewChange is false: output viewchangeWarning to indicate PBFT consensus timeout std::atomic_bool m_fastViewChange = {false}; uint8_t maxTTL = MAXTTL; /// map between nodeIdx to view mutable SharedMutex x_viewMap; std::map<IDXTYPE, VIEWTYPE> m_viewMap; std::atomic<uint64_t> m_sealingNumber = {0}; 1. 构造函数 构造函数调用ConsensusEngineBase 的构造函数 12345678910111213141516// 略去函数名与参数部分{ PBFTENGINE_LOG(INFO) << LOG_DESC("Register handler for PBFTEngine"); // p2p服务绑定回调函数 onRecvPBFTMessage m_service->registerHandlerByProtoclID( m_protocolId, boost::bind(&PBFTEngine::onRecvPBFTMessage, this, _1, _2, _3)); // 初始化广播/请求缓存 m_broadCastCache = std::make_shared<PBFTBroadcastCache>(); m_reqCache = std::make_shared<PBFTReqCache>(); /// set thread name for PBFTEngine std::string threadName = "PBFT-" + std::to_string(m_groupId); setName(threadName); /// register checkSealerList to blockSync for check SealerList // blockSync服务注册回调函数,在同步的时候进行验证 m_blockSync->registerConsensusVerifyHandler(boost::bind(&PBFTEngine::checkBlock, this, _1));} 2. 其他重要函数 从PBFTSealer模块中看,Sealer 基类重写了Worker 的doWork方法,并对shouldHandle的Block进行了handleBlock,在 handleBlock 函数中调用了Engine模块的generatePrepare方法,发送Prepare消息。该方法只有leader节点才能调用。 123456789101112131415161718192021222324252627282930313233/// 生成一个PrepareReq消息块,广播出去bool PBFTEngine::generatePrepare(Block const& block){ Guard l(m_mutex); m_notifyNextLeaderSeal = false; PrepareReq prepare_req(block, m_keyPair, m_view, nodeIdx()); bytes prepare_data; prepare_req.encode(prepare_data); // 序列化成bytes /// 广播Prepare请求 bool succ = broadcastMsg(PrepareReqPacket, prepare_req.uniqueKey(), ref(prepare_data)); if (succ) { // 如果是空块,view change if (prepare_req.pBlock->getTransactionSize() == 0 && m_omitEmptyBlock) { m_leaderFailed = true; changeViewForFastViewChange(); m_timeManager.m_changeCycle = 0; return true; } // 非空块,leader处理Prepare消息 handlePrepareMsg(prepare_req); } /// reset the block according to broadcast result PBFTENGINE_LOG(INFO) << LOG_DESC("generateLocalPrepare") << LOG_KV("hash", prepare_req.block_hash.abridged()) << LOG_KV("H", prepare_req.height) << LOG_KV("nodeIdx", nodeIdx()) << LOG_KV("myNode", m_keyPair.pub().abridged()); m_signalled.notify_all(); return succ;} 持续监听消息队列 leader广播出Prepare消息之后,其他节点进行消息接收,通过PBFTEngine::workLoop 循环从消息队列m_msgQueue接收、处理消息,m_msgQueue 消息队列在PBFTEngine构造函数初始化的时候p2p服务绑定的回调函数PBFTEngine::onRecvPBFTMessage 进行push: 123456789101112131415161718192021222324252627282930313233343536373839404142// workLoop是重写的Worker类的workLoop方法void PBFTEngine::workLoop(){ while (isWorking()) { try { // 从m_msgQueue消息队列取 std::pair<bool, PBFTMsgPacket> ret = m_msgQueue.tryPop(c_PopWaitSeconds); if (ret.first) { PBFTENGINE_LOG(TRACE) << LOG_DESC("workLoop: handleMsg") << LOG_KV("type", std::to_string(ret.second.packet_id)) << LOG_KV("fromIdx", ret.second.node_idx) << LOG_KV("nodeIdx", nodeIdx()) << LOG_KV("myNode", m_keyPair.pub().abridged()); /// 对接收到的消息进行处理 handleMsg(ret.second); } /// to avoid of cpu problem else if (m_reqCache->futurePrepareCacheSize() == 0) { std::unique_lock<std::mutex> l(x_signalled); m_signalled.wait_for(l, std::chrono::milliseconds(5)); } // 只要node是sealer if (nodeIdx() != MAXIDX) { // 检查是否timeout,如果timeout代表着leader宕机/被控制 // 需要view change checkTimeout(); handleFutureBlock(); // 清除reqcache缓存 collectGarbage(); } } catch (std::exception& _e) { LOG(ERROR) << _e.what(); } }} handleMsg判断请求类型 在以上workLoop可以看出,节点循环对消息使用handleMsg方法进行处理: 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455void PBFTEngine::handleMsg(PBFTMsgPacket const& pbftMsg){ Guard l(m_mutex); PBFTMsg pbft_msg; std::string key; bool succ = false; switch (pbftMsg.packet_id) { case PrepareReqPacket: // Prepare消息 { PrepareReq prepare_req; succ = handlePrepareMsg(prepare_req, pbftMsg); key = prepare_req.uniqueKey(); // 返回签名 pbft_msg = prepare_req; break; } case SignReqPacket: { succ = handleSignMsg(req, pbftMsg); // 其余同上 } case CommitReqPacket: { succ = handleCommitMsg(req, pbftMsg); // 其余同上 } case ViewChangeReqPacket: { succ = handleViewChangeMsg(req, pbftMsg); // 其余同上 } default: { // 略:error } } if (pbftMsg.ttl == 1){ return; } bool height_flag = (pbft_msg.height > m_highestBlock.number()) || (m_highestBlock.number() - pbft_msg.height < 10); if (succ && key.size() > 0 && height_flag) // 消息handle成功,且高度一致 { std::unordered_set<h512> filter; filter.insert(pbftMsg.node_id); /// get the origin gen node id of the request h512 gen_node_id = getSealerByIndex(pbft_msg.idx); if (gen_node_id != h512()) { filter.insert(gen_node_id); } // TTL-1,再次发送 unsigned current_ttl = pbftMsg.ttl - 1; broadcastMsg(pbftMsg.packet_id, key, ref(pbftMsg.data), filter, current_ttl); }} handleMsg执行流程图如下所示: 以下将分别讲述 handlePrepareMsg、handleSignMsg、handleCommitMsg、handleViewChangeMsg四个方法: 处理Prepare请求 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960bool PBFTEngine::handlePrepareMsg(PrepareReq const& prepareReq, std::string const& endpoint){ Timer t; std::ostringstream oss; /// oss 记录log,省略 /// 检查Prepare Request是否有效 auto valid_ret = isValidPrepare(prepareReq, oss); if (valid_ret == CheckResult::INVALID) { return false; } /// 更新当前view updateViewMap(prepareReq.idx, prepareReq.view); if (valid_ret == CheckResult::FUTURE) // 若是未来的prepare请求,为了时间顺序先不处理 { return true; } /// 将当前prepareReq缓存到reqCache m_reqCache->addRawPrepare(prepareReq); // 执行块内请求 Sealing workingSealing; try { execBlock(workingSealing, prepareReq, oss); // old block (has already executed correctly by block sync) if (workingSealing.p_execContext == nullptr && workingSealing.block.getTransactionSize() > 0) { return false; } } catch (std::exception& e) { // 块执行错误,省略 return true; } /// 造成空块是否需要删除 if (needOmit(workingSealing)) { changeViewForFastViewChange(); m_timeManager.m_changeCycle = 0; return true; } /// 使用block执行结果更新请求,对请求进行签名,重新生成一个PrepareReq PrepareReq sign_prepare(prepareReq, workingSealing, m_keyPair); m_reqCache->addPrepareReq(sign_prepare); // log省略 // 使用刚刚重新生成的PrepareReq,生成SignReq,广播出去,并添加到signCache if (!broadcastSignReq(sign_prepare)) { // 广播失败,log省略 } // 从signCache检查已签名的signReq是否达到2/3,如果达到,可以进行commit checkAndCommit(); return true;} handlePrepareMsg方法的处理流程如下图所示: 处理Sign请求 123456789101112131415161718192021222324bool PBFTEngine::handleSignMsg(SignReq& sign_req, PBFTMsgPacket const& pbftMsg){ Timer t; bool valid = decodeToRequests(sign_req, ref(pbftMsg.data)); if (!valid) { return false; } std::ostringstream oss; // oss log 省略 // 判断是否是有效的SignReq auto check_ret = isValidSignReq(sign_req, oss); if (check_ret == CheckResult::INVALID){ return false; } // 更新当前view updateViewMap(sign_req.idx, sign_req.view); if (check_ret == CheckResult::FUTURE){ return true; } // 添加进SignCache m_reqCache->addSignReq(sign_req); // 检查是否达到2/3 checkAndCommit(); return true;} handleSignMsg 方法执行流程如下所示 处理Commit请求 123456789101112131415161718192021222324bool PBFTEngine::handleCommitMsg(CommitReq& commit_req, PBFTMsgPacket const& pbftMsg){ Timer t; bool valid = decodeToRequests(commit_req, ref(pbftMsg.data)); if (!valid) { return false; } std::ostringstream oss; /// oss log 省略 // 判断是否是有效的commit方法 auto valid_ret = isValidCommitReq(commit_req, oss); if (valid_ret == CheckResult::INVALID){ return false; } /// 更新当前view updateViewMap(commit_req.idx, commit_req.view); if (valid_ret == CheckResult::FUTURE){ return true; } // 添加进commitCache m_reqCache->addCommitReq(commit_req); // 检查是否达到2/3 checkAndSave(); return true;} handleCommitMsg方法处理流程如下图所示: 处理ViewChange请求 123456789101112131415161718192021222324252627282930bool PBFTEngine::handleViewChangeMsg(ViewChangeReq& viewChange_req, PBFTMsgPacket const& pbftMsg){ bool valid = decodeToRequests(viewChange_req, ref(pbftMsg.data)); if (!valid){ return false; } std::ostringstream oss; /// oss log 省略 // 判断view change请求的有效性 valid = isValidViewChangeReq(viewChange_req, pbftMsg.node_idx, oss); if (!valid){ return false; } // 添加到viewchangeCache m_reqCache->addViewChangeReq(viewChange_req); // 如果change的就是下一个view if (viewChange_req.view == m_toView) { // 检查是否达到2/3个viewchange checkAndChangeView(); } else { VIEWTYPE min_view = 0; bool should_trigger = m_reqCache->canTriggerViewChange( min_view, m_f, m_toView, m_highestBlock, m_consensusBlockNumber); if (should_trigger) { m_toView = min_view - 1; changeViewForFastViewChange(); } } return true;} handleViewChangeMsg 处理流程如下图所示: checkAndCommit checkAndCommit方法会在handlePrepareMsg和handleSignMsg 两个方法中调用,用于确定是否达到2/3,是否可以进行下PREPARE阶段的消息传递。 1234567891011121314151617181920212223242526void PBFTEngine::checkAndCommit(){ size_t sign_size = m_reqCache->getSigCacheSize(m_reqCache->prepareCache().block_hash); // 必须等于,否则会出现多次验证情况 if (sign_size == minValidNodes()) { // log 省略 if (m_reqCache->prepareCache().view != m_view) { // view不相等,错误退出,log省略 return; } // 更新当前commitedPrepare消息 m_reqCache->updateCommittedPrepare(); // 备份commited消息到数据库 log省略 backupMsg(c_backupKeyCommitted, m_reqCache->committedPrepareCache()); // 广播Commit消息,在PBFT流程中,相当于广播PREPARE/COMMIT阶段消息 if (!broadcastCommitReq(m_reqCache->prepareCache())) { // log 广播失败 } m_timeManager.m_lastSignTime = utcTime(); // 查看该消息是否到达2/3,是否可以进一步到达COMMIT结束阶段 checkAndSave(); }} checkAndSave checkAndSave方法会在handleCommitMsg方法中调用,用于确定 SignReq 和 CommitReq 这两个请求都到达2/3,且view和高度height都正确,那么就可以加入到区块中,进行落盘。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960void PBFTEngine::checkAndSave(){ auto start_commit_time = utcTime(); auto record_time = utcTime(); size_t sign_size = m_reqCache->getSigCacheSize(prepareCache().block_hash); size_t commit_size = m_reqCache->getCommitCacheSize(prepareCache().block_hash); //// signReq 和 commitReq 都满足 >= 2/3 if (sign_size >= minValidNodes() && commit_size >= minValidNodes()) { /// 得到足够的票数 log 省略 if (m_reqCache->prepareCache().view != m_view) { // view是错误的,log错误返回 return; } /// add sign-list into the block header if (m_reqCache->prepareCache().height > m_highestBlock.number()) { /// Block block(m_reqCache->prepareCache().block); std::shared_ptr<dev::eth::Block> p_block = m_reqCache->prepareCache().pBlock; /// 生成一个签名表<签名人idx,签名>,放入p_block m_reqCache->generateAndSetSigList(*p_block, minValidNodes()); auto genSig_time_cost = utcTime() - record_time; record_time = utcTime(); /// 调用blockchain模块commit该块 CommitResult ret = m_blockChain->commitBlock((*p_block), std::shared_ptr<ExecutiveContext>(m_reqCache->prepareCache().p_execContext)); auto commitBlock_time_cost = utcTime() - record_time; record_time = utcTime(); /// 如果成功 if (ret == CommitResult::OK) { // 从交易池删除已经处理的交易 dropHandledTransactions(*p_block); auto dropTxs_time_cost = utcTime() - record_time; record_time = utcTime(); // 同步模块进行同步 m_blockSync->noteSealingBlockNumber(m_reqCache->prepareCache().height); auto noteSealing_time_cost = utcTime() - record_time; /// log 共识成功,省略 // 删除cache m_reqCache->delCache(m_reqCache->prepareCache().block_hash); m_reqCache->removeInvalidFutureCache(m_highestBlock); } else { /// log共识失败 /// 同步模块进行同步,继续进行sealing m_blockSync->noteSealingBlockNumber(m_blockChain->number()); m_txPool->handleBadBlock(*p_block); } } else { // log 该块已经存在,共识错误 } }} checkAndChangeView checkAndChangeView在共识过程中出现leader timeout checkTimeout或主动进行view change handleViewChangeMsg时进行调用。 1234567891011121314151617181920212223242526272829void PBFTEngine::checkAndChangeView(){ IDXTYPE count = m_reqCache->getViewChangeSize(m_toView); // 判断是否收到2/3的viewChangeReq if (count >= minValidNodes() - 1) { /// reach to consensue dure to fast view change if (m_timeManager.m_lastSignTime == 0) { m_fastViewChange = false; } auto orgChangeCycle = m_timeManager.m_changeCycle; /// 更快的节点有可能已经到了下一轮 if (m_toView > m_view + 1) { m_timeManager.m_changeCycle = 1; PBFTENGINE_LOG(INFO) << LOG_DESC("checkAndChangeView, update m_changeCycle to 1"); } /// log 达到共识 // view=toView, 清除cache m_leaderFailed = false; m_timeManager.m_lastConsensusTime = utcTime(); m_view = m_toView.load(); m_notifyNextLeaderSeal = false; m_reqCache->triggerViewChange(m_view); m_blockSync->noteSealingBlockNumber(m_blockChain->number()); }} st=>start: 开始 e=>end: 结束 revPBFT=>parallel: 获取PBFT请求类型 op1=>operation: Prepare请求 op2=>operation: Sign请求 op3=>operation: Commit请求 op4=>operation: viewchange请求 op5=>operation: handlePrepareMsg op6=>operation: handleSignMsg op7=>operation: handleCommitMsg op8=>operation: handleViewChangeMsg op9=>operation: broadcastMsg cond1=>condition: 是否空块 或timeout st->revPBFT revPBFT(path1,left)->op1->op5->cond1 revPBFT(path2,bottom)->op2->op6->cond1 revPBFT(path3,right)->op3->op7->cond1 cond1(yes)->op4->op8->op9->e cond1(no)->op9->e{"theme":"simple","scale":1,"line-width":2,"line-length":50,"text-margin":10,"font-size":12} var code = document.getElementById("flowchart-0-code").value; var options = JSON.parse(decodeURIComponent(document.getElementById("flowchart-0-options").value)); var diagram = flowchart.parse(code); diagram.drawSVG("flowchart-0", options); st=>start: 开始 e=>end: 结束 cond1=>condition: Prepare 请求是否有效 op1=>operation: addRawPrepare 缓存Prepare请求 cond2=>condition: Prepare内 区块是空块? op2=>operation: view change op3=>operation: execBlock 执行Prepare内区块 op4=>operation: generateSignPacket 产生签名请求 op5=>operation: addPrepareCache 缓存执行后区块 op6=>operation: broadcacstSignReq 广播签名请求 op7=>operation: 继续获取请求 op8=>operation: checkAndCommit 查看SignReq是否达到2/3 st->cond1 cond1(yes)->op1 cond1(no)->op7->e op1->cond2 cond2(no)->op2->e cond2(yes)->op3->op4->op5->op6->op8->e{"theme":"simple","scale":1,"line-width":2,"line-length":50,"text-margin":10,"font-size":12} var code = document.getElementById("flowchart-1-code").value; var options = JSON.parse(decodeURIComponent(document.getElementById("flowchart-1-options").value)); var diagram = flowchart.parse(code); diagram.drawSVG("flowchart-1", options); st=>start: 开始 e=>end: 结束 cond1=>condition: isSignReqValid 签名请求是否有效 op1=>operation: addSignReq缓存 收到的签名请求 cond2=>condition: checkSignEnough签名 请求是否达到2*f+1? op2=>operation: updateLocalPrepare 备份Prepare请求 op3=>operation: broadcastCommitReq 广播Commit请求, 表明节点已达到可提交区块状态 op7=>operation: 继续获取请求 st->cond1 cond1(yes)->op1 cond1(no)->op7->e op1->cond2 cond2(no)->op7->e cond2(yes)->op2->op3->e{"theme":"simple","scale":1,"line-width":2,"line-length":50,"text-margin":10,"font-size":12} var code = document.getElementById("flowchart-2-code").value; var options = JSON.parse(decodeURIComponent(document.getElementById("flowchart-2-options").value)); var diagram = flowchart.parse(code); diagram.drawSVG("flowchart-2", options); st=>start: 开始 e=>end: 结束 cond1=>condition: isCommitReqValid Commit请求是否有效? op1=>operation: addCommitReq 缓存Commit请求 cond2=>condition: checkCommitEnough Commit请求是否达到2*f+1? op2=>operation: CommitBlock 将缓存的执行后区块提交到DB op7=>operation: 继续获取请求 st->cond1 cond1(yes)->op1 cond1(no)->op7->e op1->cond2 cond2(no)->op7->e cond2(yes)->op2->e{"theme":"simple","scale":1,"line-width":2,"line-length":50,"text-margin":10,"font-size":12} var code = document.getElementById("flowchart-3-code").value; var options = JSON.parse(decodeURIComponent(document.getElementById("flowchart-3-options").value)); var diagram = flowchart.parse(code); diagram.drawSVG("flowchart-3", options); st=>start: 开始 e=>end: 结束 cond1=>condition: isViewChangeReqValid ViewChange请求是否有效? op1=>operation: addViewChangeReq 缓存ViewChange请求 cond2=>condition: 请求的view是否 跟上了当前网络 cond3=>condition: checkAndChange 是否达到了2/3 op2=>operation: catchupView 追赶当前网络view op3=>operation: view=toView 清除缓存 op7=>operation: 继续获取请求 st->cond1 cond1(yes)->op1 cond1(no)->e op1->cond2 cond2(yes)->cond3 cond2(no)->op2->e cond3(yes)->op3->e cond3(no)->e{"theme":"simple","scale":1,"line-width":2,"line-length":50,"text-margin":10,"font-size":12} var code = document.getElementById("flowchart-4-code").value; var options = JSON.parse(decodeURIComponent(document.getElementById("flowchart-4-options").value)); var diagram = flowchart.parse(code); diagram.drawSVG("flowchart-4", options);]]></content>
<categories>
<category>区块链项目</category>
</categories>
<tags>
<tag>blockchain</tag>
<tag>FISCO-BCOS</tag>
</tags>
</entry>
<entry>
<title><![CDATA[HotStuff:BFT Consensus in the Lens of Blockchain]]></title>
<url>%2F2019%2F10%2F29%2Fresearch-in-HotStuff%2F</url>
<content type="text"><![CDATA[Facebook 的Libra基于HotStuff进行改进,HotStuff可以将网络消息复杂度降到线性级,可在较多节点上进行部署(大于100),吞吐量相对于传统PBFT提升可观,并在数学上证明了安全性。 1. 传统BFT 共识 传统BFT共识存在以下缺陷: 需要提前知道所有参与者信息,较难扩容; 平方级别的消息传递复杂度; 增加大量节点会导致网络拥塞; Leader节点会承受整个网络的负载,负载不均衡。 同样,相对于PoX等的共识,有着重要的优势: BFT协议速度只和与网络发送的短消息的速度有关,没有额外的能源消耗或等待时间; 交易延迟非常小,延迟与网络延迟同数量级; 容错率相对于PoX类型高很多。 2. 与传统BFT共识的对比 HotStuff基于一个新的框架,这个框架相比于传统BFT有着很大的不同: 采用树/链结构,投票只会投给当前认为主链上扩展的新部分; 不是通过链长度来判定主链,而是通过最近一次成功获得大部分投票的块决定; view change算法没有特殊情况; 工程友好。 3. 摘要与介绍 We present HotStuff, a leader-based Byzantine fault-tolerant replication protocol for the partially synchronous model. Once network communication becomes synchronous, HotStuff enables a correct leader to drive the protocol to consensus at the pace of actual (vs. maximum) network delay—a property called responsiveness—and with communication complexity that is linear in the number of replicas. To our knowledge, HotStuff is the first partially synchronous BFT replication protocol exhibiting these combined properties. Its simplicity enables it to be further pipelined and simplified into a practical, concise protocol for building large-scale replication services. 在摘要中主要说明了HotStuff的两个特别属性:responsiveness、linearity,在网络最大时延时间内完成共识,即低延迟,消息复杂度与节点的数量关系是线性的,即 O(n)。这两种特性在其他部分同步BFT共识协议中是第一次集成在一起,并且在实验部分成功部署了100个节点,TPS和交易延迟与BFT-SMaRt[5]相近,且在leader节点宕机的情况下,能保持线性级别的 view change。 4. 主要HotStuff模型 4.1阶段 4.1.1 Prepare phase 新的leader收集n-f个 NEW-VIEW 消息,里面包括了最高的 prepareQC; leader根据prepareQC寻找一个highest preceding view 分支,并标记为highQC,因为highQC是获得commit最高的块,它可以断定没有更高的view到达确认状态(safe); leader使用 CREATELEAF 方法在highQC的尾端节点扩展新proposal,建立一个新的图子节点,并附上指向父图子节点的哈希指针; 之后leader便将新的proposal放到 PREPARE 消息发给其他所有,proposal里包含了highQC的安全性证明; replica节点收到了来自leader的 PREPARE 消息后,节点使用 SAFENODE 方法检测是否接受,如果接受那么replica节点就会发出 PREPARE vote 消息,并签名,发给leader。 4.1.2 SAFENODE predicate 该方法的作用是验证highQC的可靠性: safety rule:新的proposal m从现有本地的lockedQC树节点延伸; liveness rule:如果proposal m的验证结果 m.justify,即当前node所在的view,对于现在的lockedQC有更高的 viewNumber; 如果以上两条有一条为真,那么就检测正确; 4.1.3 PRE-COMMIT phase 当leader收到proposal的 n-f 个 PREPARE vote ,将他们聚合(聚合签名)成一个 prepareQC; leader将 prepareQC 放入 PRE-COMMIT 消息中,广播出去; replica节点收到消息,对消息l进行哈希并签名,放到 PRE-COMMIT vote 发给leader; 4.1.4 COMMIT phase 当leader收到了proposal的 n-f 个 PRE-COMMIT vote ,再对这些vote进行聚合成一个 precommitQC; leader将 precommitQC 装进 COMMIT 消息中,进行广播; replica节点收到消息,投出 COMMIT vote 给leader; replica节点从lockedQC变更为precommitQC(为了安全/正确性需要); 4.1.5 DECIDE phase leader收到了 n-f 个 COMMIT vote ,聚合成一个 commitQC,放进 DECIDE message; 发送 DECIDE message 给所有其他replica节点; replica节点收到了 DECIDE message 后,判断在proposal的 commitQC,执行client commands命令; 将执行结果返回给client; replica节点增加 viewNumber ,结束这次view; 4.1.6 NEXTVIEW interrupt 在所有的阶段,replica都会等待对应viewNumber的消息,使用 NEXTVIEW(viewNumber) 工具判断,如果超时就进行下一个View; 如果 NEXTVIEW(viewNumber) 中断了等待,那么replica就会增加当前viewNumber,开始下一个view; 4.1.7 基本流程图 4.2 数据结构 4.2.1 Messages 123456789101112131415enum Type{ New_VIEW, PREPARE, PRE_COMMIT, COMMIT, DECIDE};class Messages{ private: Type type; unsigned int curView; Node node; uint64_t justyfy; // optional unsigned char partialSig[256];} 4.2.2 Quorum certificates 翻译为法定证书,一个QC,一个三元组 <type,viewNumber,node>,之后的签名聚合基于这个三元组进行聚合。 4.2.3 Tree and branches 叙述分支冲突、节点冲突的情况。 一个节点(node)包含了: Client‘s command 指向父节点的哈希指针 replica节点当且仅当节点可以领导(led by)本地分支时才发送消息;当有落后时,可以从其他节点中拉取; 如果两个分支都不是另一个的扩展,则这两个分支是冲突的(conflict);当两个节点所领导的分支发生冲突,则这两个节点是冲突的。 4.2.4 Bookkeeping variables 主要是记录当前协议的状态的变量: viewNumber:记录当前view,初始化为1,并由NEXTVIEW自增; lockedQC:记录当前replica节点投COMMIT票最高QC,初始化为空; prepareQC:记录当前replica节点投PRE-COMMIT票最高QC,初始化为空; replica节点维护一个最高节点(node),该节点所在的分支是有效的。 4.3 协议细节 4.3.1 工具模块 12345678910111213141516171819202122232425262728293031323334353637// 构造一个msgfunction Msg(_type,node,qc) m._type := _type m.viewNumber := curView m.node := node m.justify := qc return m// r节点对其签名投票function voteMsg(_type, node, qc) m := Msg(_type, node, qc) m.partialSig := tsign_r (⟨m._type, m.viewNumber, m.node⟩) return m// 生成叶子结点procedure createLeaf(parent, cmd) b.parent ← parent b.cmd ← cmd return b// 生成一个完整的QCfunction QC(V ) qc._type ← m._type : m ∈ V qc.viewNumber ← m.viewNumber : m ∈ V qc.node ← m.node : m ∈ V // 签名聚合 qc.sig ← tcombine(⟨qc._type, qc.viewNumber, qc.node⟩, {m.partialSig | m ∈ V }) return qcfunction matchingMsg(m, t, v) return (m._type = t) ∧ (m.viewNumber = v)function matchingQC(qc, t, v) return (qc._type = t) ∧ (qc.viewNumber = v)function safeNode(node, qc) return (node extends from lockedQC.node) ∨ // safety rule (qc.viewNumber > lockedQC .viewNumber) // liveness rule 4.3.2 Basic HotStuff 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657for curView ← 1, 2, 3, . . . do▷ prepare phaseas a leader // r = leader(curView)// we assume special new-view messages from view 0 wait for (n − f ) new-view messages: M ← {m | matchingMsg(m, new-view, curView −1)} highQC ← (max{m.justify.viewNumber} m∈M).justify curProposal ← createLeaf(highQC.node, client’s command) broadcast Msg(prepare, curProposal, highQC)as a replica wait for message m from leader(curView) m : matchingMsg(m, prepare, curView) if m.node extends from m.justify.node ∧ safeNode(m.node, m.justify) then send voteMsg(prepare, m.node, ⊥) to leader(curView)▷ pre-commit phaseas a leader wait for (n − f ) votes: V ← {v | matchingMsg(v, prepare, curView)} prepareQC ← QC(V ) broadcast Msg(pre-commit, ⊥, prepareQC)as a replica wait for message m from leader(curView) m : matchingQC(m.justify, prepare, curView) prepareQC ← m.justify send to leader(curView) voteMsg(pre-commit, m.justify.node, ⊥)▷ commit phaseas a leader wait for (n − f ) votes: V ← {v | matchingMsg(v, pre-commit, curView)} precommitQC ← QC(V ) broadcast Msg(commit, ⊥, precommitQC)as a replica wait for message m from leader(curView) m : matchingQC(m.justify, pre-commit, curView) lockedQC ← m.justify send to leader(curView) voteMsg(commit, m.justify.node, ⊥)▷ decide phaseas a leader wait for (n − f ) votes: V ← {v | matchingMsg(v, commit, curView)} commitQC ← QC(V ) broadcast Msg(decide, ⊥, commitQC)as a replica wait for message m from leader(curView) m : matchingQC(m.justify, commit, curView) execute new commands through m.justify.node, respond to clients▷ Finally nextView interrupt: goto this line if nextView(curView) is called during “wait for” in any phase send Msg(new-view, ⊥, prepareQC) to leader(curView + 1) 4.4 Safety, liveness and complexity 4.4.1 安全性引理 安全性假设:定义一个quorum certificate \(qc\) 当且仅当以下共识为真时是有效的: \(tverify(<qc.type,qc.viewNumber,qc.node>,qc.sig)\) 对于任意有效的 \(qc_1,qc_2\) ,有 \(qc_1.type=qc_2.type\) 且 $qc_1.node $ 和 $ qc_2.node$ 冲突,那么有 \(qc_1.viewNumber\ne qc_2.viewNumber\) ; 定理:如果有两个冲突的节点 \(w,a\) 那么这两个节点不可能同时被commit,即使这两个节点都来自于正确的replica; 4.4.2 活跃性引理 主要是定义两个函数 LEADER、NEXTVIEW。 If a correct replica is locked such that \(lockedQC = precommitQC\) , then at least \(f + 1\) correct replicas voted for some \(prepareQC\) matching \(lockedQC\). 定理:在GST之后,在一段时间内所有replica节点都在一段时间 \(T_f\) 内保持在同一个view中,且leader对于当前view是有效的,那么就能达成共识。 4.4.3 复杂度 在每个阶段,都是由leader进行广播,所有replica节点接受消息,并签上签名返回给leader,leader进行阈值签名聚合,所以消息复杂度都是 \(O(n)\) 。 5. 链式HotStuff 在基本HotStuff中,Leader主节点需要三个阶段来确认一个请求提交。这些阶段都非常相似,除了收集其它副本节点的投票外,大部分没有做多少实际工作。 5.1 基本流程 链式HotStuff (Chained HotStuff)提升基本HotStuff的效用并同时并大大简化其流程。方法是在每个Prepare阶段,都主动地转换视图。具体说来,在链式HotStuff中,对Prepare阶段的投票,由下一个在prepareQC的视图的Leader来收集。同样,依此类推,Pre-Commit和Commit阶段的投票也由与之相应的下一个视图的leader来收集。这样,新Leader在视图v+1的Prepare提议阶段,同时作为视图v的Pre-Commit阶段。而新的Leader在视图v+2的Prepare提议阶段,同时可以作为视图v+1的Pre-Commit阶段,以及视图v的Commit阶段。因为所有阶段的数据结构都一样,因此可以用流水线的方式来提升共识的效率。下图展示了链式HotStuff的基于Basic HotStuff的流水线形式。 视图 \(v_1\), \(v_2\), \(v_3\)作为在\(v_1\)提交的命令cmd1的Prepare,Pre-Commit和Commit阶段。cmd1命令在\(v_4\)里确认。视图\(v_2\),\(v_3\),\(v_4\)作为在\(v_2\)提交的cmd2的三个基础HotStuff的阶段,cmd2在\(v_5\)里得到确认,依此类推。 因此链式HotStuff中,只有两类型的消息,一种是New-View,一种是Generic phase的Generic消息。genericQC实现所有不同阶段的功能。 链式HotStuff中,如果下图,节点 $ b’$ 中的QC直接对应父图节点 \(b\) ,这样形成了One-Chain; 如果在One-Chain的基础上,下一个图节点 \(b''\) 中的QC直接对应 \(b’\) ,这样就形成了Two-Chain,在这个基础上,下一个图节点 \(b^*\) 中的QC直接对应 \(b’’\) , 这样就形成了Three-Chain。显示视图\(v_4\),\(v_5\),\(v_6\) 形成了一个Three-Chain。 5.2 链式HotStuff伪代码 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556procedure createLeaf(parent, cmd, qc) b.parent ← branch extending with blanks from parent to height curView; b.cmd ← cmd; b.justify ← qc; return bfor curView ← 1, 2, 3, . . . do▷ generic phaseas a leader // r = leader(curView) wait for (n − f ) NEW-VIEW messages: M ← {m | matchingMsg(m, NEW-VIEW, curView −1)} // M包含了上个leader的NEW-VIEW消息,等待上一个leader genericQC ← (max {m.justify.viewNumber} m∈M).justify curProposal ← createLeaf(genericQC.node, client’s command, genericQC) // prepare 阶段 (leader-half) broadcast Msg(generic, curProposal, ⊥)as a replica wait for message m from leader(curView) m : matchingMsg(m, generic, curView) b∗ ← m.node; b′′ ← b∗.justify.node; b′ ← b′′.justify.node; b ← b′.justify.node if safeNode(b∗ , b∗.justify) then send voteMsg(generic, b∗ , ⊥) to leader(curView) // 开始b∗的父节点 pre-commit 阶段 if b∗.parent = b′′ then genericQC ← b∗.justify // 开始b∗的祖父节点的 commit 阶段 if (b∗.parent = b′′) ∧ (b′′.parent = b′ ) then lockedQC ← b′′.justify // 开始b∗的祖祖父节点 decide 阶段 if (b∗.parent = b′′) ∧ (b′′.parent = b′) ∧ (b′.parent = b) then execute new commands through b, respond to clients // 表明当前cmd已经被确认,可以执行as a leader // pre-commit 阶段 (leader-half) wait for (n − f) votes: V ← {v | matchingMsg(v, generic, curView)} genericQC ← QC(V) // for liveness, the message here counts as (n − f ) at Line 5as the next leader wait for message m from leader(curView) m : matchingMsg(m, NEW-VIEW, curView)▷ Finally nextView interrupt: goto this line if nextView(curView) is called during “wait for” in any phase send Msg(NEW-VIEW, ⊥, genericQC) to leader(curView + 1) 参考文献 [1]. Maofan Yin, Dahlia Malkhi, Michael K. Reiter, Guy Golan Gueta, and Ittai Abraham. 2018. HotStuff: BFT Consensus in the Lens of Blockchain. CoRR abs/1803.05069 (2018). arXiv:1803.05069 [2]. Maofan Yin, Dahlia Malkhi, Michael K. Reiter, Guy Golan Gueta, and Ittai Abraham. 2019. HotStuff: BFT Consensus with Linearity and Responsiveness. In 2019 ACM Symposium on Principles of Distributed Computing (PODC ’19), July 29-August 2, 2019, Toronto, ON, Canada. ACM, New York, NY, USA, 10 pages. https://doi.org/10.1145/3293611.3331591 [3]. Facebook Libra 采用的 HotStuff 算法,究竟是怎样一种尤物 [4]. Libra 采用的 HotStuff 算法作者亲述:「尤物」诞生记 [5]. Alysson Neves Bessani, João Sousa, and Eduardo Adílio Pelinson Alchieri. State machine replication for the masses with BFT-SMART. In 44th Annual IEEE/IFIP International Conference on Dependable Systems and Networks, DSN 2014, Atlanta, GA, USA, June 23-26, 2014, pages 355–362, 2014. [6]. (邹均)LibraBFT共识协议:三难问题平衡术]]></content>
<categories>
<category>区块链项目</category>
</categories>
<tags>
<tag>blockchain</tag>
<tag>HotStuff</tag>
<tag>Consensus</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Hyperledger Indy Research: Anonymous credentials with type-3 revocation]]></title>
<url>%2F2019%2F08%2F13%2FHyperledger-Indy-Research-Anonymous-credentials-with-type-3-revocation%2F</url>
<content type="text"><![CDATA[一、简述 匿名凭证的作用是允许用户证明当前identity符合某个属性,且不暴露出其他属性。本文描述的方法通过使用零知识证明的方式保证属性在披露的过程中不被其他人知道,且可实现凭证一次性使用,第二次用于展示给Verifier的时候会被感知。 由于其原稿难懂,有多个符号错误,计算错误,符号未命名的问题,所以本人进行翻译、纠正。 Indy选择性披露核心的流程在于: Init: issuser生成属性模板 prover/holder使用自己的私钥master key和属性(可以盲化或不盲化),用属性模板生成证明,向issuer获取证书 issuer用自己的私钥对属性进行签名,将其发送给Holder Verify: prover选择要披露的属性,,根据证书生成证书的proof,将proof和属性给Verifier Verifier根据issuer的公钥,proof,属性。用证书验证属性是否在proof里。验证proof是否是由Issuer的公钥签发 核心性质: 不可伪造性(unforgeable),即没有人可以使用未经Issuer签发的凭证通过Verifier的验证 不可链接性(unlinkable),即不可能使用同样的凭证与多个匿名的presentation关联。技术上用knowledge proof证明他拥有凭证。 可拓展性(delegatable),Prover A可以将具有特定属性X的证书C(credential)委托给Prover B,同时Verifier在当B提供属性Y的时候不获取A的身份。技术上代表可以进一步创建证书链。 二、Protocol Overview 最简单的凭证生命周期:一个凭证,单个issuer,单个持有人,单个验证者 Issuer制定凭证模板\(\mathcal S\):签凭证使用的密码学类型、\(l\) 个凭证属性、隐藏属性 \(A_h \subset \{1,2,…,l\}\) 、凭证公钥 \(P_k\) 、非撤销凭证属性数\(l_r\) 非撤销公钥\(P_r\) ,并将凭证公布到区块链上,定义其语义; Holder检索到凭证模板,并设定隐藏属性; Holder想Issuer请求凭证,并将隐藏属性以黑盒的形式发给Issuer,并对已知属性的值达成协议 \(A_k=\{1,2,...,l\}/A_h\) ; Issuer返回凭证对\((C_p,C_{NR})\) 给Holder。第一个 \(C_p\) 凭证包括了必须设定的 \(l\)个属性,第二个\(C_{NR}\) 赋值了第一个凭证的非撤销状态;Issuer随后将该凭证的未撤销状态公布到链上; Holder连接到Verifier,Verifier发送证明请求 \(\mathcal E\) 给Holder,证明请求包括了凭证模板\(\mathcal{S}_E\) 和披露断言 \(\mathcal D\) ;对于属性 \(m\) 与验证值 \(V\) 的披露断言模式可以有 \(m>V, m<V, m=V\) ; Holder检查所持有的凭证对是否符合 Verifier发来的模板 \(\mathcal{S}_E\) ,并从区块链中检索该模板未被撤销的见证(witness); Holder 使用符合证明请求 \(\mathcal E\) 的未撤销凭证,生成了证明 \(P\) ,并发送给Verifier; Verifier验证证明\(P\); 以下时序图描述整个协议流程: Prover与Issuer交互: Prover与Verifier交互: 三、具体方案步骤 接下来以整个方案的流程逐步详细介绍: 1. Schema准备 1.1 Issuer定义凭证属性 (1.1.1)Issuer定义一个有 \(l\) 个属性 \(\{m_1,…,m_l\}\) 的Schema \(\mathcal{S}\) ,并设置隐藏属性集合 \(A_h \subset \{1,2,…,l\}\) 。 在Sovrin中,\(m_1\) 保留为链接向Holder的链接, \(m_2\) 保留为枚举器, \(m_3\) 保留为策略地址\(I\) ,并且\(\{1,3\}\subset A_h, and\ 2 \notin A_h\); Issuer定义非撤销凭证内含 \(m_1,m_2\) 两个属性; 1.2 Issuer定义凭证密码方法 (1.2.1)Issuer使用CL签名算法,生成一组Primary Credential公私钥对: 随机获取1024-bit的素数 \(p', q'\) ,计算: \(p\leftarrow 2p'+1,\ q\leftarrow 2q'+1,\ n\leftarrow pq\) 随机取模n的二次剩余 \(S\) :\(S\) 不是n的倍数,且mod n同余于某个数的平方,例如 \(S\equiv x^2(mod\ n),\ S^{(n-1)/2}\equiv 1(mod\ n)\) ; 随机取 \(x_Z,x_{R_1},…,x_{R_l}\ \in[2;p'q'-1]\) 计算得公钥 \(P_k = (n,S,Z\leftarrow S^{x_Z},\{R_i\leftarrow S^{x_{R_i}}\}_{1\leqslant i \leqslant l})\) ,私钥 \(s_k=(p',q')\) 1.3 Issuer提供凭证密钥正确性 (1.3.1) Issuer生成一堆随机数 \(\widetilde{x_Z},\widetilde{x_{R_1}},…,\widetilde{x_{R_l}}\ \in[2;p'q'-1]\) Issuer计算: \[ \widetilde{Z}\leftarrow S^{\widetilde{x_Z}}\\ \{\widetilde{R_i}\leftarrow S^{\widetilde{x_{R_i}}}(mod\ n)\}_{i\le i\le l}\\ c\leftarrow H_1(Z||\widetilde Z||\{R_i,\widetilde{R_i}\}_{1\le i\le l})\\ \widehat{x_Z}\leftarrow \widetilde{x_Z}+cx_Z\\ \{\widehat{x_{R_i}}\leftarrow \widetilde{x_{R_i}}+cx_{R_i}\}_{1\le i\le l} \] Issuer最终将证明 \(\mathcal P_I=(c,\widehat{x_Z},\{\widehat{x_{R_i}}\}_{1\le i\le l})\) 发送出去。 1.4 Issuer定义Non-revocation凭证 (1.4.1)Issuer使用CKS聚合器与签名方法以追踪Primary Credential的撤销状态,生成一组Non-revocation Credential的密钥对: 设有双线性配对群 \((q, \Bbb{G}_1,\Bbb{G}_2, \Bbb{G}_t,e,g,g')\) ,其中 \(\Bbb{G}_1,\Bbb{G}_2,\Bbb{G}_t\) 都是素数 \(q\) 阶群,\(e : \Bbb{G}_t \leftarrow \Bbb{G}_1 × \Bbb{G}_2\) 是一种映射关系,\(g,g’\) 分别是 \(\Bbb{G}_1,\Bbb{G}_2\) 的生成子。 随机生成 \(h,h_0,h_1,h_2, \widetilde{h} \in \Bbb{G}_1\) ; 随机生成 \(u,\widehat{h} \in \Bbb{G}_2\) ; 随机生成 \(sk, x \in \Bbb{Z}_q\) ; 计算得出撤销公钥: \(P_r=(g,g',h,h_0,h_1,h_2,\widetilde{h}, \widehat{h},u,pk\leftarrow g^{sk},y\leftarrow \widehat{h}^x)\) 得出私钥 \((x,sk)\) (1.4.2)Issuer生成新的聚合器(Accumulator) \(A\) ,其中 \(L\) 是凭证的index : 随机生成 \(\gamma \in \Bbb{Z}_q\) ; 计算: \[ \tag{1.1}g_1,g_2,…,g_L,g_{L+2},…,g_{2L},\ where\ g_i=g^{\gamma^i} \] \[ \tag{1.2}g'_1,g'_2,…,g'_L,g_{L+2},…,g'_{2L},\ where\ g'_i=g'^{\gamma^i} \] \[ \tag{1.3}z=(e(g,g'))^{\gamma^{L+1}} \] 设置值 \(V\leftarrow \emptyset\) ,聚合器 \(acc\leftarrow 1\) ; 进而得出聚合器的公钥 \(P_a=(z)\) ,私钥 \((\gamma)\) ; 之后Issuer把 \((P_a,V)\) 公布到区块链上供其他人进行累积、验证, 聚合器的DID设置为 \(ID_a=z\) 。 2. Credential发行 2.1 Holder获取凭证模板,进行验证模板是Issuer发的 Holder拿到模板以及Issuer的公钥、证明 \((c,\widehat{x_Z},\{\widehat{x_{R_i}}\}_{1\le i\le l})\) ,进行进一步计算: \[ \widehat Z\leftarrow Z^{-c}S^{\widehat{x_Z}}\ (mod\ n)\\ \{\widehat{R_i}\leftarrow R_i^{-c}S^{\widehat{x_{R_i}}}\ (mod\ n)\}_{1\le i\le l} \] 验证: \[ c=H_1(Z||\hat Z||\{R_i,\widehat{R_i}\}_{1\le i\le l}) \] 2.2 Holder进行凭证设定 Holder从区块链中获取了凭证的模板 \(\mathcal S\) ,并设置属性 \(\{m_i\}_{i\in A_h}\) ,其余未设置的属性皆为0; Holder建立与Issuer的连接,从Issuer那获取随机数 \(n_0\) ,Holder的DID为 \(\mathcal{H}\) ; (2.2.1)Holder做以下计算,为Primary Credential的数据做准备: 生成 2128-bit随机数 \(v'\) ,673-bit随机数 \(\widetilde{v'}\) 生成593-bit随机数 \(\{\widetilde{m_i}\}_{i\in A_h}\) 使用Primary Credential的公钥 \(P_k\) 计算Primary Credential的盲化secret: \[ \tag{2.1}U\leftarrow (S^{v'})\prod_{i\in A_h}R_i^{m_i} \] 计算commitment Attribute属性值 \(vca\) ,其中 \(blind\) 是盲化因子: \[ \tag{2.2} \{vca_i\}_{i\in A_{commit}}=\{S^{blind}\cdot Z^{m_i}\}_{i\in A_{commit}}\\ \widetilde{r_i}=rand(593bit)_{i\in A_{commit}} \] \[ \tag{2.3}\{\widetilde{commitment_i}=Z^{\widetilde{m_i}}\cdot S^{\widetilde{r_i}}\}_{i\in A_{commit}} \] 另外计算盲化正确proof: \[ \tag{2.4}\widetilde{U}\leftarrow (S^{\widetilde v'})\prod_{i\in A_h}R_i^{\widetilde m_i} \] \[ \tag{2.5}c\leftarrow H(\{\widetilde{commitment_i}\}||\{vca_i\}||U||\widetilde U||n_0)_{i\in A_{commit}} \] \[ \tag{2.6}\widehat{v'}\leftarrow \widetilde{v'} + cv' \] \[ \tag{2.7.1}\{\widehat{m_i}\leftarrow \widetilde{m_i} +cm_i\}_{i\in A_h} \] \[ \tag{2.7.2} \{\widehat{r_i}\leftarrow \widetilde{r_i}+c\cdot blind\}_{i\in A_{commit}} \] 生成80-bit随机数 \(n_1\) 将 \(\{U,c,\widehat{v'},\{\widehat{m_i}\}_{i\in A_h},n_1,attr\_name\subset\{A_h\},\{A_{commit}\}=\{attr\_name,vca\}\}\) 打包发送给Issuer (2.2.2)Holder做以下计算,为Non-Credential的数据做准备: 获取撤销公钥 \(P_R\) ,并生成随机数 \(s'_R \in \Bbb{Z}_q\) ; 计算 \[ \tag{2.8}U_R\leftarrow h_2^{s'_R},\ where\ h_2\ in\ P_R \] 将 \(U_R\) 发送给Issuer 2.3 Issuer收到凭证模板,确认后颁发 (2.3.1)Issuer验证Holder发来的Primary Credential模板数据是否正确: 计算\(\widehat{U}\leftarrow (U^{-c})\prod_{i\in A_h}R_i^{\widehat m_i}(S^{\widehat{v'}})\) ; \(\{\widehat{commitment_i}\leftarrow vca_i^{-c}\cdot Z^{\widehat{m_i}}S^{\widehat{r_i}}\}_{i\in A_{commit}}\) 验证\(c= H(\{\widehat{commitment_i}\}||\{vca_i\}||U||\widehat U||n_0)_{i\in A_{commit}}\) ; 验证 \(\widehat{v'}\) 是一个673-bit的数,\(\{\widehat{m_i},\widehat{r_i}\}_{i\in A_h}\) 是594-bit的数; (2.3.2)Issuer准备为Holder发行Primary凭证: 为当前Holder赋值一个唯一值 \(i<L\) 作为标识, 计算 \(m_2\leftarrow H(i||\mathcal{H})\) 记录了当前Holder 的信息,并将 \(m_2\) 和\(i\)保存在本地数据库; 设置可被披露的属性值 \(A_k\) ; 生成2724-bit 随机数 \(v''\), 随机素数 \(e,\ where\ 2^{596}\leqslant e \leqslant 2^{596}+2^{119}\) ; 随机生成 \(r<p'q'\) ,其中 \(p',q'\) 从Primary凭证私钥中得出 ; 计算签名: \[ \tag{2.9}Q\leftarrow \cfrac{Z}{US^{v''}\prod_{i\in A_k}R_i^{m_i}(mod\ n)}\\ \] \[ \tag{2.10}A\leftarrow Q^{e^{-1}(mod\ p'q')}(mod\ n) \] 计算签名Proof: \[ \tag{2.11}\widehat A\leftarrow Q^r\ (mod\ n) \] \[ \tag{2.12}c' \leftarrow H(Q||A||\widehat A||n_1) \] \[ \tag{2.13}s_e\leftarrow r-c'e^{-1}\ (mod\ p'q') \] (2.3.3)Issuer 将primary pre-credential \((\{m_i\}_{i\in A_k},A,e,v'',s_e,c')\) 发送给Holder; (2.3.4)Issuer 非撤销凭证(Non-revocation Credential)的颁发 生成随机数 \(s'',c\leftarrow Z_q\) ; 将Primary凭证中的 \(m_2\) 也加入到非撤销凭证中,进行两个凭证的关联; \(acc_V\)是聚合器值,为证书分配一个未使用的索引index \(i\) ,\(V\) 是现在未被撤销的集合; 计算(其中L为最多颁发的证书个数,在代码中表示为n): \[ \tag{2.14} \sigma \leftarrow (h_0h_1^{m_2}\cdot U_R\cdot g_i\cdot h_2^{s''})^{\cfrac{1}{x+c}} \] \[ \tag{2.15}w\leftarrow \prod_{j\in V}g'_{L+1-j+i} \] \[ \tag{2.16} \sigma_i \leftarrow g'^{1/(sk+\gamma^i)} \] \[ \tag{2.17} u_i \leftarrow u^{\gamma_i} \] \[ \tag{2.18} acc_V\leftarrow acc_V\cdot g'_{L+1-i} \] \[ \tag{2.19} V\leftarrow V\cup\{i\} \] \[ \tag{2.20} wit_i\leftarrow \{\sigma_i,u_i,g_i,w,V\} \] 将非撤销凭证 \((I_A,\sigma,c,s'',wit_i,g_i,g'_i,i)\) 发给Holder; 将更新的 \(V,acc_V\) 放到区块链中; 2.4 Holder收到两个凭证,进行存储 (2.4.1)Holder存储凭证 计算 \(v\leftarrow v'+v''\); 验证 \(e\) 是素数,且符合 \(2^{596}\leqslant e \leqslant 2^{596}+2^{119}\) ; 计算: \[ \tag{2.21}Q\leftarrow \cfrac{Z}{S^v \prod_{i\in C_S}R_i^{m_i}}\ (mod\ n) \] (2.4.2)验证 \(Q=A^e(mod\ n)\); (2.4.3)计算: \[ \tag{2.22}\widehat A \leftarrow A^{c'+s_e\cdot e} \] 验证 \(c'=H(Q||A||\widehat A||n_1)\) ; 存储Primary凭证\(C_p=(\{m_i\}_{i\in C_s},A,e,v)\) ; 计算 \(s\leftarrow s'_R+s''\), 存储非撤销凭证 \(C_{NR}\leftarrow(I_A,\sigma,c,s,wit_i,g_i,g'_i,i)\) ; (2.4.4)三个等式证明Holder收到的Non-revocation 凭证的正确性 \[ \cfrac{e(g_i,acc_V)}{e(g,w)}=z\\ e(pk\cdot g_i,\sigma_i)=e(g,g')\\ e(\sigma,y\cdot \widehat h^{c})=e(h_0\cdot h_1^{m_2}h_2^sg_i,\widehat h) \] 3. 凭证撤销 (3.1)Issuer在数据库找到要被撤销的凭证,并找出他的索引号 \(i\) ,以及聚合器 \(A\),有效凭证集合 \(V\) 从 \(V\) 中剔除 \(i\) : \(V \leftarrow V -\{i\}\) ; 从聚合器中剔除:\(acc_V\leftarrow acc_V/g'_{L+1-i}\) ; 公布出新的 \(\{V,acc_V\}\) ; 4. Holder展示凭证 4.1 Verifier向Holder发出Proof Request Verifier向Holder发出 \(d\) 个凭证模板集合 \(\{\mathcal S_1,\mathcal S_2,...\mathcal S_d\}\) 的证明请求(Proof Request); Holder 需要对应的给出 \(d\) 个凭证证明对 \((C_p,C_{NR})\) 回应; 假设模板集合有 \(X\) 个属性,其中,公开属性集合 \(x_1:A_h=X-x_1\) ,需证明相等的属性 \(x_2: m_i=m_j\) ,需证明不相等属性 \(x_3:m_i(><\geq \leq) z\) ; \(x_4=X-x_1-x_2\) ,映射 \(\phi:A_h\ to\ \{1,2,...,x_4\}\),\(A_v\) 表示 \(x_1\) 披露的属性索引集合; Verifier给Holder发80-bit随机数 \(n_2\) ,用于之后与Holder交互; 4.2 Holder提供证明 (4.2.1)Holder准备对应凭证对 \((C_p,C_{NR})\) 去验证; 生成 \(x_4\) 个592-bit随机数 \(\widetilde{y_1},\widetilde{y_2},...,\widetilde{y_{x_4}}\) ,并设定 \(\widetilde{m_j}\leftarrow \widetilde{y_{\phi(j)}} , where\ j\in A_h\) ; 生成两个空集合 \(\mathcal T,\mathcal C\) ; 对所有凭证对 \((C_p,C_{NR})\) 都准备证明; (4.2.2)Holder给出非撤销证明: 加载Issuer的撤销公钥 \(p=(h,h_1,h_2,\widetilde h,\widehat h,u,pk,y)\) ; 加载非撤销凭证 \(C_{NR}=(I_A,\sigma,c,s,wit_i,g_i,g'_i,i)\) ; 获取现在的未撤销凭证索引集合 \(V\) ,聚合器 \(acc\) ; 更新非撤销凭证 \(C_{NR}\) : \[ \tag{4.1}w\leftarrow w\cdot \cfrac{\prod_{j\in (V\backslash V_{old})}g'_{L+1-j+i}}{\prod_{j\in (V_{old}\backslash V)}g'_{L+1-j+i}};\ where\ V_{old}\ is\ from\ wit_i;\\ V_{old}\leftarrow V; \] 随机取随机数: \(\rho,r,r',r'',r''',o,o'\ mod\ q\) ; 计算以下公式,并将最终所得放到集合 \(\mathcal C\) : \[ \tag{4.2} E\leftarrow h^{\rho}\widetilde h^o; \] \[ \tag{4.3} D\leftarrow g^{r}\widetilde h^{o'}; \] \[ \tag{4.4} A\leftarrow \sigma \widetilde h^{\rho}; \] \[ \tag{4.5} \mathcal G \leftarrow g_i\widetilde h^r; \] \[ \tag{4.6} \mathcal W \leftarrow w\widehat h^{r'}; \] \[ \tag{4.7} \mathcal S \leftarrow \sigma_i \widehat h^{r''}; \] \[ \tag{4.8} \mathcal U \leftarrow u_i\widehat h^{r'''}; \] > E、D分别是对\(\rho\) 和 \(r\) 的承诺 \(\mathcal G\), \(\mathcal W\), \(\mathcal S\), \(\mathcal U\) 分别是对\(g_i\), \(w\), \(\sigma_i\), \(u_i\)的盲化 \(NonRevocProofCList \leftarrow \{ E, D, A, \mathcal G, \mathcal W, \mathcal S, \mathcal U \}\), 作为c_list 以上过程由ProofBuilder::_create_c_list_values() 完成 计算: \[ \tag{4.9} m\leftarrow \rho \cdot c; \] \[ \tag{4.10} t\leftarrow o\cdot c; \] \[ \tag{4.11} m'\leftarrow r\cdot r''; \] \[ \tag{4.12} t'\leftarrow o'\cdot r''; \] 随机取随机数:\(\widetilde{\rho},\widetilde{o},\widetilde{o'},\widetilde{c},\widetilde{m},\widetilde{m'},\widetilde{t},\widetilde{t'},\widetilde{m_2},\widetilde{s},\widetilde{r},\widetilde{r'},\widetilde{r''},\widetilde{r'''},mod\ q\) ; 计算以下公式,并将最终所得放到集合 \(\mathcal T\) : \[ \tag{4.13} \overline{T_1}\leftarrow h^{\widetilde{\rho}}\widetilde h^{\widetilde o};\ \overline{T_2} \leftarrow E^{\widetilde c}h^{-\widetilde m}\widetilde h^{-\widetilde t} \] \[ \tag{4.14} \overline{T_3} \leftarrow e(acc_V,\widehat h)^{\widetilde c}\cdot e(\widetilde h,\widehat h)^{\widetilde r}\cdot e(\widetilde h,y)^{-\widetilde{\rho}}\cdot e(\widetilde h,\widehat h)^{-\widetilde m}\cdot e(h_1,\widehat h)^{-\widetilde{m_2}}\cdot e(h_2,\widehat h)^{-\widetilde s}; \] \[ \tag{4.15} \overline{T_4}\leftarrow e(\widetilde h,acc_V)^{\widetilde r}\cdot e(1/g,\widehat h)^{\widetilde {r'}};\ \overline{T_5} \leftarrow g^{\widetilde r} \widetilde h^{\widetilde{o'}}; \] \[ \tag{4.16} \overline{T_6}\leftarrow D^{\widetilde{r''}}g^{-\widetilde{m'}}\widetilde h^{-\widetilde{t'}};\ \overline{T_7}\leftarrow e(pk\cdot \mathcal G,\widehat h)^{\widetilde{r''}}\cdot e(\widetilde h,\widehat h)^{-\widetilde{m'}}\cdot e(\widetilde h,\mathcal S)^{\widetilde r}; \] \[ \tag{4.17} \overline{T_8}\leftarrow e(\widetilde h,u)^{\widetilde r}\cdot e(1/g,\widehat h)^{\widetilde{r'''}}; \] (4.2.3)Holder 给出Primary凭证有效证明: 对于每一个凭证 \(C_p=(\{m_j\},A,e,v)\) 以及Issuer的公钥 \(pk_I\leftarrow (n,S,Z,{R_i}_{1\leq i\leq l})\) : 随机选取2128-bit随机数 \(r\) ; 计算: \[ \tag{4.18}A'\leftarrow AS^r\ (mod\ n);v'\leftarrow v-e\cdot r; \] 并将 \(A'\) 放入集合 \(\mathcal C\) ; 计算:\(e'\leftarrow e-2^{596}\) ; 随机取456-bit随机数 \(\widetilde e\) ,3060-bit随机数 \(\widetilde v\) ; 计算以下公式,并将结果放入集合 \(\mathcal T\) ; \[ \tag{4.19}T\leftarrow (A')^{\widetilde e}\Big(\prod_{j\in \mathcal A_{\overline r}}R_j^{\widetilde{m_j}}\Big)(S^{\widetilde v})\ (mod\ n) \] 对于每一个断言 \(p\) ,其操作符 \(*\) 都是 \(>,\geq, <,\leq\) 其中之一 计算 \(\Delta\) : \[ \tag{4.20}\Delta \leftarrow \begin{cases} z_j-m_j; &\text{if } * \equiv\ \leq\\ z_j-m_j-1; &\text{if } * \equiv\ <\\ m_j-z_j; &\text{if } * \equiv\ \geq\\ m_j-z_j-1; &\text{if } * \equiv\ > \end{cases} \] 计算 \(a\) : \[ \tag{4.21} a\leftarrow \begin{cases} -1 &\text{if } * \equiv\ \leq\ or\ <\\ 1 &\text{if } * \equiv\ \geq\ or\ > \end{cases} \] 寻找四个值\(u_1,u_2,u_3,u_4\)符合以下等式: \[ \tag{4.22}\Delta =(u_1)^2+(u_2)^2+(u_3)^2+(u_4)^2 \] 随机取2128-bit随机数 \(r_1,r_2,r_3,r_4,r_{\Delta}\) ; 计算以下公式,并将结果按顺序放入集合 \(\mathcal C\) : \[ \tag{4.23}\{T_i\leftarrow Z^{u_i}S^{r_i}\ (mod\ n)\}_{1\le i\le 4}; \] \[ \tag{4.24}T_\Delta \leftarrow Z^\Delta S^{r_\Delta}\ (mod\ n); \] 随机取592-bit数 \(\widetilde{u_i}, 1\le i \le 4\) ; 随机取672-bit数 \(\widetilde{r_i}, 1\le i \le 4, \widetilde{r_\Delta}\) ; 随机取2787-bit随机数 \(\widetilde{\alpha}\) ; 计算以下公式,并将值按顺序放入集合 \(\mathcal T\) : \[ \tag{4.25}\{\overline{T_i}\leftarrow Z^{\widetilde{u_i}}S^{\widetilde{r_i}}\ (mod\ n)\}_{1\le i\le 4} ; \] \[ \tag{4.26}\overline{T_\Delta}\leftarrow Z^{\widetilde{m_j}}S^{a\widetilde{r_\Delta}}\ (mod\ n); \] \[ \tag{4.27}Q\leftarrow (S^{\widetilde{\alpha}}\prod_{i=1}^4 T_i^{\widetilde{u_i}}\ (mod\ n)); \] 4.2.1 Holder计算哈希,向Verifier提出挑战 计算:\(c_H\leftarrow H(\mathcal T,\mathcal C,n_2)\) ,并将其发给Verifier; 4.2.2 最终披露 Holder进行最终的披露: (4.2.2.1)对于Non-Revcation Credential:对参数 \(\rho, o,c,o',m,m',t,t',m_2,s,r,r',r'',r'''\) 都进行盲化处理,处理方法类似于下面的公式: \[ \tag{4.28}\widehat \rho \leftarrow \widetilde{\rho} -c_H\rho\ (mod\ q) \] 最终得出\(\widehat\rho,\widehat o,\widehat c,\widehat{o'},\widehat m,\widehat{m'},\widehat t,\widehat {t'},\widehat{m_2},\widehat s,\widehat r,\widehat {r'},\widehat{r''},\widehat{r'''}\) 并将结果放入集合 \(\mathcal X\) ; (4.2.2.2)对于Primary 凭证 \(C_p=(\{m_j\},A,e,v)\) 计算: \[ \tag{4.29}\widehat e\leftarrow \widetilde e+c_He'; \] \[ \tag{4.30}\widehat v\leftarrow \widetilde v+c_Hv'; \] \[ \tag{4.31}\{\widehat m_j\leftarrow \widetilde{m_j}+c_Hm_j\}_{j\in \mathcal A_{\overline r}} \] 最终得出 \(Pr_C=(\widehat e,\widehat v,\{\widehat{m_j}\}_{j\in \mathcal A_{\overline r}},A')\) 是凭证 \(C_p\) 的子证明; (4.2.2.3)对每一个断言 \(p\) ,计算: \[ \tag{4.32}\{\widehat{u_i}\leftarrow \widetilde{u_i}+c_Hu_i\}_{1\le i\le 4}; \] \[ \tag{4.33}\{\widehat{r_i}\leftarrow \widetilde{r_i}+c_Hr_i\}_{1\le i\le 4}; \] \[ \tag{4.34}\widehat{r_\Delta}\leftarrow \widetilde{r_\Delta}+c_Hr_\Delta; \] \[ \tag{4.35}\widehat\alpha\leftarrow \widetilde\alpha +c_H(r_\Delta-u_1r_1-u_2r_2-u_3r_3-u_4r_4); \] 最终得出 \(Pr_p=(\{\widehat{u_i}\},\{\widehat{r_i}\},\widehat{r_\Delta},\widehat{\alpha},\widehat{m_j})\) 是断言 \(p\) 的子证明; 4.2.3 Holder发送信息给Verifier Holder发送 \((c_H,\mathcal X,\{Pr_c\},\{Pr_p\},\mathcal C)\) 给verifier。 4.3 Verifier验证 对于凭证对 \((C_p,C_{NR})\) ,Verifier收到证明相关参数 \((c_H,\mathcal X,\{Pr_c\},\{Pr_p\},\mathcal C)\) 4.3.1 非撤销检查 Verifier计算以下公式,并将结果放入集合 \(\widehat T\) : \[ \tag{4.36} \widehat{T_1}\leftarrow E^{c_H}\cdot h^{\widehat{\rho}}\widetilde h^{\widehat o};\ \widehat{T_2} \leftarrow E^{\widehat c}h^{-\widehat m}\widetilde h^{-\widehat t} \] \[ \tag{4.37} \widehat{T_3} \leftarrow \Big(\cfrac{e(h_o\mathcal G,\widehat h)}{e(A,y)} \Big)^{c_H}\cdot e(acc_V,\widehat h)^{\widehat c}\cdot e(\widetilde h,\widehat h)^{\widehat r}\cdot e(\widetilde h,y)^{-\widehat{\rho}}\cdot e(\widetilde h,\widehat h)^{-\widehat m}\cdot e(h_1,\widehat h)^{-\widehat{m_2}}\cdot e(h_2,\widehat h)^{-\widehat s}; \] \[ \tag{4.38} \widehat{T_4}\leftarrow \Big(\cfrac{e(\mathcal G,acc_V)}{e(g,\mathcal W)z} \Big)^{c_H}\cdot e(\widetilde h,acc_V)^{\widehat r}\cdot e(1/g,\widehat h)^{\widehat {r'}};\ \widehat{T_5} \leftarrow D^{c_H}\cdot g^{\widetilde r} \widetilde h^{\widetilde{o'}}; \] \[ \tag{4.39} \widehat{T_6}\leftarrow D^{\widehat{r''}}g^{-\widehat{m'}}\widetilde h^{-\widehat{t'}};\ \widehat{T_7}\leftarrow \Big(\cfrac{e(pk\cdot \mathcal G,\mathcal S)}{e(g,g')} \Big)^{c_H}\cdot e(pk\cdot \mathcal G,\widehat h)^{\widehat{r''}}\cdot e(\widetilde h,\widehat h)^{-\widehat{m'}}\cdot e(\widetilde h,\mathcal S)^{\widehat r}; \] \[ \tag{4.40} \widehat{T_8}\leftarrow \Big(\cfrac{e(\mathcal G,u)}{e(g,\mathcal U)} \Big)^{c_H}\cdot e(\widetilde h,u)^{\widehat r}\cdot e(1/g,\widehat h)^{\widehat{r'''}}; \] 4.3.2 验证正确性 Verifier获取Issuer的公钥 \(pk_I\leftarrow (n,S,Z,{R_i}_{1\leq i\leq l})\) 、Primary凭证的证明 \(Pr_C=(\widehat e,\widehat v,\{\widehat{m_j}\}_{j\in \mathcal A_{\overline r}},A')\) ,并使用已披露属性 \(\{m_j\}_{j\in \mathcal A_r}\) ,定义空集合 \(\widehat{\mathcal T}\) ; (4.3.2.1)对于每个凭证 \(C_p\) 都使用其对应的子证明 \(Pr_C\) 进行计算,并将其结果放入集合 \(\widehat{\mathcal T}\) : \[ \tag{4.41}\widehat T\leftarrow \Bigg(\cfrac{Z}{\big(\prod_{j\in \mathcal A_r}R_j^{m_j}\big)(A')^{2^{596}}} \Bigg)^{-c_H}(A')^{\widehat e}\Bigg(\prod_{j\in (\mathcal A_{\widetilde r})}R_j^{\widehat{m_j}} \Bigg)(S^{\widehat v})\ (mod\ n) \] (4.3.2.2)对每个断言 \(p\) 进行计算: 得出\(\Delta'\) : \[ \tag{4.42}\Delta' \leftarrow \begin{cases} z_j; &\text{if } * \equiv\ \leq\\ z_j-1; &\text{if } * \equiv\ <\\ z_j; &\text{if } * \equiv\ \geq\\ z_j+1; &\text{if } * \equiv\ > \end{cases} \] 得出\(a\) : \[ \tag{4.43} a\leftarrow \begin{cases} -1 &\text{if } * \equiv\ \leq\ or\ <\\ 1 &\text{if } * \equiv\ \geq\ or\ > \end{cases} \] 使用断言子证明 \(Pr_p=(\{\widehat{u_i}\},\{\widehat{r_i}\},\widehat{r_\Delta},\widehat{\alpha},\widehat{m_j})\) 以及集合 \(\mathcal C\) ,进行计算: \[ \tag{4.44}\{\widehat{T_i}\leftarrow T_i^{-c_H}Z^{\widehat{u_i}}S^{\widehat{r_i}}\ (mod\ n)\}_{1 \le i\le 4}; \] \[ \tag{4.45} \widehat{T_\Delta}\leftarrow (T_{\Delta}^aZ^{\Delta'})^{-c_H}Z^{\widehat{m_j}}S^{a\widehat{r_\Delta}}\ (mod\ n); \] \[ \tag{4.46} \widehat{Q}\leftarrow (T_\Delta^{-c_H})\prod_{i=1}^4 T_i^{\widehat{u_i}}(S^{\widehat \alpha})\ (mod\ n); \] 最终将 \(\widehat{T_1},\widehat{T_2},\widehat{T_3},\widehat{T_4},\widehat{T_{\Delta}},\widehat Q\) 加入到集合 \(\widehat{\mathcal T}\) ; 4.3.3 最终的哈希比较 Verifier计算 \(\widehat{c_H}\leftarrow H(\widehat{\mathcal T},\mathcal C,n_2)\) ;如果 \(c_H=\widehat{c_H}\) 则验证成功,否则失败; 5. 证明 欲证明 \(c_H=\widehat{c_H}\) 成立,即证明 \(H(\mathcal T,\mathcal C,n_2)=H(\widehat{\mathcal T},\mathcal C,n_2)\) 成立,即证明 \(\mathcal T=\widehat{\mathcal T}\) ; 在 \(\mathcal T\) 中,集合为: \(\{T,\{\overline {T_i}\}_{1\le i\le 4},\overline{T_{\Delta}},Q \}\) ; 在 \(\widehat{\mathcal T}\) 中,集合为: \(\{\widehat T,\{\widehat{T_i}\}_{1\le i\le 4},\widehat{T_\Delta},\widehat Q\}\) ; 5.1 证明 \(T=\widehat T\) \(\{\widehat{T_i}= T_i^{-c_H}Z^{\widehat{u_i}}S^{\widehat{r_i}}\ (mod\ n)\}_{1 \le i\le 4};\) Prover计算: \(\overline{T_1}= Z^{\widetilde{u_1}}S^{\widetilde{r_1}}\ (mod\ n)\}\) Verifier计算: \(\widehat{T_1}= T_1^{-c_H}Z^{\widehat{u_1}}S^{\widehat{r_1}}\ (mod\ n)\) 验证过程: \(T_1= Z^{u_1}S^{r_1}\ (mod\ n)\) \(u_1,r_1\)为随机数 \(c=H(U||\widetilde U||n_0)\) 验证 \[ T\leftarrow (A')^{\widetilde e}\Big(\prod_{j\in \mathcal A_{\overline r}}R_j^{\widetilde{m_j}}\Big)(S^{\widetilde v})\ (mod\ n) \] 和 \[ \widehat T\leftarrow \Bigg(\cfrac{Z}{\big(\prod_{j\in \mathcal A_r}R_j^{m_j}\big)(A')^{2^{596}}} \Bigg)^{-c_H}(A')^{\widehat e}\Bigg(\prod_{j\in (\mathcal A_{\widetilde r})}R_j^{\widehat{m_j}} \Bigg)(S^{\widehat v})\ (mod\ n) \] \(\widetilde e\)为 456bit随机数 \(\widetilde v\)为 3060bit随机数 随机取随机数: \(\rho,\rho',r,r',r'',r''',o,o'\ mod\ q\) ; \(\widetilde{\rho},\widetilde{o},\widetilde{o'},\widetilde{c},\widetilde{m},\widetilde{m'},\widetilde{t},\widetilde{t'},\widetilde{m_2},\widetilde{s},\widetilde{r},\widetilde{r'},\widetilde{r''},\widetilde{r'''},mod\ q\)为随机数 随机素数\(e,\ where\ 2^{596}\leqslant e \leqslant 2^{596}+2^{119}\) \(e' \gets e-2^{596}\) \(\widehat e\leftarrow \widetilde e+c_He'\) \(v_1,v_2\)为2128,673bit随机数 \(v=v_1+v_2\) \(v'\gets v-e\cdot r\) \(\widehat v\leftarrow \widetilde v+c_Hv'\) \(\widehat{m_j} \leftarrow \widetilde{m_j} +c_Hm_j\ (mod\ q)\) \[ T\leftarrow (A')^{\widetilde e}\Big(\prod_{j\in \mathcal A_{\overline r}}R_j^{\widetilde{m_j}}\Big)(S^{\widetilde v})\ (mod\ n) \] \[ \Bigg(\cfrac{Z}{\big(\prod_{j\in \mathcal A_r}R_j^{m_j}\big)(A')^{2^{596}}} \Bigg)^{-c_H}(A')^{\widehat e}\Bigg(\prod_{j\in (\mathcal A_{\widetilde r})}R_j^{\widehat{m_j}} \Bigg)(S^{\widehat v})\\ = \Bigg(\cfrac{Z}{\big(\prod_{j\in \mathcal A_r}R_j^{m_j}\big)(A')^{2^{596}}} \Bigg)^{-c_H}(A')^{ \widetilde e+c_He'}\Bigg(\prod_{j\in (\mathcal A_{\widetilde r})}R_j^{\widetilde{m_j} +c_Hm_j} \Bigg)(S^{\widetilde v+c_Hv'}) \] 除以\(T\), 得到 \[ \Bigg(\cfrac{Z}{\big(\prod_{j\in \mathcal A_r}R_j^{m_j}\big)(A')^{2^{596}}} \Bigg)^{-c_H}(A')^{c_He'}\Bigg(\prod_{j\in (\mathcal A_{\widetilde r})}R_j^{c_H{m_j}} \Bigg)(S^{c_Hv'})\\ \] 提取A \[ \Bigg(\cfrac{Z}{\big(\prod_{j\in \mathcal A_r}R_j^{m_j}\big)(A')^{2^{596}}} \Bigg)^{-c_H}(A')^{c_He'}\Bigg(\prod_{j\in (\mathcal A_{\widetilde r})}R_j^{c_H{m_j}} \Bigg)(S^{c_Hv'})\\ =\Bigg(\cfrac{Z}{\big(\prod_{j\in \mathcal A_r}R_j^{m_j}} \Bigg)^{-c_H}(A')^{c_H(e'+2^{596})}\Bigg(\prod_{j\in (\mathcal A_{\widetilde r})}R_j^{c_H{m_j}} \Bigg)(S^{c_Hv'})\\ =\Bigg(\cfrac{Z}{\big(\prod_{j\in \mathcal A_r}R_j^{m_j}} \Bigg)^{-c_H}(A')^{c_He}\Bigg(\prod_{j\in (\mathcal A_{\widetilde r})}R_j^{c_H{m_j}} \Bigg)(S^{c_Hv'}) \] 提取\(\prod\) \[ Z^{-c_H}(A')^{c_He}(S^{c_Hv'})\Bigg(\prod_{j\in (\mathcal A_{r})}R_j^{c_H{m_j}}\Bigg)\Bigg(\prod_{j\in (\mathcal A_{\widetilde r})}R_j^{c_Hm_j}\Bigg) \] \[ = Z^{-c_H}(A')^{c_He}(S^{c_Hv'})\Bigg(\prod_{j\in \mathcal A}R_j^{c_H{m_j}}\Bigg) \] \[ =Z^{-c_H}(A')^{c_He}(S^{c_Hv'})\Bigg(\prod_{j\in \mathcal A}R_j^{c_H{m_j}}\Bigg) \] \(Z=S^{x_Z}\) \(A'=AS^r\) \(A_c+A_k=A\) \(A_r+A_\widetilde {r} =A\) \(A\)表示所有属性 \(Q\leftarrow \cfrac{Z}{US^{v_2}\prod_{i\in A_k}R_i^{m_i}(mod\ n)}\\\) \(U=(S^{v_1})\prod_{i\in A_c}R_i^{m_i}\) \(A\leftarrow Q^{e^{-1} (mod\ p'q')}(mod\ n)\) \[ Z^{-c_H}(A')^{c_He}(S^{c_Hv'})\\ =Z^{-c_H}S^{rc_He}(\cfrac{Z}{US^{v_2}\prod_{i\in A_k}R_i^{m_i}(mod\ n)})^{c_He\cdot e^{-1}}(S^{c_Hv'})\\ =S^{rc_He+c_Hv'}((S^{v_1+v_2})\prod_{i\in A_c}R_i^{m_i}\prod_{i\in A_k}R_i^{m_i}(mod\ n))^{-c_H}\\ =S^{rc_He+c_H(v-er)-c_Hv}\prod_{i\in A_c}R_i^{m_i}\prod_{i\in A_k}R_i^{m_i}(mod\ n))^{-c_H}\\ = (\prod_{i\in A_c}R_i^{m_i}\prod_{i\in A_k}R_i^{m_i}(mod\ n)))^{-c_H}\\ = \Bigg(\prod_{j\in \mathcal A}R_j^{-c_H{m_j}}\Bigg) \] 连乘公式左右为披露属性和未披露属性: \(R_i= S^{x_{R_i}}\) 即: \[ \Bigg(\prod_{j\in \mathcal A}R_j^{-c_H{m_j}}\Bigg)\cdot \Bigg(\prod_{j\in \mathcal A}R_j^{c_H{m_j}}\Bigg) =1 \] 证毕。 5.2 证明 \(\overline{T_\Delta}=\widehat{T_\Delta}\) \[ \overline{T_\Delta}\leftarrow Z^{\widetilde{m_j}}S^{a\widetilde{r_\Delta}}\ (mod\ n);\\ \widehat{T_\Delta}\leftarrow (T_{\Delta}^aZ^{\Delta'})^{-c_H}Z^{\widehat{m_j}}S^{a\widehat{r_\Delta}}\ (mod\ n); \] 其中: \[ T_\Delta=Z^{\Delta}S^{r_\Delta}\\ \widehat{m_j}=\widetilde{m_j}+c_Hm_j\\ \widehat{r_\Delta}\leftarrow \widetilde{r_\Delta}+c_Hr_\Delta;\\ \] 所以有: \[ \Large\begin{aligned} \widehat{T_\Delta}&=(Z^{\Delta a} S^{ar_\Delta}\cdot Z^{\Delta '})^{-c_H}\cdot Z^{\widetilde{m_j}+c_H m_j}\cdot S^{a(\widetilde{r_\Delta}+c_H r_\Delta)}\\ &=Z^{-\Delta a c_H} S^{-c_Har_\Delta}\cdot Z^{-c_H\Delta '}\cdot Z^{\widetilde{m_j}+c_H m_j}\cdot S^{a\widetilde{r_\Delta}+ac_H r_\Delta}\\ &=Z^{\widetilde{m_j}}Z^{c_H(m_j-a\Delta-\Delta')}\cdot S^{a\widetilde {r_\Delta}} \end{aligned} \] 再根据: \[ \Delta \leftarrow \begin{cases} z_j-m_j; &\text{if } * \equiv\ \leq\\ z_j-m_j-1; &\text{if } * \equiv\ <\\ m_j-z_j; &\text{if } * \equiv\ \geq\\ m_j-z_j-1; &\text{if } * \equiv\ > \end{cases}\\ \Delta' \leftarrow \begin{cases} z_j; &\text{if } * \equiv\ \leq\\ z_j-1; &\text{if } * \equiv\ <\\ z_j; &\text{if } * \equiv\ \geq\\ z_j+1; &\text{if } * \equiv\ > \end{cases}\\ a\leftarrow \begin{cases} -1 &\text{if } * \equiv\ \leq\ or\ <\\ 1 &\text{if } * \equiv\ \geq\ or\ > \end{cases} \] 假设这里的原属性值是 20 ,待检测基准值 18 ,那么 Verifier是检测 \(>\) 关系,检测原属性值是大于基准值的,所以有: \[ \begin{aligned} \Delta &\leftarrow m_j-z_j-1\\ &\leftarrow 20-18-1\\ &\leftarrow 1\\ a &\leftarrow 1\\ \Delta'&\leftarrow z_j+1\\ &\leftarrow 18+1\\ &\leftarrow 19 \end{aligned} \] 所以可得: \[ m_j-a\Delta-\Delta'=20-1-19=0 \] 所以上式可得: \[ \begin{aligned} \widehat{T_\Delta}&=Z^{\widetilde{m_j}}Z^{c_H(m_j-a\Delta-\Delta')}\cdot S^{a\widetilde {r_\Delta}}\\ &=Z^{\widetilde{m_j}}Z^{c_H(0)}\cdot S^{a\widetilde {r_\Delta}}\\ &=Z^{\widetilde{m_j}}S^{a\widetilde{r_\Delta}}\\ &=\overline{T_\Delta} \end{aligned} \] 证毕。]]></content>
<categories>
<category>区块链项目</category>
</categories>
<tags>
<tag>Identity</tag>
<tag>Zero-Knowledge Prove</tag>
<tag>Hyperledger</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Mathematics in Cryptography]]></title>
<url>%2F2019%2F08%2F11%2FMathematics-in-Cryptography%2F</url>
<content type="text"><![CDATA[原作时间:2018年3月31日 密码学中的离散数学知识学习 密码学中的近世代数实在是让人头疼,在实际阅读文章中很吃力,于是决心下点苦工补一补代数的知识。(本科有学习过离散数学,终于还是吃了数学的亏。谁要是再说学数学没用我就*@$%!) 首先是学习这篇文章里的知识点,和之前学习过的离散数学无异,但是这篇文章好就好在了深度展开了许多知识点,并用较为简洁的例子讲解。但是呢,有点不足的是,因为代数系统他是一环扣一环的,有很强的迭代,往往会让人拎不清谁是谁。本文引用这篇文章就想能更加拎清楚概念。 离散数学基础 二次关系 一些其他的二次关系就暂且不提,只说一些与密码学相关的. 二次关系的一些性质:(其中,A是集合,R是集合中的关系) - 自反性 反自反性 对称性 反对称性 传递性 定义 X∈A,有(x,x)∈R x∈A,有(x,x)不∈R 若(x,y)∈R,则(y,x)∈R 若(x,y)∈R,则(y,x)不∈R 若(x,y)∈R,且(y,z)∈R,则(x,z)∈R 等价关系和偏序关系 等价关系: R是非空集A的关系,如果R是 自反,对称,传递 的,则称R为A上的等价关系. 举个栗子: 在实数集合中,等号'='就是一个等价关系.假设a=b=c=1; a,b,c都∈实数R;符合自反性:a=b; 符合对称性:a=b则b=a;符合传递性:a=b且b=c,则a=c; 偏序关系: R是非空集A的关系,如果R是 自反,反对称,传递 的,则称R为A上的偏序关系. 举个栗子: 在实数集合中,大等于号'≥'就是一个偏序关系。假设a≥b≥c; a,b,c都∈实数R; 符合自反性: a≥a; 符合反对称性: a≥b 则 b不≥a; 符合传递性: a≥b且b≥c,则a≥c; 若集合S上定义了一个偏序R,则S成为 偏序集 (S,R) 设有偏序集(S,≤),(note:偏序关系'≤'并非实数的小等于) 若有任意x∈S,且b≤x,则称b为S的 下界 ; 若有任意x∈S,且x≤b,则称b为S的 上界 ; 若b是一个下界,且对于每一个S的下界b'都有b'≤b,则b是S的 最大下界或下确界 . 若b是一个下界,且对于每一个S的下界b'都有b≤b',则b是S的 最小上界或上确界 . (Note: 上界和下界有可能不唯一) 二元运算及其性质 代数中的二元运算的内容和小学学过的乘法结合律,交换了,幂等律差不多,所以不再详细说. 主要介绍幺元,零元,逆元的定义。(假设*是集合S中的二元运算) 幺元 : 若存在元素e∈S,使任何x∈S,有 e*x=x,x*e=x 则,e是集合S中关于*运算的幺元。就像1在实数集合关于×运算的幺元。 零元 : 若存在元素θ∈S,使任何x∈S,有 θ*x=θ,x*θ=θ 则,θ是集合S中关于*运算的零元。就像0在实数集合关于+运算的零元。 逆元 : e∈S是运算*的幺元,对任意x∈S,若存在y∈S,且 y*x=e,x*y=e 则,y是x的逆元。就像所有实数(除0之外)在实数集合中的倒数,相乘都等于关于×运算幺元1,这些相应的倒数就是这些实数的逆元。 典型代数系统 半群 在一个集合S中定义了某种运算(记作加法“+”,但这个加法指代广泛意义上的运算,并不是指日常使用的加法),那么在这个集合上,如果这种运算满足以下性质,那么他和集合S共同组成一个半群,记作(S,+): 封闭性。也就是运算的结果始终在集合S内 结合律。也就是满足:(a + b) + c= a + (b + c) 举例: 在实数集合R中,加法'+'符合封闭性:加法运算的所有结果都是实数; 符合结合律; 所以(R,+)形成半群。 幺半群 如果在一个半群(S,+)中存在一个幺元e,使得任意x∈S都有: x + e = e + x = x 那么该半群就是一个幺半群. 举例: 在刚才例子中的半群(R,+)中,存在一个幺元0,使得任意x∈R都有 x + 0 = 0 + x = x. 群 如果在一个幺半群(S,+)中,任意元素x∈S,都存在唯一对应元素y使得: x + y = y + x = e , 其中e是幺元 即: 任意元素x∈S,都存在唯一逆元与之对应. 那么该幺半群就是一个 群。这样就在群中定义了减法. 交换群(Abel群) 如果一个群(S,+)符合交换律,即对于集合S中任意元素x,y∈S,有: x+y=y+x 那么这个群就是交换群. 来总结一下刚才所提到的群概念的迭代: - 半群 幺半群 群 交换群 性质 封闭性,结合律 封闭性,结合律,存在幺元 封闭性,结合律,存在幺元,存在逆元 封闭性,结合律,存在幺元,存在逆元,交换律 迭代 +封闭性,结合律 +存在幺元 +存在逆元 +交换律 环 设 (S,+,)是一个代数系统,其中S为集合,+,是二元运算。若有: 1。(S,+)是Abel群(交换群)。(结合律,交换律,存在幺元和逆元) 2。(S,)是半群。 (结合律) 3。二元运算对于+适合分配律. 则(S,+,*)是一个 环 .且群(S,+)中的 幺元 是环(S,+,*)的 零元 . 举例:在实数集合中,(R,+)是个交换群,(R,×)是半群,且加法和乘法符合分配律,所以(R,+,×)是一个环. 零因子 : 若在环(S,+,*)中,且该环零元为θ,存在a,b∈S,且a!=θ,b!=θ,但有a*b=θ,则称a为S中的左零因子,b为S中的右零因子. 整环 若环(S,+,*)中(S,*)半群 符合交换律,且存在幺元,且无零因子,那么该环就称为整环. 例如 整数环(R,+,×)就是整环. 除环 若环(S,+,*)中(S,*)半群存在幺元,无零因子,且对任意x∈S,都存在除 零元 以外的逆元,那么该环就成为除环 除环定义了乘法逆元的存在,也就是除法. 交换环 若环(S,+,*)中(S,*)满足交换律,那么环(S,+,*)是 交换环. 来总结一下刚才所提到的环概念的迭代: (其中环都表示为(S,+,*)) - 环 交换环 整环 除环 定义 (S,+)是交换群,(S,*)是半群,符合分配律 (S,+)是交换群,(S,*)是交换半群,符合分配律 (S,+)是交换群,(S,*)是幺半群且符合交换律,符合分配律 (S,+)是交换群,(S,*)是幺半群且有逆元(零元以外),符合分配律 迭代 (S,+)交换群,(S,*)半群 (S,*)+交换律 (S,*) +有幺元,无零因子,符合交换律 (S,*)+有幺元,有逆元,无零因子 域 如果一个环(S,+,*),既是除环又是交换环,那么它就是一个域. 例如:(R,+,*)既是除环又是交换环,所以它是一个域,成为 实数域. 格 设(S,R)是 偏序集 ,若有任意x,y∈S,{x,y}都有最小上界和最大下界,则称S关于偏序R构成一个格. 有限域 如果一个域的元素是有限的,那么就是一个有限域。相对地,无限域犹如实数域一样,元素个数是无限的. 有限域中的元素个数被称为有限域的 阶(Order).有限域的阶一定是某个素数p的正整数次幂. 模p的有限域 GF(p) GF(p)是定义在整数集合{0,1,...,p-1}上的域。GF(p)上的加法和乘法分别是模加法和模乘法. 加法和乘法 .(br) 模加法和模乘法和普通的整数加法和乘法有些不同.例如在GF(7)定义在{1,2,..6}上,加法和乘法如下:(br) 121 + 2 = 3 mod 7 = 31 * 2 = 2 mod 7 = 2 减法 (br) a减去b,其实就是加上b的加法逆元。已知GF(7)的加法幺元是0,于是x的加法逆元y就有:( x + y ) mod 7 = 0; 121 - 2 = 1 + ( -2 ) = 1 + 5 = 6 mod 7 = 6 or1 - 2 = -1 mod 7 = 6 除法 (br) a除以b,需要找到b的乘法逆元,已知GF(7)的乘法幺元是1,于是x的乘法逆元就有: 123x * y mod 7 = 1也就是解下面这个方程:b * x = 1 + 7*k ,其中k是正整数. 实际求解过程并不简单,直接上实例: 123453 ÷ 4= 3 * (1/4)= 3 * 2= 6 mod 7= 6; 有限域GF(2^m) 在里德-所罗门编码(二维码使用的编码)以及椭圆曲线加密中都有使用。 GF(2m)包含了2m个元素。因为计算机的二进制所以选用2这个质数。2m个元素恰好是长度为m的二进制.具有更高的计算效率。 为了方便,之后都将GF(2m)中的元素表示成长度为m的二进制形式,以m=3为例。 加法和减法 (br) GF(2m)上的加法减法都是异或运算。加法的幺元是0.(br) 010和110都是GF(23)的元素,有: 12010 + 110 = 010 ⊕ 110 = 100010 - 110 = 010 ⊕ 110 = 100 乘法 (br)太繁琐了,就不认真写了.看这链接. 因为之前学习ABE的构造加密策略的时候遇到了一些问题,例如LSSS的原理,拉格朗日多项式插值,双线性配对,DH密钥交换等问题。 需要进一步deep dive。 LSSS原理学习 这一篇博客从访问控制树开始说起,再到SSS密码分享方案,说得很详细。 所以我就以这篇博客为范本开始学习LSSS。 控制树就不说了,之前的学习有详细描述。 2008年RSA的S,Shamir提出来一种 秘密分享方案SSS(secret sharing scheme)。 Shamir秘密分享方案利用了 拉格朗日多项式插值方法,其基本思想是:如果预先定义了一个t-1阶的多项式,那么如果知道这个多项式上的t个点,则一定能完整恢复出这个多项式. 这个拉格朗日多项式插值法在之前的学习有学习到。在这个知乎@马同学的回答上有很详细很有趣的解说。 于是有拉格朗日多项式插值: \(\Large L(x):= \sum_{j=0}^{k}y_i\ell_j(x)\) 其中 \(\Large \ell_j(x):=\prod_{i=0,i\ne j}^{k}\frac{x-x_i}{x_j-x_i}\) 拉格朗日多项式插值法如何运用在秘密的分享上? 假设有t-1阶的多项式, 如果有t个线性无关的等式就肯定可以还原出这个多项式. 所以假设所要分享的秘密是S, 任取t-1个随机数 \(a_1,a_2,..,a_{t-1}\) 构造一个t-1阶多项式: \(f(x)=a_{t-1}x^{t-1}+a_{t-2}x^{t-2}+...+a_1x+S\). 对于每个用户i, 所分享的结果为 \((i,f(i))\) 所以当t个用户在场时,可以得到秘密S. 线性秘密分享方案(Linear Secret Sharing Scheme,LSSS) 只要是线性的秘密分享方案, 都可以用LSSS来描述. A secret sharing scheme \(Π\) over a set of parties \(P\) is called linear (over \(\mathbb{Z}_p\)) if the shares for each party form a vector over \(\mathbb{Z}_p\), and there exists a matrix \(M\) called the share-generating matrix for \(Π\). The matrix \(M\) has \(m\) rows and \(d\) columns. For \(i = 1, . . . , m\), the \(i^{th}\) row \(M_i\) of \(M\) is labeled by a party \(ρ(i)\) where \(ρ\) is a function from \(\{1, . . . , m\}\) to \(P\). Given a column vector \(\vec{v} = (s, r_2, . . , r_d)\), where \(s ∈ \mathbb{Z}_p\) is the secret to be shared and \(r_2, . . . , r_d ∈ \mathbb{Z}_p\) are randomly chosen, \(M\vec v\) is the vector of \(m\) shares of the secret \(s\) according to \(Π\). The share \(λ_i = (M\vec v)_i\), i.e., the inner product \(M_i · \vec v\), belongs to party \(ρ(i)\). 通过这个定义可以知道,一个秘密分享方案要被称作线性的需要符合如下: 每一个成员的份额通过 \(\mathbb{Z}_p\) 形成一个向量,且 存在一个分享生成矩阵 \(M\),矩阵的每一行都依次被一个成员所标记。 有一个向量 \(\vec{v} = (s, r_2, . . , r_d)\), s是需要分享的秘密, \(r_2, . . , r_d\) 是在 \(\mathbb{Z}_p\) 中随机选择的. 第i个成员所拥有的分享份额就是: \(M_i · \vec v\). M的第i行和这一列的积(结果还是一个向量). Any LSSS defined as above enjoys the linear reconstruction property defined as follows. Suppose that \(\Pi\) is an LSSS for access structure \(\mathbb{A}\). Let \(S \in \mathbb{A}\) be an authorized set, and \(I \subset \{1, \ldots, m\}\) be defined as \(I = \{i: \rho(i) \in S\}\). There exist constants \(\{\omega_i \in \mathbb{Z}_p\}_{i \in I}\) satisfying \(\sum_{i \in I}{\omega_i M_i} = (1, 0, \ldots, 0)\) , so that if \(\{\lambda_i\}\) are valid shares of any secret s according to \(\Pi\), then \(\sum_{i \in I}{\omega_i \lambda_i} = s\) . Furthermore, these constants \(\{\omega_i\}\) can be found in time polynomial in the size of the share-generating matrix M. For any unauthorized set, no such constants exists. The LSSS is denoted by \((M, \rho)\). 上面所定义的LSSS有如下定义的线性重建属性. 假设在一个访问结构A中, I为分享组的所有成员. 对于每个分享组成员 i 总在p阶整数域内存在一个常数 \(\omega_i\) ,满足 \(\sum_{i \in I}{\omega_i M_i} = (1, 0, \ldots, 0)\), 即对于每个合法分享成员所持有的秘密 \(\lambda_i\) 总有 \(\sum_{i \in I}{\omega_i \lambda_i} = s\) 得出最终秘密s. 所以这个常数的求解就是LSSS的解密关键. 求解常数 \(\omega\) 从定义可知 \(\vec \lambda = M \cdot \vec v\) ,M为分享生成矩阵,向量 \(\vec{v} = (s, r_2, . . , r_d)\),恢复出向量v的第一项S,也就是所要求的秘密. 因为矩阵M并不是一个方阵, 不存在它的逆矩阵, 所以想到使用M的某个子阵求逆.(博客原话,需要进一步推敲为什么.) 矩阵M的列d代表着至少需要d方参与才能恢复. 但是并不是属性个数满足列数就能访问, 例如(A or B)and(C or D), 若属性集合是{A,B}也不能访问, 所以意味着,A和B在矩阵对应的行是重复的,可以删去. 所以我们需要在集合中找到一个子集,使得子集对应的矩阵M的行所组成的子阵满足满秩就行了. 如何找到这样的矩阵,就要用到单调访问政策的单调性了. 单调性意味着,一个属性是冗余的,那么去掉这个属性也能满足访问控制政策. 用遍历的方法,去除各个属性,就能得到一个子矩阵M',其对应的分享为 \(\vec \lambda'\) M'满足可逆性. \(s = (1, 0, \ldots, 0) \cdot \vec v = (1, 0, \ldots, 0) \cdot M'^{-1} \vec \lambda'\) . 因为 \(\sum_{i \in I}{\omega_i \lambda_i} = s\) 所以有 \(\vec \omega = (1, 0, \ldots, 0) \cdot \vec M'^{-1}\). 这意味着不需要知道 \(\vec \lambda\) 只需要知道LSSS的矩阵M,已经知道能够满足恢复S条件的属性集合就行了. 构造LSSS矩阵 2010年, Lewko和Waters在论文5中提到,只要是 AND和OR描述的都可以转换为LSSS方案. We now describe a general algorithm for converting a boolean formula into an equivalent LSSS matrix. We consider the boolean formula as an access tree, where interior nodes are AND and OR gates and the leaf nodes correspond to attributes. We will use \((1,0,\ldots,0)\) as the sharing vector for the LSSS matrix. We begin by labeling the root node of the tree with the vector (1)(a vector of length 1). We then go down the levels of the tree, labeling each node with a vector determined by the vector assigned to its parent node. We maintain a global counter variable c which is initialized to 1. If the parent node is an OR gate labeled by the vector v, then we also label its children by v (and the value of c stays the same). If the parent node is an AND gate labeled by the vector v, we pad v with 0’s at the end (if necessary) to make it of length c. Then we label one of its children with the vector \((v|1)\) (where | denotes concatenation) and the other with the vector \((0,\dots, 0 | -1)\), where \((0, \ldots, 0)\) denotes the zero vector of length c. Note that these two vectors sum to \((v|0)\). We now increment the value of c by 1. Once we have finished labeling the entire tree, the vectors labeling the leaf nodes form the rows of the LSSS matrix. If these vectors have different lengths, we pad the shorter ones with 0’s at the end to arrive at vectors of the same length. 将布尔表达式化为访问树, 其中内部节点是AND和OR门, 叶子节点表示为属性. 将树的根节点标记为 1,从上往下依次向每个节点根据父节点的向量添加向量. 维护一个全局变量 C ,C从1开始记. 若父节点是OR门, 且父节点被标记为v, 那么子节点也标记为v,且变量C保持不变. 若父节点是AND门,且父节点被标记为v, 那么将用'0'来填充v的尾部(如果需要的话)来保证最终长度为C.将其中一个子节点标记为向量 \(v|1\) (其中'|'表示串联); 其他的子节点标记为 \((0,\dots, 0 | -1)\), 其中 \((0,\dots,0)\) 表示长度为 C 的零向量. 且C+1. 这两个向量的和为 \(v|1 + (0,\dots,0)|-1=v|0\). 当我们完成了整个树的标记, 标记的叶节点就是LSSS矩阵的行. 如果这些向量有不同的长度,就在尾部用'0'来填充. 不过不同的方案可以有不同的LSSS矩阵构造方案, 具体问题具体分析. 此外布尔表达式如何转化为访问树结构还需进一步学习. 这里有一些Parser源码,可以参考(链接). Diffie-Hellman密钥交换学习 Diffie-Hellman密钥交换(简称DH密钥交换)是可以让对等的双方在完全缺乏对方信息的前提下, 通过不安全的信道达成一个共享的密钥. DH密钥交换的方法是建立在计算离散对数(Discrete Logarithm Problem)的困难程度上的. 之前的学习(链接)有详细描述,在此就不展开探讨. 总而言之就是一个模p有限域的问题. 例如: 若p是一个素数,g和x都是p阶域中的整数, 计算 \(y=g^x \bmod p\) 很简单. 相反的, 若已知素数p,g和y,要求x满足等式 \(y=g^x \bmod p\) 就是非常困难的. 当然, 基于安全性的考虑, 这里的 p通常都是很大的素数,通常取1024bit, 且(p-1)/2也是素数. G是素数p的原根(primitive root). 原根可以保证: \(g^i\bmod p\ne g^j\bmod p,\ where\ i\ne j\ and\ i,j\in (0,p-1)\) DH密钥交换具体算法如下: Alice和Bob约定 \(p\) 和 \(g\) 的值 Alice生成私钥 \(x\),计算 \(g^x\bmod p\) 作为公钥公布出去 Bob生成私钥 \(y\),计算 \(g^y\bmod p\) 作为公钥公布出去 Alice得知 \(g^y\bmod p\) 后,计算 \(s=(g^y\bmod p)^x\bmod p=(g^y)^x\bmod p=g^{xy}\bmod p\) Bob得到 \(g^x\bmod p\) 后,计算 \(s=(g^x\bmod p)^y\bmod p=(g^x)^y\bmod p=g^{xy}\bmod p\) 双方都得到了相同的密钥的 \(s\),交换完毕 在上面的流程中,私钥 \(x,y\) 始终是Alice和Bob自己保管的, 窃听到的只有 \(p,g,g^x\bmod p,g^y\bmod p\). 可以保证安全性. 双线性配对学习 双线性配对(Bilinear Pairing)最初在2001年由Boneh和Franklin利用它构造了第一个实用并且可证安全的基于身份的加密方案(IBE). 素数阶双线性群(Prime-Order Bilinear Groups) 双线性配对定义了三个素数p阶群乘法循环群(有些方案是加法循环群, 例如椭圆曲线的双线性构造) \(G_1,G_2和G_T\). 并且定义了这三个群的一个配对(映射)关系 \(e:G_1×G_2→G_T\) (这里的乘和矩阵的乘相似),并且满足如下性质: 双线性: 对于任意 \(g_1\in G_1,g_2\in G_2,\ a,b\in Z_p\) 均有 \(e(g_1^a,g_2^b)=e(g_1,g_2)^{ab}\) 成立. 非退化性: \(\exists g_1 \in G_1, g_2 \in G_2\), 满足 \(e(g_1,g_2) \neq 1_{G_T}\). 可计算性: 存在有效的算法, 对于 \(\forall g_1 \in G_1, g_2 \in G_2\), 均可计算 \(e(g_1,g_2)\). 若 \(G_1 = G_2\) 则称上述双线性群是对称的. 合数阶双线性群(Composite-Order Bilinear Groups) 与素数阶类似, 区别在于 \(G_1,G_2和G_T\) 的介数是一个 合数 ,该合数是一些很大的素数的乘积. 例如:\(N=p_1×p_2×\cdots×p_n\) 也满足素数阶双线性群的三个性质. 与之不同的是,合数阶双线性群中,有阶数分别为 \(p_1,p_2,\dots,p_n\) 的子群 \(G_{p_1},G_{p_2},\dots,G_{p_n}\). 这些子群满足正交性. 也就是说: \(\forall g_i\in G_{p_i},\forall g_j\in G_{p_j},\ and\ i\ne j\ and\ e(g_i,g_j)=1\) 参考文章 记线性秘密分享方案(Linear Secret Sharing Scheme,LSSS)的实现 如何直观地理解拉格朗日插值法? 拉格朗日插值法(图文详解) 线性秘密共享方案(LSSS)构造与解密 Lewko, A., Waters, B.: Decentralizing attribute-based encryption. IACR Cryptology ePrint Archive, (2010) 351. https://eprint.iacr.org/2010/351. Diffie–Hellman 密钥交换协议简介 密码学中的离散数学知识学习 [可以解释一下密码学中什么叫双线性配对吗?@SDKany的回答]8 双线性映射(密码学常用算法) 斯坦福大学pbc库 谈谈有限域那些事儿 离散数学偏序关系哈斯图上(下)确界极小(大)值最大(小)值 第18章 格与布尔代数]]></content>
<categories>
<category>密码学</category>
</categories>
<tags>
<tag>cryptography</tag>
<tag>mathematics</tag>
</tags>
</entry>
<entry>
<title><![CDATA[IoT调研报告]]></title>
<url>%2F2019%2F07%2F31%2FIoT-research-report%2F</url>
<content type="text"><![CDATA[一、简述 本文从物联网(IoT)技术的基础知识开始,主要介绍了物联网的基本定义、主要通信协议,并对现在物联网技术所面临的挑战进行了详细分析。在第三章,研究区块链与物联网结合的契合点,分析区块链是如何解决物联网现在面临的挑战,并提供一些物联网部署在区块链的方法。在第四章,从区块链在物联网中身份标识治理的角度切入,通过对比现有中心化身份管理方法,研究基于区块链的实体身份标识可以如何解决物联网相关的痛点,并给出现有案例(学术上、工业上)。 二、认识IoT 物联网是一个计算设备、电子器械、物体、动物或人相互关联的系统,具有唯一标识符(UID)和通过网络传输数据、交互的能力,而无需人与人或人与计算机的互动,终极梦想是万物互联的世界。 如下图所示是一个物联网系统的样例,物联网生态系统由支持Web的智能设备组成,这些设备使用嵌入式处理器,传感器和通信硬件来收集、发送和处理从环境中获取的数据。 物联网设备通过连接到物联网网关或其他边缘设备来共享它们收集的传感器数据,其中数据被发送到云以进行本地分析或分析。 尽管人们可以与设备进行交互,但设备可以完成大部分工作而无需人工干预。 1. “三个维度”认识IoT 1.1 横向维度 - 物联网产业图谱 如下图所示,可以看到,身份管理以及安全控制贯穿整个生态架构。 1.2 纵向维度 - 物联网生态架构 可以简单把IoT核心架构分为4层模型: 应用程序层:对大量的数据进行处理、持久性存储、数据分析、数值预测; 平台服务层:主要包括数据管理、设备管理、应用集成、消息发布/订阅/传递、安全管理; 通信层:主要是支持数据的可靠传输,内置了感应层向管理控制层的通信机制,如Wifi、3G、LTE、 Ethernet等; 物理感应层:主要是设备、网关等硬件传感器和相应的传感网络; 1.3 时间维度 - 物联网的前世、今生与来世 在过去的几年中,前物联网从封闭的集中式大型机架构逐渐向以开放接入云为中心的物联网的替代方案发展;下一步物联网将在部署在多节点的分布式云上,实现真正的万物互联,区块链技术在这里充当重要的角色。 在这里作者由于知识储备原因(学术不精),主要简单介绍通信层的内容,在本章后面的内容展开介绍物联网技术现有的挑战,并在后面的章节介绍平台服务层的相关内容。 2. 现有IoT通信协议 如上图所示, 现有物联网中应用数据层的通信协议主要有以下几种: HTTP:因为其广泛的应用,兼容稳定性都很好,开发也简单,但在物联网大规模使用的情况下,实时性和消息一致性都不如MQTT协议来的表现出色,而且耗电量更大; Message Queuing Telemetry Transport(MQTT):MQTT协议开销较小(带宽和能耗),支持永久性连接,减少重连带来的开销,在物联网中大规模的并发连接场景具有优势; Constrained Application Protocol(CoAP):CoAP是一种可用于资源受限的设备上的数据应用协议,支持多播和低开销在物联网小型设备使用场景较实用; Extensible Messaging and Presence Protocol (XMPP):XMPP支持实时通讯、即时消息; 在网络层的路由协议主要有 6LoWPAN与RPL,这两种协议都意在资源受限的设备上能轻松访问网络,但也将带来被攻击的可能,详情可见论文[8]. 在 数据链路层的协议 一般就以频率、能耗、可用范围区分,以下图做对比总结: 3. 现有IoT方案存在的挑战 在过去的几年间,物联网垂直领域相关企业数量处于快速增长期,经过了幻想破灭期的洗礼,投资逐渐理性,技术逐渐成熟。虽然人们对于物联网可以推动许多商业机会、变革现有中心化体系有清楚的认识,但物联网还存在一系列的技术挑战,直接导致了全球物联网应用布局缓慢的局面。以下是对这些挑战的简述: 3.1 网络安全问题 物联网中的网络安全问题是最关键也是最致命的应用落地门槛。对于传统的Web安全而言,物联网设备往往条件更加严苛:设备条件通常是隔离的硬件,根据其部署条件,所有者往往无法有效监测到设备数据篡改;设备往往是和其他设备进行互联,管理这些M2M的交互、保证两端数据一致性与传统的C/S交互相比更加复杂;此外,物联网设备往往处于资源受限的状态(硬件性能、网络连接、电量低等),使得更加复杂的场景不能得以应用。因此,这种系统更加容易被网络攻击,在以下列出了几种物联网攻击方法与其相应的防御手段。 现存的IoT攻击方法与防御手段 物联网涵盖了从小型嵌入式处理芯片到大型高端服务器各种设备,因此遇到的安全问题都可能在不同层次不同级别。下图给出了从OSI网络模型自下往上地分析了物联网安全威胁的分类。各个攻击方式的具体防御手段可借鉴论文[2],在这里不赘述。 3.2 访问控制与隐私保护 物联网设备每日生成大量的数据,可提供设备所有者或者用户所在的环境详细信息以及个人习惯、隐私数据。这些数据可以在没有任何明确的用户授权下收集,并有可能在某个支持IoT共享平台上暴露给第三方。更糟的情况制造商挂羊头卖狗肉,IoT设备主动收集与所提供服务无关的数据。 用户除了必须信任集中式服务提供商不会侵犯他们的隐私之外,还必须相信数据的传输具有保密性和完整性。任何不安全的数据传输都会使得恶人在未经授权的情况下窃听和收集数据。 3.3 设备管理 “普通物联网设备管理包括设备的配置、管理、监控、对故障的诊断以及纠正措施。关键物联网设备管理主要包括设备的注册、配置、关联、软件更新、固件升级以及整体控制管理。”(链接) 随着物联网的加速发展,服务提供商在满足管理要求方面遇到了一些挑战,主要包括以下两个方面: 集中式设备管理的挑战:随着设备规模扩大到一定范围,当前的集中式网络管理会出现明显瓶颈,设备监控、固件升级等的维护成本大幅增加; 事物身份(Identity of Things, IDoT)治理: 物联网设备的所有权和身份关系:设备的所有权在设备的生命周期内,从制造商、供应商、零售商和消费者处发生变化;如果设备被转售、退役或销毁,需要更改或撤销消费者的IoT设备所有权; 物联网设备的属性与关系:设备的属性包括制造商、品牌、序列号等;设备关系还包括设备-人、设备-设备、设备-服务等;如何处理这些复杂的关系也是一种挑战; 设备的访问控制:现有物联网设备访问控制都还是基于PKI体系,依赖于中心化PKI容易受到MITM(Man-In-The-Middle)攻击,CA单点故障也会带来系统加密体系全面崩盘的风险; 异构物联网设备的连通性:物联网范式需要数十亿异构设备的广泛连接,这种异构的连通性对于不同供应商开发的协议和解决方案的交互都是业界难题。 论文[12]对于现有的物联网设备管理平台进行了Benchmark评估测试,并展望未来的物联网设备管理平台。 3.4 规范化与协同操作 物联网标准由多个独立多国治理机构、联盟或组织提供支持(例如 IEEE、ETSI、IETF、W3C、OMG、OneM2M等)。这些标准涵盖了物联网产品与服务从通信技术到架构的多个方面,其中一些遵循中立的跨域方法,二其他一些仅适用于特定的垂直领域。各个标准组织还未形成统一的国际标准,各种设备编码之间相互孤立,有的甚至重复交叉。 要实现信息的互联互通和系统的有效协同,必须建立统一的物联网标识系统。建立统一的物联网标识还需兼容现有设备的异构编码标准。不同供应商设备的异构协同操作问题在2.3节已经提到。 3.5 数据治理 物联网设备产生的巨大数据量,难以在通信/传输、存储方面进行精细的管理。可扩展的基础架构对于处理大量不断增长的数据是有必要的。 数据管理涉及在线数据的聚合,同时提供事件日志、审计和存储,从而进行查询处理和数据分析。且在数据聚合前都应该从应用中抽象出复杂的语义,未经处理的数据面临着非均匀性(non-uniformity)和弱语义。此外许多物联网应用领域对时间要求很高,因此在考虑物联网设备的受限资源能力的同时,及时处理物联网数据也非常重要。 现有的集中式方法确实效率较高,但这些方法不能同时为数据完整性提供保证,并且在处理异构数据方面存在数据孤岛等的信任问题。 三、IoT Meets Blockchain 缘起 物联网的目标是尽可能简化概念,使智能对象通过互联网进行通信,以收集全面的数据并提供个性化的自动化服务,几乎不需要人工干预。为此,目前的物联网平台已经建在集中式模型上,中央服务器或代理提供数据处理,设备协调和授权等服务。 这种方法需要高端服务器,并且这种方法不适用于物与物自主交换数据的场景。 在集中式模型中,集中式服务器授权对象相互通信,因此当越来越多的设备通过Internet相互通信,极大提高了服务器的门槛要求。 在认识到区块链提供的机会及其潜在影响之后,研究人员和开发人员已经开始为物联网设计分布式的解决方案。 区块链的固有特性使其天然地成为开发物联网和分布式云计算的安全分布式结构的首选。 1. Blockchain可以解决IoT什么问题?如何解决? 1.1 支持异构协同操作 目前,物联网设备和协议的异构性限制了它们的协同操作性,并且由于区块链是与语义无关的分布式数据库,因此使用区块链作为物联网的网络控制机制将为其增加更大程度的适应性。 事实证明,区块链可以在异构硬件平台上运行,基于区块链的物联网框架有望适应不同的环境和用例,以满足物联网用户不断增长的需求和需求。 此外,在区块链中可以使用智能合约、跨链等方法将不同厂商、不同协议的设备连接起来,对设备产生的事务交易等消息进行订阅/发布,并结果记录在区块链上[9]。 1.2 安全与隐私保护 在物联网上确保隐私保密下和数据保护,大多数区块链网络都可以使用地址假名简单地保护用户隐私,且其链状结构按时间顺序连续地记录了数据,数据分布地在多个设备上记录,增加了篡改数据的成本,有效抵御DDoS等网络攻击方式。在未来的发展中,基于区块链的去中心化物联网网络消除了用户因为“互相不信任”而通过集中式的实体来处理的需要,从而防止恶意第三方实体收集用户的私人数据。 如何隐私保护? 通过区块链进行的所有交互都是公开可用且可验证的,因此存储在链上和链下的物联网数据通常保持加密,并且在区块链上强制执行授权访问的策略。但是由于区块链网络的可审计性需要通过公开数据访问,这也不符合隐私保护原则。所以,为了保持隐私,区块链技术本身并不充分,需要在可审计和隐私之间寻找有效的平衡。 现有在基于区块链的物联网框架中实现隐私保护的研究,包括利用智能合约执行访问策略的方案[15-16]、分层区块链架构[17]、通过假名地址更新在事务级别上提高区块链的隐私[18-19];以及在密码学上做的改进,例如:将传感器数据通过属性加密保护隐私[20],零知识证明[21]。 如何保证安全? 凭借decentralized public-key infrastructure(DPKI)、可容错设计、可审计以及内在的不受DDoS攻击等多个特性,区块链也可以保证交易网络传输安全的能力。相对于物联网现有的中心化的安全管理方法,区块链带来的技术革新会替代当前的安全方法,并为物联网提供改进的安全解决方案。 现有研究已经有一些方案,用于在不依赖第三方服务的情况下在物联网实施访问控制策略。 针对PKI改进:论文[22]提出了一种基于区块链的PKI方案,相对于中心化的PKI更具有容错性; 针对架构改进:论文[23]提出了一种多层区块链框架,数据存储和数据访问在单独的层中执行:(i).分布式数据存储层,特定地址的用户可以存储物联网数据;(ii).消息层,供存储层和访问控制层进行协商访问;(iii).访问控制层,具有权限的参与者才可以解密密文; 使用Token方法:论文[24]在区块链链中存储加密数据,并使用Token和智能合约策略来允许和撤销对数据的访问。 链下存储方法:论文[25]将数据存储在链下,使用分布式哈希表进行索引,在链上存储不同角色的访问控制权限,从而达到实现访问控制的目的。 1.3 Identity of Things的管理 区块链已被广泛用于身份授权、身份注册、所有权跟踪以及产品、商品和资产的监控。 像TrustChain这样的方法使用区块链来实现可信交易,同时保持分布式环境中的事务的完整性。 物联网设备也不例外。 区块链可用于物联网设备注册并提供身份,具有一组属性和复杂关系,可以上传并存储在区块链分布式分类账中。区块链还在物联网设备的供应链和生命周期的每个环节提供分布式管理、治理和追踪。 具体方案将会在第四章详细说明。 1.4 提高可用性 物联网代表了高可用的收集数据和提供自动功能智能设备。 物联网的网络控制机制需要高可用性,在涉及集中式服务器的体系结构中可能并非总是如此。 区块链的分布式架构,天然地容许部分节点/设备出错或掉线,也可以通过一些分布式共识协议识别故障。 1.5 降低维护成本 实现物联网全球普及的一个重要步骤是找到有效且经济的方法来处理整个物联网中传感器产生的大量数据。集中式云服务因为其计算和存储的价格更低,所以替代了原有集中式服务器的模式。但是数据表明,使用基于区块链的数据存储平台(例如Sia)证明了使用区块链存储数据的成本更低。Amazon S3服务器每个月存储1TB是25美元,Sia每月每TB是2美元。 1.6保证数据完整 物联网应用程序要求传输和分析数据的完整性,因此物联网框架需要对数据泄漏和破坏具有弹性。 区块链网络在节点上存储冗余的副本,这有助于维护数据完整性。 在论文[5]中有张图,可以很全面的展示Blockchain-based IoT的应用。 2. IoT如何部署在Blockchain上? 集中式的云服务在物联网的发展中作出了重要贡献,但在数据透明性方面,集中式云服务就像黑匣子一样,物联网用户无法控制和完全信任他们共享的数据。 物联网可以从区块链提供的分布式网络范例中受益,同时消除对集中式服务的信任需求。 然而,区块链仍处于研究和开发的早期阶段,集成物联网和区块链仍存在多项研究挑战。 物联网中涉及的各种各样的设备,这些设备都是资源限制的,无法托管区块链的整个副本或参与验证区块链的新块,使用区块链在物联网中实现绝对分布式是欠考虑的。 因此,重要的是决定物联网边缘中不同实体(设备,网关等)将扮演什么角色。 物联网边缘设备或网关作为简单的交易发起者(transaction-issuers)并具有可验证的区块链标识,而无需托管整个区块链副本,选取部分设备作为全节点参与共识和区块验证。以下是现研究关于如何集成区块链和物联网的一些方案: 物联网网关设备作为区块链端点: 在这种方案中,所有通信都通过区块链,而IoT网关则作为区块链网络的端点。在这种情况下,IoT设备将注册到网关设备,并且网关向区块链发出交易。这种方法可以跟踪涉及特定物联网网关和物联网服务的所有通信。此集成方案还可用于验证连接到不同网关的设备之间的通信。在这种方法中,并非所有传输的数据都需要存储在区块链中。区块链本身可以用作控制机制,智能合约充当可编程逻辑,而数据传输可以通过P2P技术进行。 设备作为区块链的交易发起者: 这种集成方案出自论文[26],在上述的分析中,我们假设物联网设备实际上没有携带区块链的副本,而只是简单地向区块链发布交易。 与之前的方法类似,因安全考虑,所有IoT交互事件都会记录到区块链中。 在这种方法中,需要为IoT设备提供加密功能。 这种方法物联网设备和应用程序具有更高自治程度,而物联网硬件的计算复杂性增加。 互联的边缘设备作为区块链的端点: 在这种方法中,物联网网关和设备向区块链发布交易,并且可以与另外的链外通信。 这种方法可确保物联网设备之间的低延迟以及在区块链上记录特定交互。 这种集成方案更适合于交互频繁且需要高吞吐量、低延迟、可靠的物联网数据的场景。 基于云的区块链与物联网边缘混合: 这种方法是对先前集成方案的扩展,其中物联网用户可以选择将区块链用于记录某些物联网交互事件,其余事件直接发生在物联网设备之间。 这种方法利用区块链的分散记录保护以及实时物联网通信的优势。该方法的主要问题是如何优化实时发生的交互与通过区块链的交互之间的反应时差。 四、IoT与Blockchain-based ID Management 在物联网中,IDM主要可以包括以下几个部分: 身份验证(authentication); 身份授权(authorization); 访问控制管理; 设备所有权管理; 设备与人、设备与设备的关系管理; 此外,在传统的IDM通信方法里,还是使用基于中心化PKI的方案,如下图所示,用户之间进行通信需要多次轮训,且对中心CA机构极为依赖。 但这种方法由于一些物联网的特性(如可扩展性、协同操作性和移动性)而无法直接移植到物联网环境。这些特性要求对于物联网身份管理系统设计来说很重要。 1. 物联网身份管理系统应该有的特性 可扩展性(Scalability) 物联网技术的愿景是万物互联,当网络物理世界的个数达到一定数量,使用传统的集中式IDM方案,所有物联网标识由一个通用第三方维护以构建高度可扩展的IDM解决方案变得极不现实。现有的联邦式身份管理解决方案(例如,SAML)还是无法绕过信任问题,不能解决在无信任网络中如何建立信任的问题。因此IDM应该在分布式无信任网络中可扩展可信,而无需对任何安全机构进行集中控制。 协同操作性(Interoperability) 根据物体的通信范围、信息处理能力的不同,使用的通信协议也往往不同,如本文第二章所述,通信协议分为很多种,多样性和异构性导致设备之间的协同操作存在问题。设备的身份标识根据不同的标准也全然不同,现在仍然没有一种综合的方案。 可移动性(Mobility) 一些物联网设备有强大的移动能力,可移动性确保用户即使在移动时也能连续地连接服务。无论设备在何处都需要进行身份验证,获得相应的设备服务的授权和访问控制权限。 安全与隐私性(Security & Privacy) 安全与隐私是身份管理系统应该有的最基本特性,具体表现为数据安全、通信安全、隐私保护等。 2. IoT传统身份管理方案 2.1 传统IDM模型 数字身份管理系统负责管理用户的身份信息,由标识符(UserID、电子邮件、URL等),凭证(证书、令牌、生物识别等)和属性(角色、职位、特权等)。下图描绘了传统IDM的示例实例系统,包括三个主要利益相关者:主体(也称为用户),依赖方(也是称为服务提供商)和身份提供商(IdP)。 由此可见,在传统的IDM模型中,身份提供者IdP作为依赖方发挥了核心的作用。这种强依赖关系直接导致了信任问题(在中国不会出现这种情况)。而且,随着提供在线身份服务的服务商增加,用户需要记忆的自己的身份标识变得更多了。 2.2 联邦IDM模型 联邦IDM模型是一种较新的IDM模型,这种模型尝试在各大IdP之间建立信任关系,一个安全域中的用户可以从另一个域访问服务。例如,SAML、OpenID[28]和Shibboleth,允许用户仅使用一个身份登录到多个安全域并授予对属于同一联盟的各种系统的访问权限,即无论在一个域中对哪个身份进行身份验证,同一联盟中的另一个域提供的服务都可以根据其域提供的凭据进行访问。 论文[29]给出了现有传统身份管理方案的比较,如下表所示(节选): 方案 可扩展性 协同操作性 可移动性 安全与隐私性 以用户为中心 FIDIS √ √ √ √ SAML27 √ OpenID[28] √ √ Shibboleth √ STORK √ √ √ PICOS √ √ √ √ √ Cardspace √ √ √ √ 用户必须考虑来自物联网的所有实体,并协调不同安全域的应用加入IDMS,在异构环境中构建可协同操作性系统。但从上表可以看到,大多数的身份管理方案都无法处理可扩展性。虽然OpenID和PICOS等方法可以某种程度上具有可扩展性,但IoT需要更强大的分布式可扩展的底层对上层所有物联网实体的管理支撑。此外,现有的安全与隐私都建立在“用户都信任他们的IdP”的假设上,IdP的安全事故将会导致大批量用户数据泄露(Facebook账号泄露事件),并不能真正消除隐私问题。 总而言之,互联网上的当前身份管理系统已经从孤立模型演变为去中心化的、联邦制的和以用户为中心的身份管理解决方案。通常,一些大型在线服务提供商的IdMS成为其联合域中的通用身份提供商,例如:微信登录、Facebook登录、Google登录等登录方式。不可否认,以用户为中心的联邦式IDMS确实减轻了用户管理身份标识的复杂性。然而,安全性和隐私性尚未得到完美解决,因为用户必须完全信任他们身处中间的身份提供者,这些身份提供者看到每个用户与其在线服务提供商之间的所有活动,“Facebook用户账号泄露事件”就给我们敲响了警钟。因此,消除不必要的第三方并在无信任网络中构建可信身份提供商对于物联网环境至关重要。 3. 现有方案举例 本节先从学术界和工业界对Blockchain-based IDM与物联网的现状进行简单阐述,并提出个人观点;再进行实际举例,举出实际应用结合点,并附上现有方案。 3.1 相关综述 3.1.1 学术界综述 从学术研究的角度来看,基于区块链的IDM系统正在引起很多的关注,为数字身份提出新的解决方案: Hardjono[33]在准入式区块链环境中使用零知识证明引入了一种基于区块链的隐私保护身份解决方案,称为ChainAnchor。在ChainAnchor中,验证节点具有编写或处理事务的权限,而其他节点只能读取和验证事务。所有经过验证的节点都建立在防篡改硬件上,形成隐私保护层,为用户提供隐私保护服务; Lee[34]为物联网设备提出了基于区块链的身份和认证管理系统。 他们提出的解决方案将身份标识的生成和维护放在区块链上,作为一种即时服务,而不考虑通过设备使用区块链的交互或通信。 在这种情况下,基于区块链的身份标识仅用于去中心的身份验证目的; Kravitz[6]提出基于准入式区块链网络的解决方案,由于准入式的区块链网络里的用户可知,参与者之间物联网的接入更可信。此外,该方法利用设备组成员(DGM)机制,将多个设备和用户绑定,并且在执行事务时,在区块链中可以体现出所属成员。 3.1.2 工业界综述 在工业界有很多新兴的创业公司以及企业联盟,意图在区块链与物联网结合的大生态市场上分一杯羹: Trusted IoT Alliance:一个物联网开源软件基金会,其使命是利用区块链技术解决物联网去中心、异构等技术难点。其中不泛有IOTA等的区块链公司,纽约梅隆银行、西门子、思科等合作企业,以及几个物联网企业(区块链公司成员比物联网的还多); IOTA:以Tangle闻名,将基于DAG区块链做大做强的方案。使用独特的方法来验证交易,使其成为物联网所需的大量数据交换的理想选择; slock.it blockpass 综上所述,实际上基于区块链的身份标识产品已经很多,相关学术论文也不少,但是实际上用在物联网领域的还真不多,个人认为主要原因有以下几点: 离不开PKI体系:不使用公钥体系,建起来的城堡就如同沙雕。PKI在物联网中并不能很好适配的主要原因就是其过度中心化的设计,常常容易带来性能瓶颈、单节点故障等问题。现有解决方案DPKI可以有效解决过度中心化的缺点,但其落地为时尚早, 真正的去中心化不切实际; 加密成本太高:物联网设备根据设备不同的职能有不一样的硬件情况,但普遍是资源限制的,运算能力弱,存储能力差,蓄电量低,这样就对安全通信、安全存储带来了一系列的挑战;同时,由于成本的关系,不可能给设备都配备上性能高的硬件条件,所以如何平衡安全和成本是一个主要问题: 再上图可以看到,在通信层使用TLS或轻量级DTLS可以抵抗中间人攻击等通信攻击方式;在针对软件或硬件攻击其密钥,可以使用ARM基于TEE(Trusted Execution Enviroment)/PSA(Platform Security Architecture)进行硬件隔离,存储密钥相关的数据;更深层次的硬件攻击可以使用SE(Secure Element)芯片级的安全保护,但是成本也会大大增加; 不能完全实现去中心化:如今DPKI等对中心化体系替换的方案还未成熟,完全去中心化不切实际,所以现在多是从单中心化转变为多中心化,在企业业务层面进行合作; 3.2 物联网身份管理与属性管理 分布式身份管理与属性管理是分布式经济的基础。在物联网中,设备与人与其他设备的关系,以及其所有权的变更,在不同时间不同地点的访问控制权限,都与分布式身份管理息息相关。如下图所示,是一个基于区块链的分布式身份标识系统的样例。 3.2.1 Securing User Identity and Transactions Symbiotically: IoT Meets Blockchain[6] 论文[6]基于传统PKI与联邦式IDM,提出了一种使用联盟链保护和管理多个物联网设备的分布式身份管理解决方案。该解决方案通过对非对称密钥的重发(rorating key)增加安全性并防止攻击,并提供设备成员DGM机制,可以保证成员内的设备发出Transaction时,区块链内可以认定是从属于哪个DGM发出的Transaction。并且可以调节设备存储量,对存储空间很小的物联网设备很友好。 1). 定义声明 Enrollment Cert:长期存储固有属性,用于证明身份; Transaction Cert(TCert):记录动态的属性,用于区块链交易; Transaction Cert Authority(TCA):颁发TCert; Attribute CA(ACA) Kown Your Machine(KYM) 2). 授权密钥管理 生成TCA CA RootKey与Primary TCA的ID; 生成Primary TCA RootKey: \(TCA\_RootKey_{384bit}=HMAC(TCA\_CARootKey,TCA\_ID)\) ; Primary TCA分发Template TCert给从属TCA,从属TCA负责颁发相应TCert: \(TCertsRoot_{384bit}=HMAC(TCA\_RootKey,''1''||KeyVersion)\) ; 从属TCA实例化TCert,对某个设备/人进行注册,生成Enrollment Cert与TCert,生成TCertOwnerRootKey:\(TCertOwnerRootKey_{384bit}=HMAC(TCertsRoot,EnrollmentPublicKey)\) ; 从属TCA派生出拓展密钥TCertOwnerExpansionKey与加密密钥TCertOwnerEncryptionKey: \(TCertOwnerEncryptionKey\_{256bit}=HMAC(TCertOwnerRootKey,''1'')\ (256bit truncation)\) \(TCertOwnerExpansionKey_{384bit}=HMAC(TCertOwnerRootKey,''2'')\) 生成TCertIndex,ConstantPad代表着在审计中的所属DGM设备: \(EncryptedTCertIndex=AES\_CBC\_Encrypt(TCertOwnerEncryptionKey,TCertIndex||ConstantPad)\) 生成TCert-specific拓展值: \[ \begin{align} TCertSpecificExpansionValu_{384bit}\\ & = \{HMAC(TCertOwnerExpansionKey,TCertIndex)\\ &||HMAC(TCertOwnerExpansionKey,TCertIndex+1)\} \end{align} \] 3). 密钥拓展 TCA可以将TCert的公钥和私钥进行派生,以符合一个群组多个设备的设计(和ID Mixer有区别),而且派生的过程中是与当前属性无关的,这个和面向对象的基类继承派生很相似,可以在继承属性的基础上添加资质证明等属性值,更有利于审计与分析。 \[ \begin{align} TCertPublicKey\\ &=EnrollmentPublicKey+TCertSpecificExpansionValue*G \\ TCertPrivateKey\\ &=(EnrollmentPrivateKey+TCertSpecificExpansionValue)\ (mod\ n) \end{align} \] \(G\) 是ECDSA中的系数。 4). 属性管理 生成TCA CA RootKey与Primary TCA的ID; 生成Primary TCA RootKey: \(TCA\_RootKey_{384bit}=HMAC(TCA\_CARootKey,TCA\_ID)\) ; 生成审计/从属TCA树根节点密钥:\(PreK\_Root=HMAC(TCA\_RootKey,''2''||KeyVersion)\) ; \(K\_TCert=HMAC(PreK\_xyz,TCertID),\ where\ PreK\_xyz=HMAC(PreK\_Root,''xyzx'')\) ; 属性的加密密钥 \(Attribute\_EncryptionKey[i]\) 是由 \(K\_TCert\) 派生而成的,即 : \[ \begin{align} Attribute\_EncryptionKey[i] &=HMAC(K\_TCert,i)\\ Encrypted_Attribute[i] &=AES\_CBC\_Encrypt(Attribute\_EncryptionKey[i],Attribur[i]) \end{align} \] 被认证的属性为 \(Authenticated\_Attribute\) : \[ \begin{align} Attribute\_HMACKey[i]&=HMAC(Attribute\_EncryptionKey[i],i)\\ Authenticated\_Attribute[i]&=HMAC(Attribute\_HMACKey[i],Attribute[i]) \end{align} \] 3.3 物联网密钥管理 在物联网场景中,设备与设备之间通信,更多的是通过多播/广播进行的群组通信可以与整个群组进行直接通信,这种方式更加高效。在物联网中的所有安全问题中,群组密钥管理是保护群组通信的基础之一。群组密钥本质上是由群组的所有成员共享的密钥,以便在使用该组密钥传输之前对所有组通信包进行加密。未授权用户可能由于网络错误或故意拦截而接收群组通信包,但是,如果没有正确的群组密钥,则非法用户无法解密所接收的包。 因为物联网设备资源的限制,现有的IP网络中的群组密钥管理方案不能直接用于物联网中。这意味着每个节点都无法存储大型密钥数据库或进行繁重的加密计算。 在3.3.1节介绍一种基于PUF的物联网密钥管理方法,虽然不是基于区块链的解决方案,但是或许可以从中寻找更加深入的结合点。 3.3.1 Efficient and Secure Group Key Management in IoT using Multistage Interconnected PUF[31] 论文[31]提出了一种基于物理上不可克隆方程(Physically Unclonable Function, PUF)设计的组密钥管理方案:多级互联PUF(Multistage Interconnected PUF, MIPUF),该方法可以在能量资源受限的环境中保护设备进行组通信。这种设计能够安全、高效地执行密钥管理任务:密钥分发、密钥存储和密钥更新。在最后的实验表明,与现有的基于ECC的密钥管理方案相比,可以节省47.33%的电源。 暂且跳过MIPUF的部分,假设作者提出的MIPUF嵌入芯片在计算效果上是正确的、有效的、节能的、安全的。我们主要看它的密钥管理部分。 密钥分发 密钥分发遵循着群组密钥分发协议,请看下图,不再赘述: 密钥存储 在密钥分发之后,当提供正确的配置参数时,可以从MIPUF中提取群组密钥。 与其他基于加密的密钥管理系统不同,这个方法不直接将群组密钥存储在内存中, 而是从密钥提示(hint) \(p_i\) 中提取群组密钥。因为只有当攻击者可以同时访问存储(包含 \(p_i,f_i,c_i^{\gamma_i}\) )和MIPUF(\(\Bbb{F}^{\gamma_i}\)),才能获得真实的群组密钥。 只篡改其中一个不损害整个设计的安全性。此外,群组密钥仅用于接收或发送组消息,因此使用低功率MIPUF存储真实密钥也是高能效的。 密钥更新 只要群组成员进行动态更改,就需要重新生成,重新分发或更新群组密钥。当一个成员离开该组时,它应该无法解密未来的群组通信(forward security); 当一个新成员加入时,它不应该能够解密过去的群组通信(backward security)。 出于安全考虑,在检测到潜在泄漏时,还应完全重新组密钥组密钥。 这里讨论所有三种可能的情况: 新成员加入 假设新的IoT节点\(N_{\alpha}\)意图加入组\(G\),\(N_{\alpha} \notin G\)。在这种情况下,将新密钥重新分配给所有组成员是昂贵且低效的。 因此,控制单元向所有设备 \(\forall N_i \in G\) 发出消息 \(msg^{join}={E_{key_g}(key'_g)}\) 。现有的组成员计算并存储新的密钥提示 \(p'_i=r_i^{\gamma_i}\otimes key'_g\) 并在接收和解密\(msg^{join}\)时删除 \(key'_g\)。 新成员必须完成整个密钥分发过程。 使用此方法可以保留向后安全性,因为新成员没有关于旧组密钥的信息。 成员退出 从组中删除现有成员比添加新成员更复杂。假设将\(G\)群组分成m个子群 \(g_j\subset G =\{g_1,…,g_m\},1\leq j\leq m\) 。同一子群中的所有节点共享相同的配置参数\(\gamma_{g_j}\)。 假设IoT节点 \(N_{\beta}\in g_j \subset G\) 意图离开子群,其中子群中的所有成员使用相同的MIPUF配置参数\(\gamma_j\)。控制节点首先多播/广播m-1包含新密钥的消息\(msg_j^{leave}=\{E_{\gamma_i}(key'_g||H(\gamma_i))\}\) 发送给所有使用配置参数\(\gamma_i,i\neq j,1\leq i\leq m\)加密的子群。收到消息后,每个节点首先使用自己的配置参数 \(\gamma_i\) 对消息进行解密,并检查 \(H(\gamma_i)\) 是否与解密的消息中匹配。如果为正确,那么解密的新群密钥 \(key'_g\) 有效,否则,丢弃该消息。包括离开节点在内的\(g_j\)成员都不知道其他子组的配置参数,因此无法正确解密消息。控制单元应该通过以下方式对\(g_j\)的所有成员进行单播通信。分配新的群组密钥\(key'_g\)和新的配置\(\gamma'_j\)以替换\(\gamma_j\) 。 所有密钥更新 但是,可以通过完全重新映射输入 - 输出映射来重新调整MIPUF以解决建模攻击(modeling attacks)。 一旦生成的CRP总数超过计算的样本复杂度下限,我们建议执行完全更新。该下限等于打破MIPUF的训练集大小。 下面的等式描述了根据IPN模型参数的下限的样本大小,其中\(m\)是MIPUF中的节点的数量,并且\(n\)是MIPUF节点中的PUF的最大数量。 \(k=VC(\Bbb F)\)其中\(VC\)是Vapnik-Chervonenkis维度,\(\Bbb F\)是MIPUF中最大的单个PUF。 \(\delta\)是失败概率,\(\epsilon\) 是学习的错误。 \[ Sample\ complexity = \frac{(m\cdot k+m)\cdot n+lb(\frac{1}{\delta})}{\epsilon} \] 3.4 物联网权限管理 物联网场景比传统的C/S场景更加动态,设备状态、管理权、所有权变化更加频繁。当访问控制查询和更新变得更加频繁时,单个集中式访问控制服务器会存在明显的性能瓶颈。基于区块链技术的分布身份识别,具有可追溯、不可抵赖等特点更加适合物联网的场景。然而现有的方法还处在验证阶段,离不开中心化的PKI是不能从根本上改变现状的。 3.4.1 Blockchain Meets IoT: an Architecture for Scalable Access Management in IoT[32] 论文[31]提出了一种可用于仲裁物联网中的角色和权限的体系结构。该体系结构是基于区块链技术的物联网分布式访问控制系统,这种架构由概念验证实验支持,并在实际的物联网场景中进行了评估。 所提出的方法定义一个Management Hub代表物联网设备从区块链请求访问控制信息,其余所有设备都在区块链网络中具有唯一标识。设备在注册时,必须在管理员的控制下注册,并且一定要注册在一个Management Hub下,注册之后管理员便可以对该设备的访问控制权限进行设定。 在区块链中部署智能合约用于定义访问控制系统中所有的操作。管理者可以和智能合约交互,便于定义系统的访问控制策略。 上图显示了各个部件的交互情况。 3.5 设备生命周期的安全管理 区块链还可以在物联网设备的供应链和生命周期的每个环节提供可信赖的分布式管理,如下图所示,可以记录设备的所有权(ownership)。 在开发商处建立设备的Identity; 在交付时建立所有权(Ownership),分发密钥对; 在部署时对设备参数化,建立访问控制以及配置设备 ; 在维护时,定期重新分发密钥,恢复、升级、重配置; 若存在更改所有权,需要在新的持有者重新分配密钥对、重新部署; 设备报废/退休,需要删除所有权。 4. IDM for IoT的挑战 4.1 访问控制 身份标识和访问控制始终是紧密相连的。在物联网中建立身份系统的目标是实现通信并规范设备和资源的授权过程。尽管基于区块链的访问控制在物联网领域是重要结合点,然而现存的方案中没有很好地解决物联网的访问控制。 传统的访问控制模型访问控制列表(ACLs)和基于角色的访问控制(RAC)模型由于其中心化的设计和扩展性差,早已落入历史洪流;传统方案的共同缺点都是其中心化管理(Admin,IdP等),中心化管理者为设备设定其访问权、角色与属性。因此,这些解决方案不适用于去中心化的可扩展的物联网系统。因此,物联网访问控制的主要挑战可以归结为两点(可扩展性和去中心化): 可扩展性:如何设计有效的访问控制机制,以便于对多种多样的物联网实体(人、物、服务等)的访问权限进行管理,而无需担心用户、角色以及访问策略的快速增长; 去中心化:如果使用区块链技术去除“可信”第三方的IdP,如何在无信任的物联网环境构建访问控制机制? 4.2 隐私保护 基于身份标识的隐私保护也需要从重考虑。如本章第2节中所述,在传统的身份认证中,验证者从服务商或IdP中取得被验证者的信息,在这一步用户的信息往往被多次披露,并且中心化的IdP可以看到服务访问者和提供者之间的交互,存在个人隐私泄露的风险。从用户的角度来看,隐私保护包括两个方面: 来自IdP的身份信息保护; 来自服务提供商的敏感应用数据保护; 在基于区块链的分布式身份标识中,更改了以往的身份验证范式,由用户决定向谁现实敏感信息,而不是托管给IdP。当然,单纯依靠区块链技术还远远不够,还需要额外的隐私保护方案,例如将多方计算(MPC)和零知识证明(ZKP)引入区块链,可实现敏感信息的选择性披露,可实现真正的隐私。但是现今的学术界和工业界都由于方案的复杂性、性能瓶颈等问题,真正落地的不多。 4.3 性能/成本 性能其实与底层区块链的性能有关,能够承受数量众多的物联网设备进行信息交互的底层区块链平台的开发也具有一定的挑战性。其次,成本、安全、性能这三者如何平衡,仍然是产品能不能落地的重要因素,值得研究。 参考文献/链接 What is internet of things (IoT)? - Definition from WhatIs.com Khan M A, Salah K. IoT security: Review, blockchain solutions, and open challenges[J]. Future Generation Computer Systems, 2018, 82: 395-411. M. Conoscenti, A. Vetro, J.C.D. Martin, Blockchain for the Internet of Things: A systematic literature Review, in: The 3rd International Symposium on Internet of Things: Systems, Management, and Security, IOTSMS-2016, 2016. Lo S K, Liu Y, Chia S Y, et al. Analysis of Blockchain Solutions for IoT: A Systematic Literature Review[J]. IEEE Access, 2019, 7: 58822-58835. Fernández-Caramés T M, Fraga-Lamas P. A Review on the Use of Blockchain for the Internet of Things[J]. IEEE Access, 2018, 6: 32979-33001. Kravitz D W, Cooper J. Securing user identity and transactions symbiotically: IoT meets blockchain[C]//2017 Global Internet of Things Summit (GIoTS). IEEE, 2017: 1-6. Internet of Things Protocols and Standards Pongle P, Chavan G. A survey: Attacks on RPL and 6LoWPAN in IoT[C]//2015 International conference on pervasive computing (ICPC). IEEE, 2015: 1-6. Ali M S, Vecchio M, Pincheira M, et al. Applications of blockchains in the Internet of Things: A comprehensive survey[J]. IEEE Communications Surveys & Tutorials, 2018, 21(2): 1676-1717. Gu H, Potkonjak M. Efficient and Secure Group Key Management in IoT using Multistage Interconnected PUF[C]//Proceedings of the International Symposium on Low Power Electronics and Design. ACM, 2018: 8. IoT device management: challenges, solutions, platforms, choices, market and future Biliyaminu U, Hamdan H, Lengyel L, Farkas K. Evaluation of IoT Device Management Tools, in: ACCSE 2018: The Third International Conference on Advances in Computation, Communications and Services, 2018.07.22-26, Barcelona, Spain. Sia combines a peer-to-peer network with blockchain technology to create the world's first decentralized storage platform. P. Otte, M. de Vos, J. Pouwelse, TrustChain: A Sybil-resistant scalable blockchain, Future Gener. Comput. Syst. (2017). http://dx.doi.org/10.1016/j.future.2017.08.048. A. Ouaddah, A. A. Elkalam, and A. A. Ouahman, “Towards a novel privacy-preserving access control model based on blockchain technology in iot,” in Europe and MENA Cooperation Advances in Information and Communication Technologies, 2017, pp. 523–533. A. Kosba, A. Miller, E. Shi, Z. Wen, and C. Papamanthou, “Hawk: The blockchain model of cryptography and privacy-preserving smart contracts,” in IEEE Symposium on Security and Privacy, 2016, pp. 839–858. M. S. Ali, K. Dolui, and F. Antonelli, “Iot data privacy via blockchains and ipfs,” in 7 th International Conference for the Internet of Things, 2017. J. Kang, R. Yu, X. Huang, M. Wu, S. Maharjan, S. Xie, and Y. Zhang, “Blockchain for secure and efficient data sharing in vehicular edge computing and networks,” IEEE Internet of Things Journal, pp. 1–1, 2018. Z. Li, J. Kang, R. Yu, D. Ye, Q. Deng, and Y. Zhang, “Consortium blockchain for secure energy trading in industrial internet of things,” IEEE Transactions on Industrial Informatics, vol. 14, no. 8, pp. 36903700, Aug 2018. Y. Rahulamathavan, R. C.-W. Phan, S. Misra, and M. Rajarajan, “Privacy-preserving blockchain based iot ecosystem using attributebased encryption,” 2017. A. Alcaide, E. Palomar, J. Montero-Castillo, and A. Ribagorda, “Anonymous authentication for privacy-preserving iot target-driven applications,” computers & security, vol. 37, pp. 111–123, 2013. L. Axon and M. Goldsmith, “Pb-pki: a privacy-aware blockchain-based pki,” 2016. S. H. Hashemi, F. Faghri, P. Rausch, and R. H. Campbell, “World of empowered iot users,” in Internet-of-Things Design and Implementation (IoTDI), 2016 IEEE First International Conference on. IEEE, 2016, pp. 13–24. O. Novo, “Blockchain meets iot: an architecture for scalable access management in iot,” IEEE Internet of Things Journal, 2018. H. Shafagh, L. Burkhalter, A. Hithnawi, and S. Duquennoy, “Towards blockchain-based auditable storage and sharing of iot data,” in Proc. of the Cloud Computing Security Workshop, 2017, pp. 45–50. A. Reyna, C. Martín, J. Chen, E. Soler, and M. Díaz, “On blockchain and its integration with iot. challenges and opportunities,” Future Generation Computer Systems, 2018. Security Services Technical Committee of OASIS—Security Assertion Markup Language (SAML) v2.0 Recordon, D.; Reed, D. OpenID 2.0: A Platform for User-centric Identity Management. In Proceedings of the Second ACM Workshop on Digital Identity Management, Alexandria, VA, USA, 3 November 2006. Zhu X, Badr Y. Identity Management Systems for the Internet of Things: A Survey Towards Blockchain Solutions[J]. Sensors, 2018, 18(12): 4215. PICOS—Privacy and Identity Management for Community Services. Gu H, Potkonjak M. Efficient and Secure Group Key Management in IoT using Multistage Interconnected PUF[C]//Proceedings of the International Symposium on Low Power Electronics and Design. ACM, 2018: 8. Novo O. Blockchain meets IoT: An architecture for scalable access management in IoT[J]. IEEE Internet of Things Journal, 2018, 5(2): 1184-1195. Hardjono, T.; Pentland, A. Verifiable Anonymous Identities and Access Control in Permissioned Blockchains. 2016. Available online: http://connection.mit.edu/wp-content/uploads/sites/29/2014/12/ChainAnch or-Identities-04172016.pdf (accessed on 31 August 2018). J.-H. Lee, “Bidaas: blockchain based id as a service,” IEEE Access, vol. 6, pp. 2274–2278, 2018. Trust IoT Alliance The Next Generation of Distributed Ledger Technology | IOTA slock.it connects devices to the blockchain, enabling the economy of things KYC-as-a-Service for Regulated Industries]]></content>
<categories>
<category>物联网</category>
</categories>
<tags>
<tag>blockchain</tag>
<tag>Identity</tag>
<tag>IoT</tag>
<tag>Security</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Hyperledger Indy分析报告]]></title>
<url>%2F2019%2F07%2F16%2FHyperledger-Indy-Research%2F</url>
<content type="text"><![CDATA[Hyperledger Indy提供了一种基于区块链或其他分布式账本的分布式数字身份(DID)方案,这种方案中包含了各种工具、库和可重用工具,以便于这些数字身份可在多个管理域、应用程序以及其他任何数据孤岛上互通。 一、Indy架构综述 从横向看,Indy主要分为项目分布、生态系统架构、数据模型(DID、DID Document、Verified Credentials);从纵向看,Indy主要分为业务层(Business Layer)、应用层(Applications Layer)和技术层(Technology Layer)。 总体架构如下图所示: HBB-Indy-Sovrin ARM v0.27 1. 业务层 image-20190704181446731 业务层主要使用以下几个应用层提供的功能服务:凭证发行(Issue)、凭证存储(Local Store)、数据请求(Request)、凭证披露(Present)、凭证验证(Verify)、凭证撤销(Revocate)用户注册登录等。 2. 应用层 应用层主要功能:提供DID服务、提供凭证服务、提供特定业务服务。 image-20190704181354240 应用层由Indy底下 Indy-Agent 和 Indy-SDK 两个项目支撑。Indy-SDK项目提供钱包功能组件(Wallet Component)支撑数据存储与开发,使用技术层Agent API提供的服务;Indy-Agent项目提供代理功能组件(Agent Component)支撑业务开发。 3. 技术层 image-20190704181540967 技术层也可再分为Cloud Agent层和Ledger层。 Cloud Agent层由Indy-Agent项目、Indy-SDK项目和 DIF Universal-Resolver 项目作支撑,主要功能是提供对Edge Agent的服务,直接与Ledger层进行交互,将请求结果返回到应用层。Indy-SDK项目调用Ledger层的API,实现直接与区块链进行交互;Indy-Agent项目调用Indy-SDK的钱包API,提供代理功能组件,并提供凭证注册组件(Credential Registry Node Component)实现凭证的注册;DIF Universal-Resolver项目提供DID的解析器组件,直接与Ledger层交互,解析出DID。 Ledger层由 Indy-Node 和 Indy-Plenum 两个项目实现,主要功能是实现Indy区块链的功能。Indy-Plenum 项目主要实现的是Plenum BFT共识协议,是Fabric for Identity的定制版,是整个Indy项目的核心部分;Indy-Node是在Indy-Plenum区块链之上的服务器,直接与区块链层进行交互,实现节点功能。 4. 数据模型 DID、DID Document都是按照W3C所定的数据标准建立的,主要关系如下图所示: image-20190704171205582 二、Hyperledger Indy工作流 以一个Alice从Faber大学毕业找工作的场景简单介绍Hyperledger Indy的工作流。(链接) Step 1: 政府生成凭证模板(Schema) img 政府颁发Transcript Schema和Job-Certificate Schema,并将其记录到分布式账本中。每个人都可以访问这些模板。 Step 2: Faber大学和Acme公司生成他们自己的凭证定义(Credential definition) Faber大学和Acme公司根据政府发布的模板创建自己的凭证的定义,并将定义上传到链上。 img img Alice从Faber大学获得成绩单(凭证),然后再申请工作时想Acme公司提供证书作为教育资格证明。 Step 3: Alice从Faber大学获得成绩单凭证 img 具体子步骤如下: Alice与Faber大学建立连接; Faber 大学生成Credential offer给Alice; Alice从分布式账本中查询Faber大学对成绩单的定义,生成Credential request发送给Faber大学; Faber大学生成一个Credential给Alice,这个Credential内含了足够的proof证明凭证的有效性; Alice收到Credential,保存到自己的钱包(wallet)。 Step 4: Acme公司请求Alice的教育证明 img 具体子步骤如下: Acme公司与Alice建立连接; Acme生成proof request发送给Alice,这个请求中包含了应该符合的条件; Alice收到了proof request,基于Credential生成对应的proof,发送给Acme公司; Acme公司收到了proof,并验证其有效性; Acme公司确认了proof。 之后Alice获得了Acme的工作凭证(job-certificate),并将该凭证发送给Thrift银行以证明聘期,便可申请贷款。(Alice使用Faber大学给的教育凭证完成了KYC过程) Step5: Alice获得了Acme公司给的工作证明 img 具体子步骤如下: Acme公司发送Credential Offer给Alice; Alice从分布式账本获取Acme Credential的定义,生成Credential request发送给Acme公司; Acme公司生成Credential发送给Alice,该凭证中包含了足够多的证明以证明Alice的聘期; Alice收到Credential并保存到钱包(wallet)里。 Step 6 : Thrift银行请求Alice的聘期证明,以及Alice 的KYC img 具体子步骤如下: Thrift银行与Alice建立连接; Thrift银行生成两个proof request,发送给Alice;在这里的例子中,银行要求工资大于2000,工作经验大于1年,以及KYC流程; Alice收到两个proof request,基于Faber大学的凭证以及Acme公司的凭证收成两个proof,发送给Thrift银行; Thrift银行收到了证明,并确认其有效性; Thrift银行确认了Alice的proof。 三、关键技术点 Indy整个项目的文件分布如下: 分布式账本 Indy-Node:实现在基于Plenum BFT的分布式账本功能与节点功能,; Indy-Plenum:实现基于Plenum BFT共识机制,定义wallet基类; 客户端工具 Indy-SDK:由两个主要组件构成:libindy(底层),libVCX(实现层); Indy-Agent:项目实现Agent Client,有以下几种功能方向的App: Edge Agent App; Edge Agent Web App; Edge Agent Lightweight App; Cloud Agent Node; Ledger Node; Credential Registry Agent Mode; 通用组件: Indy-Crypto:承用了Hyperledger URSA,作为Indy的密码学代码库; Indy-HIPE(Hyperledger Indy Project Enhancements):实现了Indy的功能增强组件。 接下来将按照项目文件的主体部分进行逐层解析。 1. Indy-Plenum Indy-Plenum.png 从内容上看,Plenum项目主要实现了基于RBFT改进的共识机制以及共识操作方法,定义了四种链分别存储整个Indy的配置、事务等信息,定义了DID的wallet以及DID签名验证方法。项目主要分为以下几个部分: 1.1 plenum包 plenum包实现了基于 RBFT 改进的Plenum BFT共识算法,在Commit阶段手机n-of-l个的BLS签名,在共识Order阶段,对多个BLS签名进行聚合。(注:BLS签名算法在Indy-Crypto中详细说明) Plenum共识改进部分大致在以下三点体现: RBFT每个请求都会发起三段commit,Plenum是一堆请求才发起三段commit; Plenum在PRE-PREPARE和PREPARE阶段都保存了默克尔树根与state树根; 三段commit都是用了BLS多签名聚合方法,客户端不需要其他节点响应。 可以通过这个链接看到Plenum共识协议流程图:Plenum Diagrams 此外,plenum包定义了DID的钱包(wallet)基类,以及DID对消息签名、签名验证的方法。 钱包类主要数据结构如下: name -> str:id名; ids -> Dict[Identifier, IdData]:DID到IdData的映射,一个DID一个IdData; idsToSigners -> Dict[Identifier, Signer]:DID到Signer的映射,一个DID一个Signer; aliasesToIds -> Dict[Alias, Identifier]:(别名)Alias到DID的映射,一个DID对应多个Alias。 钱包类主要方法: Encrypt/Decrypt:均使用 libsodium密码库的python封装进行加解密; sign/verify:签名和签名验证方法都是基于libsodium的sign方法进行的,使用signKey签名,使用veryKey+DID进行验证; DID Create: 指定或产生Seed,32byte; 根据Ed25519算法产生公私钥对 MSK,MPK; 再将产生的私钥作为种子Seed,使用Ed25519,生成新的公钥VerkeyRaw,新的签名私钥signKey; 将verKeyRaw的前16字节进行base58解码,成为DID,后16字节为verKey。 当signKey、verKey丢失时,将可以使用MSK再次重新生成。 Wallet storage:使用 jsonpickle 进行JSON序列化和反序列化,保存在本地。 1.2 ledger包 ledger包定义了整个区块链结构、创世块、Merkle tree结构以及实现了Merkle tree快速验证方法。 1.3 crypto包 crypto包是对Indy-Crypto项目部分功能的封装,主要实现了BLS多重签名。(注:BLS多重签名将在Indy-Crypto项目中详细说明) 1.4 存储组件 img 在Ledger组件中默认使用RocksDB和LevelDB进行KV存储,且使用Merkle Patricia Trie 存储账本状态。每个节点均维护四个账本: Audit Ledger:主要负责与其他三个Ledger同步,为失败节点恢复数据,并对账本正确性进行审计; Pool Ledger:主要维护池中节点的信息(Membership); Domain Ledger:为主要账本,记录交易; Config Ledger:是Pool节点的配置账本。 1.5 底层性能 目前暂未有数据文件表明Plenum的性能指标,还需进一步实际测试。 TODO: 测试Plenum性能指标。 2. Indy-Node Indy-Node.png Indy-Node项目主要实现了基于Plenum BFT共识协议的分布式账本,以及节点的功能。主要包括:处理读写请求、定义交易类型以及交易分类存储。 接下来将按照项目文件的主体部分进行逐层解析。 2.1 indy-node Indy-node包主要实现基于Plenum BFT共识协议的分布式账本、对交易读写请求的处理以及提供了对特定交易的支持,各类交易都会记录到不同种类的Ledger中: 存储到Domain Ledger的交易: NYM:NYM交易主要实现创建新DID、对已存在的DID用户进行角色变更(注:角色变更涉及到权限管理,可查看交易权限管理部分的详情)DID Document就是对NYM交易进行溯源,即可得到一份完整的DID Document; ATTRIB:主要实现对已有NYM添加一个属性; SCHEMA:增加一个声明模板,模板主要包含:属性名、模板名、模板版本号; CLAIM_DEF:对一个声明进行定义,由Issuer创建并公开,若要对一个声明进行升级,需要用新的Issuer DID进行新的声明,主要包含:声明公钥、声明撤销公钥、签名类型(只支持CL签名算法); 存储到Pool Ledger的交易: NODE:在池中添加一个节点,或更新一个池中的节点; 存储到Config Ledger的交易: POOL_UPGRADE:由Trustee发起,升级Pool中的配置,也可更新池中特定的节点设置; NODE_UPGRADE:记录节点升级后的节点状态,由升级的节点发出; POOL_CONFIG:更改池中的配置。 2.2 indy-common indy-common包主要定义了角色权限,以及一些对Indy-Plenum项目方法的封装。 2.3 dev-setup/evironment dev-setup包和evironment包提供了节点部署方案,可以在本机部署(目前只支持Ubuntu、macOS),也可以部署在容器Docker上,可以部署在云端。 2.4 交易权限管理 Indy中节点可分为common user,trust anchor,steward,trustee 四类,每种特殊交易都有特定的角色权限才可以进行。具体可看链接。 3. Indy-SDK Indy-SDK.png Indy-SDK作为Plenum分布式账本的SDK,主要是实现了代理端软件Agent可以与分布式账本、DID钱包以及DID doc进行互通,实现凭证Credential,为不同编程语言封装了主要功能。 3.1 libindy 如上图所示,libindy包主要面向应用提供了基础的区块构建方法,实现了对钱包Wallet、凭证Credential以及DID的操作,且提供不同编程语言调用的封装。并基于SDK提供了命令行工具CLI。 Credential Indy Credential工作流图如下图所示: Issuer生成凭证模板(Create Credential Schema): Issuer创建某个凭证Schema,并将Schema交易发送给Ledger; Issuer生成凭证定义(Create Credential Definition): Issuer想Ledger发送获取某个凭证Schema请求,得到Schema后创建凭证定义,存储公私钥对和正确性证明在本地,将该种凭证定义发送给Ledger; Issuer生成凭证撤销表(Create Revocation Registry): Issuer生成凭证撤销表,并将撤销表入口、撤销表定义发送到Ledger; Prover生成主密钥(Create Master secret): Prover生成主密钥,并保存在本地; Issuer生成凭证提议(Create Credential Offer): Issuer想要发行凭证给Prover,向wallet请求,wallet获取对应的正确性证明,再讲cred_offer消息发送给Prover; Prover请求,Issuer发行凭证(Request and Issue Credential): Prover收到cred_offer消息,向Ledger发送GET_CRED_DEF请求,填写好相应的表单之后生成凭证请求发送给Issuer;Issuer正式发行凭证给Prover,并向Ledger更新凭证撤销表入口;Prover获得凭证后向Ledger验证凭证有效,保存在本地; Prover展示凭证(Show Credential on UI): Prover向wallet请求,wallet返回对应Credential; Prover向Verifier展示凭证(Present Credential to 3rd Party(proof request)): Verifier发起证明请求,Prover给出相应的凭证,并向Ledger核实该凭证的撤消状态,确认之后便将凭证发送给Verifier;Verifier拿到凭证向Ledger核实; Issuer撤销凭证(Revoke Credential): Issuer获取密钥和撤销注册表,并向Ledger同步撤销注册表的入口。 (注:Credential相关密码学部分将会在Indy-Crypto部分详细说明) Command Line Interface CLI组件设计如下图所示: cli-components Wallet Wallet组件设计如下图所示: Wallet Components 在Secrets API,允许调用密钥生成、DID生成等需要访问加密实体的方法;在Non-secrets API只允许访问存取wallet中特定的DID数据。Wallet API提供方法将钱包记录在本地SQL数据库中存取。 Decentrailized Key Management 相关文档并不多,只介绍了当密钥丢失时的措施: 离线物理恢复密钥; 需要trustee级别的用户进行恢复; 考虑到安全性,恢复往往需要与密钥轮换和撤销相结合。 此外,在官方文档中提到了使用Shamir Secret Sharing Scheme是通过分布式密钥碎片存储,在密钥丢失时,只需要将碎片重新整合起来即可恢复。(注:Shamir Secret Sharing Scheme会在Indy-Crypto中简单介绍) 3.2 libvcx libvcx包实现了一种Agent-2-Agent的通信协议,用于credentials的交换。主要还是使用JSON进行通信,通信时使用SSL证书进行加密通信。(注:Credential的选择性披露将在Indy-Crypto中详细说明) 4. Indy-Agent Indy-Agent项目是一个基于Indy-SDK实现的代理客户端的合集,目前已有多种语言的客户端实现。 5. Indy-Crypto Indy-Crypto项目是Hyperledger URSA密码库的一部分,主要在Indy项目使用的密码学方法有: BLS多签算法 , CL群签名算法 。其中,Indy使用BLS多签算法,减少Plenum共识算法的轮训,减少签名长度;Indy使用CL群签名算法对Credential进行选择性披露,实现零知识证明。 5.1 1). 准备阶段 有两个哈希方程 \(H_0: \{ 0, 1 \} ^* \rightarrow \Bbb{G}_2\) , \(H_1: \{ 0, 1 \}^* \rightarrow \Bbb{Z}_q\) $ H_0$是将元素哈希到 \(\Bbb{G}_2\) 群,\(H_1\)是将元素哈希到q阶整数群。 2). 参数生成 \(Pg(k): par \leftarrow (q, \Bbb{G}_1,\Bbb{G}_2, \Bbb{G}_t,e,g_1,g_2) \leftarrow G(k)\) 生成一个双线性配对群,其中q是阶数,$ _1, _2$ 是q阶群,\(e : \Bbb{G}_t \leftarrow \Bbb{G}_1 × \Bbb{G}_2\) 是一种映射关系,\(g_1,g_2\) 分别是 $ _1, _2$ 的生成子。 3). 密钥生成 \(Kg(par) : sk \xleftarrow{random} \Bbb{Z}_q ; pk \leftarrow g_2^{sk}\) 在整数群众随机抽取得出私钥 \(sk\) ,公钥 \(pk\) 由私钥计算得出。 4). 公钥聚合 \(KAg({pk_1,…,pk_n}) : apk \leftarrow \prod_{i=1}^n{pk_i^{H_1(pk_i, \{ pk_1,…,pk_n \} )}}\) 将所有的用户公钥都聚合起来,最终形成一个聚合公钥 \(apk\) 。 5). 签名 \(Sign(par, \{ pk_1,…,pk_n \} ,sk,m) : s_i \leftarrow H_0(m)^{a_i \cdot sk_i} , where\ a_i \leftarrow H_1(pk_i, \{ pk_1,…,pk_n \} )\) 每个用户 \(i\) 对消息 \(m\) 用私钥签名,得出签名 \(s_i\) \(\sigma \leftarrow \prod_{j=1}^n s_j\) 再将签名发给一个节点,节点进行聚合计算,生成聚合签名 \(\sigma\) 6). 验证 \(Vf(par,apk,m, \sigma ) : \ e( \sigma , g_2^{-1}) \cdot e(H_0(m),apk) = 1_{ \Bbb{G}_t}\) 将聚合公钥和聚合签名输入,进行两次双线性配对,若上面的式子成立,则说明验证成功;否则失败。 5.2 1). 准备阶段 有一个哈希方程 \(Hash: \{ 0, 1 \} ^* \rightarrow \Bbb{Z}_q\) \(Hash\) 函数是将元素哈希到q阶整数群。 2). 参数生成 \(Pg(k): par \leftarrow (q,\Bbb{G}, \Bbb{G}_t,e,g) \leftarrow G(k)\) 生成一个双线性配对群,其中q是阶数,$ $ 是q阶群,\(e : \Bbb{G}_t \leftarrow \Bbb{G} × \Bbb{G}\) 是一种映射关系,\(g\) 是 \(\Bbb{G}\) 的生成子。 3). 密钥生成 \(Kg(par) : sk_1,sk_2 \xleftarrow{random} \Bbb{Z}_q ; pk_1 \leftarrow g^{sk_1}; \ pk_2 \leftarrow g^{sk_2}\) 在整数群众随机抽取得出子私钥 \(sk_1,sk_2\) ,子公钥 \(pk_1,pk_2\) 由私钥计算得出。 最终输出私钥: \(SK=(sk_1,sk_2)\) , 公钥: \(PK=(par,pk_1,pk_2)\) 。 4). 签名 输入 \(message\) ,生成消息 \(M \leftarrow Hash(message)\) ,在群 $ $ 随机选取随机数 \(A \in \Bbb{G}\) , 计算 \(B \leftarrow A^{sk_2}, \ C \leftarrow A^{sk_1}B^{sk_1 \cdot M}\) ,最终输出对消息 \(M\) 的签名:$ (A,B,C)$ 。 5). 验证 输入对消息 \(M\) 的签名 $ (A,B,C)$ ,使用公钥 \(PK\) 验证,若 \(e(A,pk_2)=e(B,g)\) 且 \(e(C,g)=e(A,pk_1) \cdot e(B,pk_1)^M\) 则验证成功。 5.3 Anonymous credentials with type-3 revocation 这是Indy项目中Credential(凭证)的整体方案,包括凭证颁发、凭证存储、凭证选择性披露与验证、凭证撤销。 在整个Credential的方案中有三种角色:issuer(凭证发行人)、holder(凭证持有人)、verifier(验证者)。这种方案是基于Camenisch-Lysyanskaya Sign方案改进的,可实现选择性披露、“一次性”凭证的功能。 详情可看这个PDF文档 (建议由密码学功底的人看) 5.4 Shamir Secret Sharing Scheme TODO 四、Hyperledger Aries Hyperledger Aries 是今年5月Hyperledger宣布开源的项目,目前该项目还处于初始阶段,Aires 的产品包括: 用于创建和签名区块链事务的区块链接口层(称为解析器) 安全存储(安全存储技术)用于构建区块链客户机加密信息和其他信息的加密钱包 一种加密的消息传递系统,用于使用多种传输协议在客户端之间进行账外交互 使用 Ursa 中的 ZKP 原语实现支持 ZKP 的 W3C 可验证凭证 一种去中心化密钥管理系统(DKMS)规范 一种基于安全消息传递功能构建的高级协议和类API用例的机制 我个人认为这是Hyperledger Indy项目的一种扩展延伸,实现功能点几乎一样; 但是,Indy是专注于为身份认证而建立的特定区块链,Aries是不适用区块链的项目,项目组期望能在Aries成熟之后融入Indy项目。Hyperledger之后会将Indy项目中与区块链无关的功能迁移到Aries项目,Induy专注于区块链功能。 五、落地案例 主要落地应用是在加拿大British Columbia省的 Verfiable Organizations Network(VON),该项目已开源(链接),目的在于帮助商人建立可信的持续的电子身份验证,从而加速申请政府机构的许可证和执照。 该项目已经在2019年1月推出上线,减少了新供应商或客户进行尽职调查的时间。下一步目标是扩展应用程序,鼓励更多的司法管辖区域使用。 六、推广模式 目前Indy的推广模式相关文章/报道较少(可能也是我菜,找不到/不会找 _(:3」∠)_ ) 以投资者的角度分析了Sovrin项目 (链接) 采访Sovrin主创报道文章,主要讲述了Sovrin是什么,要解决什么问题,怎么解决的,展望未来(链接) 七、Q&A Q:Hyperledger Indy是否支持智能合约? A:Indy专注于数字身份管理,Indy不是为了支持任何资产交换而开发的,而是为了解决与我们当前数字环境的问题。该项目旨在取代我们用来通过分散机制验证用户数字身份的主流机制,例如用户名 - 密码组合,这种机制更安全可靠。由于其独特的使用案例,Indy无法支持任何智能合约。 Q:Authentication是如何进行的?授权的粒度? Indy对DID、Credential以及节点的授权都有不同,详情可见链接。 Q:是否支持多个区块链平台? A:目前Indy项目的底层是Plenum BFT,共识并没有模块化,底层耦合度较高,所以不支持。 Q:用户和机构如何介入? A:详情可见链接1、链接2 Q:区块节点部署方式? A:目前Indy节点支持本地部署(macOS,Ubuntu),容器部署(docker)以及云端部署,都有一键部署工具可用。 参考链接/文献 Hyperledger Indy/Sovrin/DID Comprehensive Architecture Reference Model (INDY ARM) hyperledger/indy-agent hyperledger/indy-sdk decentralized-identity/universal-resolver hyperledger/indy-node hyperledger/indy-plenum Decentralized Identifiers (DIDs) v0.13 hyperledger/indy-crypto hyperledger/indy-hipe Aublin, P.-L & Mokhtar, Sonia & Quéma, Vivien. (2013). RBFT: Redundant byzantine fault tolerance. Proceedings - International Conference on Distributed Computing Systems. 297-306. 10.1109/ICDCS.2013.53. Plenum Diagrams Libsodium document jsonpickle: Python library for serializing any arbitrary object graph into JSON. Merkling in Ethereum Current implemented rules in auth_map Dan Boneh, Manu Drijvers, and Gregory Neven. Compact multi-signatures for 62 smaller blockchains. Cryptology ePrint Archive, 2018. Camenisch J., Lysyanskaya A. (2003) A Signature Scheme with Efficient Protocols. In: Cimato S., Persiano G., Galdi C. (eds) Security in Communication Networks. SCN 2002. Lecture Notes in Computer Science, vol 2576. Springer, Berlin, Heidelberg Hyperledger Aries is infrastructure for blockchain-rooted, peer-to-peer interactions Exploring Hyperledger Indy through indy-dev Example Verifiable Organizations Network: Global digital trust for organizations Verifiable Organizations Network Reducing Government Red Tape: British Columbia Creates New Business Identity Model with Hyperledger Indy Does Hyperledger Indy support any kind of smart contracts? Add Node to Existing Pool Create a Network and Start Nodes Camenisch, J., Kohlweiss, M., Soriente, C.: An Accumulator Based on Bilinear Maps and Efficient Revocation for Anonymous Credentials. In Jarecki, S., Tsudik, G., eds.: Public Key Cryptography. Volume 5443 of Lecture Notes in Computer Science., Springer (2009) 481–500 Anonymous credentials with type-3 revocation. Dmitry Khovratovich, Michael Lodder. 9 February 2018, version 0.4 TokenGazer深度研究:Sovrin,技术落地可期,但推广难度较高 Use case spotlight: The Government of British Columbia uses the Sovrin Network to take strides towards a fully digital economy]]></content>
<categories>
<category>区块链项目</category>
</categories>
<tags>
<tag>blockchain</tag>
<tag>Identity</tag>
<tag>Hyperledger</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Sovrin White Paper Reading]]></title>
<url>%2F2019%2F07%2F12%2FSovrin-White-Paper-Reading%2F</url>
<content type="text"><![CDATA[问题描述 在物质世界,我们使用物理凭证来证明我们的身份(identity)我们可以有驾照来证明我们的驾驶许可、可以有学位证书来证明我们的学历、可以有技能证书来证明我们的能力;但是在互联网上,却没有等同的解决方案来向互联网端的验证者证明自己的能力、资质、拥有权。 这些问题的本质是因为,在整个互联网中没有凭证以及凭证发行验证的标准。The World Wide Web Consortium(W3C)在2017年4月对凭证进行了标准化。但如何对凭证发行方的电子签名的验证进行标准化,还存在着疑问。现有解决方案是采用PKI证书密钥体系,但是这种方案需要多次证书交互,每次进行验证都需要与证书颁发中心进行交互验证证书,且存在中心作恶的风险。 Sovrin给出的解决方案 在区块链上部署decentralized PKI(DPKI)体系结构,每个实体可以进行ID标识,生成Decentralized Identifier(DID),这样每个实体都以同一标准生成一个身份标识,所有人都可以发行电子签名的凭证,所有人都可以验证这些凭证。 image-20190703144357168 Sovrin愿景 全球化的分布式身份识别与可验证凭证方案。这种方案可以用在所有类型的区块链,并且广泛使用程度能超过DNS。 Sovrin隐私保护方案 Pseudonymity by default 成对且唯一的DID和公钥; Private agents by default 任何隐私数据都不会上链; image-20190703161333818 Selective disclosure by default 使用零知识证明的方法,对有选择地披露声明信息,保证隐私安全。 image-20190703161524192 参考文献 Sovrin-Protocol-and-Token-White-Paper1 Decentralized Public Key Infrastructure: A White Paper from Rebooting the Web of Trust W3C: Decentralized Identifiers (DIDs) v0.13]]></content>
<categories>
<category>区块链项目</category>
</categories>
<tags>
<tag>blockchain</tag>
<tag>Identity</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Facebook Libra区块链白皮书研读]]></title>
<url>%2F2019%2F06%2F24%2FLibra-whitepaper-study%2F</url>
<content type="text"><![CDATA[简述 Facebook这次发起的新区块链虚拟货币在技术层面上并未看到有大的革新,与现有的虚拟货币区别不大。从现在的白皮书以及技术文档上所指,最大的特点是币的价值和真实资产储备相挂钩,相对于比特币,波动性较小,价值更平稳,这更像是一种有政府背书的数字货币。 Libra使用了新的编程语言来编写智能合约,设计了基于拜占庭容错的共识算法LibraBFT,如何能承受住全球这么打的用户量,如何,这些问题在技术论文上也没有披露太多信息。 应用背景 现有区块链缺乏可扩展性,加密货币具有波动性,到目前为止,这些因素导致现有的加密货币在保值和交换媒介方面均表现欠佳,因而阻碍了它们在市场上的广泛使用。 一些项目还试图破坏现有体系并绕过监管,而不是在合规和监管方面进行创新,以提高反洗钱举措的效力。 携手金融部门(包括各个行业的监管机构和专家)进行合作和创新,是确保为这一新体系建立可持续、安全和可信的支撑框架的唯一途径。 应用愿景 Libra 的使命是建立一套简单的、无国界的货币和为数十亿人服务的金融基础设施。 Libra 完全由真实资产储备提供支持。对于每个新创建的Libra 加密货币,在 Libra 储备中都有相对应价值的银行存款和短期政府债券,以此建立人们对其内在价值的信任,并以此维持加密货币的价值稳定。 Libra协会成员包括分布在不同地理区域的各种企业、非营利组织、多边组织和学术机构。包含PayPal、Visa等支付业巨头,eBay、Uber、Booking等交易平台。 任何消费者、开发者或公司都可以使用 Libra 网络、在这个网络上构建产品,并通过他们的服务实现增值作用。 技术特色 目标是扩展到数十亿账户,要求具有极高的交易吞吐量和低延迟; 设计和使用全新的Move编程语言,用于智能合约编程; 采用拜占庭容错共识机制,设计使用LibraBFT; 参考链接 [1]. Libra中文白皮书 [2]. Libra技术论文 [3]. Libra开发文档]]></content>
<categories>
<category>区块链项目</category>
</categories>
<tags>
<tag>blockchain</tag>
</tags>
</entry>
<entry>
<title><![CDATA[区块链实验课简易教程]]></title>
<url>%2F2019%2F05%2F29%2Fblockchain-easy-test%2F</url>
<content type="text"><![CDATA[这是一个使用 Python3 + flask 写的简单平台,主要目的是体验区块链的场景。 项目库:https://github.com/dvf/blockchain 一、实验目标 熟悉区块数据结构,了解哈希算法; 简单了解哈希碰撞(挖矿)的流程,并对发起新交易流程有所了解; 熟悉区块链的不可篡改性、顺序性,以及区块链分叉时的场景。 二、实验基础 本实验涉及到以下必要知识点: 掌握Python语言知识点,熟悉Python程序构建方法,了解flask web框架; 熟练使用 *nix系统,熟悉命令行操作(Windows也可); 掌握HTTP协议,熟悉状态返回值的含义; 会使用普通IDE,会使用Postman等工具测试API。 三、实验步骤 1. 实验环境依赖 Git python version >= 3.6 flask == 0.12.2 requests == 2.18.4 Python下载 Git下载 2. 实验环境搭建 PS:在这里的命令行操作主要面向 *nix 系统。 12345678910111213141516# 在适当的目录下拉取库$ git clone https://github.com/dvf/blockchain.git# 检查python版本号 >= 3.6python --version# 下载pipenv$ pip install pipenv# 在当前代码根目录下$ pipenv install# 启动服务器 (默认端口是5000) -p 设定端口号$ pipenv run python blockchain.py# 起多个服务 PS:注意端口冲突$ pipenv run python blockchain.py -p 5001 另:可使用Docker标准环境搭建,可供不希望更改python环境的用户使用。 (注意 这是另外一种实验环境搭建方法,上面做完可不做这一步) Docker桌面工具下载地址:Docker Desktop for Mac and Windows 命令行下载(面向Ubuntu) :Get Docker CE for Ubuntu 1234567891011# 在适当的目录下拉取库$ git clone https://github.com/dvf/blockchain.git# 确保docker服务已经在运行,构建镜像$ docker build -t blockchain .# 起容器,-p 端口映射,外部通过端口80,访问容器内5000端口的服务$ docker run --rm -p 80:5000 blockchain# 起多个容器服务 注意端口$ docker run --rm -p 81:5000 blockchain 3. 与区块链进行交互 实验很简单,使用API工具对服务器发起HTTP请求,也可以使用古老的cURL来替代Postman工具访问API。 Postman Download API总共5中方法: /chain:返回当前区块链表 /mine:进行挖矿,生产一个区块 /transactions/new:产生一笔新交易 /nodes/register:节点注册,将多个节点绑定到一起 /nodes/resolve:区块链同步 1). /chain 方法测试 使用Postman 发送GET方法HTTP请求 shotcut1 12# cURL方式访问$ curl -X GET "http://localhost:5000/chain" 可以看到区块链的结构如下: 123456789101112{ "chain": [ { "index": 1, "previous_hash": "1", "proof": 100, "timestamp": 1558874710.4303942, "transactions": [] } ], "length": 1} 创世块的index为1,transactions内不包含交易。 2). /mine 方法测试 使用Postman 发送GET方法HTTP请求 image-20190526204644640 12# cURL方式访问$ curl -X GET "http://localhost:5000/mine" 可以看到服务器将交易池的所有交易打包产生了一个新的区块index2,并计算了前一块的哈希值。 若交易池内没有交易,系统默认产生sender为0的交易,方便演示 :) 这时,再调用/chain方法,查看返回的记录,有什么变化?测试previous_has是否就是前一块的哈希。 3). /transactions/new方法测试 使用Postman 发送POST方法HTTP请求,这里需要使用JSON格式写入body。 image-20190526204808458 如上图所示,alice向bob发出数量为1的交易。 123456# cURL方式访问$ curl -X POST -H "Content-Type: application/json" -d '{ "sender": "alice", "recipient": "bob", "amount": 1}' "http://localhost:5000/transactions/new" 这笔交易将会发到交易池,等待矿工将它打包到区块里。 这时,再调用/mine方法,查看返回的记录,有什么变化? 4). /nodes/register方法测试 在这里,需要两个以上服务端,即两个以上终端进行操作。 注意:这里分为两种情况,使用pipenv配置的环境,使用Docker配置的环境,请按已有的环境登记节点。 使用pipenv配置的环境 12# 在代码根目录内,重新起一个服务,注意端口要设置成不一样$ pipenv run python blockchain.py -p 5001 使用Postman 发送POST方法的HTTP请求,这里需要填入JSON格式写入body。 注意:这里填入的node是你新起的服务端口,可以有一个,可以有多个 image-20190526204930747 1234# cURL方式访问$ curl -X POST -H "Content-Type: application/json" -d '{ "nodes": ["http://0.0.0.0:5001"]}' "http://localhost:5000/nodes/register" 在 http://0.0.0.0:5001 的服务节点也要用/nodes/register方法把端口5000的服务节点加进去,数据就可以互通。 使用Docker配置的环境 12# 重起一个新的节点$ docker run --rm -p 81:5000 blockchain 在登记节点时,需要知道本机的本地ip(local IP),在这里假设本地IP是196.128.0.1 12345# cURL方式访问# 在80端口登记81端口的服务$ curl -X POST -H "Content-Type: application/json" -d '{ "nodes": ["http://196.128.0.1:81"]}' "http://localhost:80/nodes/register" 同样的,在81端口也需要登记80端口的服务。 5). /nodes/resolve方法测试 在刚才起的新服务节点5001端口(端口号因人而异),调用/chain方法: 123456789101112131415$ curl -X GET "http://localhost:5001/chain"#返回{ "chain": [ { "index": 1, "previous_hash": "1", "proof": 100, "timestamp": 1558874708.5040278, "transactions": [] } ], "length": 1} 可以看到,还是空的,只有1个区块。 这时调用/nodes/resolve方法与登记好节点的区块链进行同步拉取。 例如,5000端口现在的区块链如下: 1234567891011121314151617181920212223242526272829303132333435363738394041424344$ curl -X GET "http://localhost:5000/chain"{ "chain": [ { "index": 1, "previous_hash": "1", "proof": 100, "timestamp": 1558874710.4303942, "transactions": [] }, { "index": 2, "previous_hash": "43417cdaeda03ca51a0959828b681e52a95c0ea77f8544114b1b9f4358dd3bbc", "proof": 5363, "timestamp": 1558874791.834334, "transactions": [ { "amount": 1, "recipient": "2adafd5dd2184a989289f38a02d35a9e", "sender": "0" } ] }, { "index": 3, "previous_hash": "c22e009dd1d09a08b681013b5c0bd8c9f7e798483186562c9ab7f98370c035f2", "proof": 31893, "timestamp": 1558875113.180196, "transactions": [ { "amount": 1, "recipient": "bob", "sender": "alice" }, { "amount": 1, "recipient": "2adafd5dd2184a989289f38a02d35a9e", "sender": "0" } ] } ], "length": 3} 现在调用5001端口的/nodes/resolve方法进行同步: 1234567891011121314151617181920212223242526272829303132333435363738394041424344$ curl -X GET "http://0.0.0.0:5001/nodes/resolve"{ "message": "Our chain was replaced", "new_chain": [ { "index": 1, "previous_hash": "1", "proof": 100, "timestamp": 1558874710.4303942, "transactions": [] }, { "index": 2, "previous_hash": "43417cdaeda03ca51a0959828b681e52a95c0ea77f8544114b1b9f4358dd3bbc", "proof": 5363, "timestamp": 1558874791.834334, "transactions": [ { "amount": 1, "recipient": "2adafd5dd2184a989289f38a02d35a9e", "sender": "0" } ] }, { "index": 3, "previous_hash": "c22e009dd1d09a08b681013b5c0bd8c9f7e798483186562c9ab7f98370c035f2", "proof": 31893, "timestamp": 1558875113.180196, "transactions": [ { "amount": 1, "recipient": "bob", "sender": "alice" }, { "amount": 1, "recipient": "2adafd5dd2184a989289f38a02d35a9e", "sender": "0" } ] } ]} 可以看到,5001端的区块链已经完全和5000端的同步了。 4. 处理区块链分叉 此时,5000和5001两个节点的区块链都是完全一致的。若在5000端和5001端同时进行一次交易,那么会出现什么结果呢?两个节点的链长是一样的,最后是谁同步谁的? 1234567891011121314151617# 在5000端,alice给bob发10块$ curl -X POST -H "Content-Type: application/json" -d '{ "sender": "alice", "recipient": "bob", "amount": 10}' "http://localhost:5000/transactions/new"# 在5001端,bob给alice发10块$ curl -X POST -H "Content-Type: application/json" -d '{ "sender": "bob", "recipient": "alice", "amount": 10}' "http://localhost:5001/transactions/new"# 在两个节点,都生成一个区块$ curl -X GET "http://0.0.0.0:5000/mine"$ curl -X GET "http://0.0.0.0:5001/mine" 此时,在5000端调用/nodes/resolve方法将不会和5001端的同步,反之也是。 当两个节点之中,有一个节点先于另一个节点出块,那么另一个节点将会遵从先出快节点的区块链。Have a try :) 5. 修改哈希碰撞难度 修改哈希碰撞难度,可有效降低出块的时间。 在blockchain.py文件 178行: 12345678910111213141516def valid_proof(last_proof, proof, last_hash): """ Validates the Proof :param last_proof: <int> Previous Proof :param proof: <int> Current Proof :param last_hash: <str> The hash of the Previous Block :return: <bool> True if correct, False if not. """ guess = f'{last_proof}{proof}{last_hash}'.encode() guess_hash = hashlib.sha256(guess).hexdigest() # 在这里修改,0的个数要与数字一致 # 数字越大,0越多,哈希碰撞难度越大 return guess_hash[:4] == "0000"]]></content>
<categories>
<category>记录</category>
</categories>
<tags>
<tag>blockchain</tag>
<tag>Python</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Hexo+GoDaddy+GitHub Pages 构建一个属于自己的博客平台]]></title>
<url>%2F2019%2F05%2F20%2Fhow-i-build-this-website%2F</url>
<content type="text"><![CDATA[关于博客 学习技术总是无底洞,越往深处挖掘,越有挑战也越有乐趣。之前就很想要有个属于自己域名,自己的博客,可以在自己的博客里分享自己学到的、感受的,这也是在这世上孤独的自己的一种乐趣。如今将想法做成现实,希望能多多commit :) GitHub Pages 首先当然是要在Github创建一个repository, 用于存放自己的blog文件. 申请好之后在仓库Settings处往下拉, 到GitHub Pages栏中 snapshot7 选择master branch刷新后, 就会在username.github.io自动生成一个网站, GitHub Pages就已经生成了, 之后我们在GoDaddy里申请好了域名, 再把新域名填入Custom domain就好了. GoDaddy域名申请 在网上的一些GoDaddy申请配置教程稍微有点过时了, 所以在这也说说如何配置. 选择GoDaddy的原因 其实狗爹这里的域名价格并不是最实惠的, 国内的万网之类的也是可以, 但是使用国内域名可能存在备案之类的,感觉麻烦的, 于是.. (申请的时候搜索一下GoDaddy优惠券会有不小的优惠) 申请 snapshot1 查询自己喜欢的域名是否已经被占用, 选好之后添加到购物车. 进入购物车前会推荐你使用它们的隐私服务, No Thanks 就好了. 可使用支付宝, 但不知为啥我这一直用不了支付宝支付, 自动被拒绝了, 所以使用了银联. 第一年只需要14块钱, 也算是很优惠了:) 一般来说 .com .live之类的域名还算便宜, *.cn的比较贵. DNS更换 狗爹这里的DNS不太稳定, 所以建议使用DNSPod进行域名解析. 首先在刚刚购买的域名这进行DNS更换 选择自定义的dns服务器, 填入以下地址: 12f1g1ns1.dnspod.netf1g1ns2.dnspod.net 在DNSPod注册完成后, 在控制台域名解析中添加域名 添加主机记录, 用于解析. 其中ip地址是你申请的GitHub Pages的ip地址, 如果不知道ip的话就ping一下就行了. 完成了之后, 需要一些时间来让DNS迭代, 一般一两个小时以内就行了. 在GitHub Pages使用自己的域名 在Github中创建的仓库设置中Custom domain填入新域名就好了, 建议强制使用HTTPS. 有可能存在一时半会无法解析新域名的情况, 这是DNS还没迭代好, 等一会就好了. Hexo使用 Hexo是一种简单快捷又强大的博客构建工具,可参照Hexo官方文档进行搭建。 依赖 Node.js,version >= 6.9 Git 安装与使用Hexo 在全局安装hexo-cli 1npm install -g hexo-cli 安装成功之后在合适的位置创建Blog文件夹, 用于存放Bolg资源. 12mkdir myBlog && cd myBlog #名字自拟hexo init # hexo 初始化 初始化完成, 自动构建了一个简易Hexo包, 结构如下: 123456789$ tree -L 1.├── _config.yml #配置文件├── node_modules #模块文件夹├── package-lock.json├── package.json #所需模块配置信息├── scaffolds├── source #源码, 资源所在包└── themes #使用的主题包 运行以下命令, 根据你的_config.yml配置, 以及source中的资源自动生成静态文件. 123hexo generate# 以下缩减方式也可hexo g 该命令在文件夹下自动生成了public文件夹, 之后是该文件夹deploy到远程网站(Github)中. 可在本地调试, 查看效果, 默认使用端口4000: 123456hexo server# 以下缩减方式也可hexo s# 终端输出INFO Start processingINFO Hexo is running at http://localhost:4000 . Press Ctrl+C to stop. 在Blog发布一篇新文章"My First Post": 1hexo new "My First Post" 随即在 source/_post 文件夹创建一个My-First-Post.md的Markdown文件, 在上面自由创作就猴啦. _config.yml配置 在这个yml文件中可以配置大部分Blog应有的设置信息, 看懂英文就行, 这里不多赘述. 但是有几个需要提及的. 1vim _config.yml 在最底下的一部分来配置远端Deploy, 在这里建议使用新的分支, 最后再merge到master分支. 123456# Deployment## Docs: https://hexo.io/docs/deployment.htmldeploy: type: git repository: https://github.com/username/repo branch: hexo-dev 完成之后在本地调试hexo g && hexo s后, 即可deploy到Github pages了: 123hexo deploy# 以下缩减也可以hexo d 其余配置详情可以看官方文档的配置(链接) 使用Theme Hexo默认使用的主题是landscape, 还有许多有趣的主题可以使用. 本博客使用的主题是NexT, 如何配置详情就请查看链接内写的吧. 有其他功能部件使用, 就放以后再更吧 <_< 参考链接 Documentation | Hexo Node.js GoDaddy DNSPod NexT]]></content>
<categories>
<category>博客搭建</category>
</categories>
<tags>
<tag>Hexo</tag>
<tag>GitHub</tag>
</tags>
</entry>
<entry>
<title><![CDATA[A lightweight attribute-based encryption scheme for the Internet of Things]]></title>
<url>%2F2019%2F05%2F16%2FA-lightweight-attribute-based-encryption-scheme-for-the-Internet-of-Things%2F</url>
<content type="text"><![CDATA[论文阅读:A lightweight attribute-based encryption scheme for the Internet of Things 文如其名, 比较lightweight, 才9页(笑. 由北京科技大学的博士与中科院博士联手出品. ABSTRACT In this paper, a lightweight no-pairing ABE scheme based on elliptic curve cryptography (ECC) is proposed to address the security and privacy issues in IoT. The security of the proposed scheme is based on the ECDH assumption instead of bilinear Diffie–Hellman assumption, and is proved in the attribute based selective-set model. By uniformly determining the criteria and defining the metrics for measuring the communication overhead and computational overhead, the cMomparison analyses with the existing ABE schemes are made in detail. The results show that the proposed scheme has improved execution efficiency and low communication costs. In addition, the limitations and the improving directions of it are also discussed in detail. We propose a no-pairing ECC-Based ABE scheme to deal with the data security and privacy issues in IoT. Since it replaces the expensive bilinear pairing operation with point scalar multiplication on elliptic curve, it can meet the lightweight requirement and is suitable for IoT. 本文提出了个适用于IoT的ABE解决方案, 因为双线性配对型的ABE很复杂,代价很高,所以采用基于ECC的方法. 同时, 在安全方面采用基于ECDH假设来取代二线Diffie-Hellman假设. 用在椭圆曲线上的点标量乘法代替代价高的双线性配对,可以减少计算开销和通信开销,更适用于IoT设备. ps:Diffie-Hellman密钥交换(csdn和知乎) 预备知识 1.ECC基础 ECC首先是个公钥加密的算法,生成一对公私钥,私钥用来加密,公钥进行解密与验证. 私钥是一个数字(非常大),通常是随机选出来的. 通过椭圆曲线乘法生成一个公钥. 比特币是在公钥的基础上继续进行哈希函数生成比特币地址. 私钥 为了生成私钥,需要挑选一个足够安全的熵源以保证随机性.从编程的角度来看,一般是通过在一个密码学安全的随机源中 去除一长串随机字节,对其进行SHA256哈希算法进行运算,就可以产生一个256位二进制数,一般是以16进制表示. 有如下随机生成的秘药,以十六进制格式表示: 11E99423A4ED27608A15A2616A2B0E9E52CED330AC530EDCC32C8FFC6A526AEDD 比特币私钥空间大小是2256,用十进制表示的话,大约是1077. 目前可见宇宙被估计只含有10^80个原子. 公钥 公钥K是通过使用私钥k进行椭圆曲线乘法运算得到公钥,这个过程不可逆: K=k*G,其中G是生成点的常数点. 逆向求私钥及其困难,只能暴力破解. 椭圆曲线密码学解释 比特币使用的是secp256k1标准的特殊椭圆曲线. 由下述函数定义: 1y^2=(x^3 + 7) over (Fp) or y^2 mod p=(x^3 + 7) mod p 上述mod p(素数p取模)表明该曲线实在素数阶p的有限域内, 也写作Fp, 其中: >p = 2^256 – 2^32 – 2^9 – 2^8 – 2^7 – 2^6 – 2^4 – 1, 这是⼀个⾮常⼤的素数. 上面的素数阶和有限域让我看得头疼,是啥? 带着问题,来到这个博客认真补习了一下离散数学的知识. 这个博客学习ECC的原理. 椭圆曲线普通方程 : \(\large y^2+a_1xy+a_3y=x^3+a_2x^2+a_4x+a_6\) 无穷远点(0,Y,0) 平常点(x,y)斜率k: >\(\Large k=-\frac{F_x(x,y)}{F_y(x,y)}=\frac{3x^2+2a_2x+a_4-a_1y}{2y+a_1x+a_3}\) 椭圆曲线Abel群 : 在椭圆曲线定义了交换群(Abel群) >任意取椭圆曲线上两点P、Q(若P、Q两点重合,则作P点的切线),作直线交于椭圆曲线的另一点R',过R'做y轴的平行线交于R,定义P+Q=R。这样,加法的和也在椭圆曲线上,并同样具备加法的交换律、结合律. 有限域椭圆曲线 : 因为椭圆曲线是连续的,需要将曲线上的点变成离散的点.把椭圆曲线定义在有限域上. 所以椭圆曲线是模p的有限域,记作GF(p)或Fp. 可表示为(P,+,*),其中p是一个质数,P集合表示{0,1,..,p-1}.其中加运算和乘运算都是模运算. 详情可以看这个博客,在这不展开. 椭圆曲线在有限域就表示为 Ep(a,b) ,p是质数, x,y∈[0,p-1] >\(\large y^2=x^3+ax+b\pmod p\) 选择两个满足下列条件的小于p的非负整数a,b >\(\large 4a^3+27b^2\ne0\pmod p\) Fp上的椭圆曲线同样有加法 无穷远点O∞是零元, 有O∞+ O∞= O∞,O∞+P=P P(x,y)的逆元是 (x,-y mod p)= (x,p-y) ,有P+(-P)= O∞ P(x1,y1),Q(x2,y2)的和R(x3,y3) 有如下关系: \(x_3\equiv k^2-x_1-x_2\pmod p\) \(y_3\equiv k(x_1-x_3)-y_1\pmod p\) 若P=Q, 则 \(k=(3x_2+a)/2y_1\pmod p\) 若P≠Q, 则 \(k=(y_2-y_1)/(x_2-y_1)\pmod p\) 举例 :椭圆曲线已知E_23(1,1)上两点P(3,10),Q(9,7),求(1)-P,(2)P+Q,(3) 2P 公式 椭圆曲线加密 : >考虑K=kG ,其中K、G为椭圆曲线Ep(a,b)上的点,n为G的阶(nG=O∞),k为小于n的整数。则给定k和G,根据加法法则,计算K很容易但反过来,给定K和G,求k就非常困难。因为实际使用中的ECC原则上把p取得相当大,n也相当大,要把n个解点逐一算出来列成上表是不可能的。这就是椭圆曲线加密算法的数学依据. > >点G称为基点(base point) > >k(kn)为私有密钥(privte key) > >K为公开密钥(public key) ECC保密通信算法 : Alice选定一条椭圆曲线E,并取椭圆曲线上一点作为基点G 假设选定E29(4,20),基点G(13,23) , 基点G的阶数n=37 Alice选择一个私有密钥k,并生成公开密钥K=kG 比如25, K= kG = 25G = (14,6) Alice将E和点K、G传给Bob Bob收到信息后,将待传输的明文编码到上的一点M(编码方法略),并产生一个随机整数r(r小于n,n为G的阶数) 假设r=6 要加密的信息为3,因为M也要在E29(4,20) 所以M=(3,28) Bob计算点C1=M+rK和C2=rG C1= M+6K= M+625G=M+2G=(3,28)+(27,27)=(6,12) C2=6G=(5,7) Bob将C1、C2传给Alice Alice收到信息后,计算C1-kC2,结果就应该是点M C1-kC2 =(6,12)-25C2 =(6,12)-25*6G =(6,12)-2G =(6,12)-(27,27) =(6,12)+(27,2) =(3,28) 数学原来上能解密是因为:C1-kC2=M+rK-krG=M+rkG-krG=M 论文对ECC进行了剖析. >ECC can provide security based on the known public key cryp-tography primitives, which are Elliptic Curve Digital Signature Al-gorithm (ECDSA), key exchange/agreement (ECDH, Elliptic Curve Diffie–Hellman) and Elliptic Curve Integrated Encryption Standard (ECIES). Compared with other public key cryptography schemes, ECC has 3 distinguished features, which make it very fit for resources-constrained environments [22]. > - It only requires significantly smaller key size than RSA and the modular exponent based public key schemes on the same level of security. > - Its point scalar multiplication operation is much faster than modular exponent operation and bilinear mapping operation. > - It is easy to be implemented in hardware. > > In this paper, we take these advantages of ECC and the features of ABE to construct an ABE scheme for IoT, where Elliptic Curve Decisional Diffie–Hellman Problem (ECDDHP) serves as the complexity assumption, and the Elliptic Curve Integrated Encryption Standard (ECIES) is adopted to encrypt the data. ECC提供的安全性基于ECDSA,ECDH,ECIES.与其他的公钥加密算法,ECC有如下几个非常适用于资源节约型的环境的特性. 相对于RSA,可以用较小量级的密钥大小提供与RSA相同等级的安全性. 标量乘法运算比模指数运算和双线性映射快得多. 在硬件上更容易实现. 本文基于这些ECC的功能,来构建在IoT上的ABE方案. ECDDH 来作复杂度假设, ECIES 对数据加密. ECDDH ECDH 是一种在椭圆曲线上的Diffie-Hellman的密钥交换协议. 可以帮助具有椭圆曲线公私钥对的双方通过不安全的通道生成 共享密钥. 这个共享密钥可以直接当成密钥或者派生出新的密钥来加密接下来通讯内容. >例如, Alice与Bob使用同一套ECC系统(q,a,b,G,p) > > Alice的密钥对是(S_A , P_A=S_A*G). Bob的密钥对(S_B , P_B=S_B*G) > >那么他们的共享密码K_{A,B}就是: K_{A,B}=S_A* P_B=S_B* P_A=S_A* S_B* G ECDDH(elliptic curve decisional Diffie–Hellman problem) 是ECDH的重要变体. >对于具有生成元G的q阶椭圆曲线群G_E, DHH表明, 给定c*G和d*G的条件下,c*d*G是G_E中的随机元素. > (其中,c,d都是在q阶整数上随机取的.) > >也就是说,对于给定的三元组(c·G,d·G,c·d·G)和(c·G,d·G,Z),无法判断Z = c·d·G ECIES ECIES椭圆曲线集成加密方案,包含有密钥交换和公钥加密的部分. 使用ECDH生成共享密钥,数据的机密性由对称加密算法保证,密钥和数据完整性由MAC密钥的功能保证. 以下是ECIES的加密与解密步骤: Access structure 访问结构用于描述访问策略,可用访问树表示,由如下定义: >(Access Structure [11]). Let \(\{A_1, A_2,..., A_n\}\) be a set of attributes. A collection \(\mathbb{A}\) = \(2^\{A_1,A_2,...,A_n\}\) is monotone, for \(\forall B,C\): if \(B\in \mathbb{A}\) and \(B\subseteq C\), then \(C ∈ \mathbb{A}\). An access structure (respectively, monotone) is a collection (respectively, monotone) \(\mathbb{A}\) of non-empty subsets of \(\{A_1,A_2,..,A_n\}\), i.e.,\(\mathbb{A}⊆\)\(2^{A_1,A_2,..,A_n}\setminus \emptyset\). The sets in A are called the authorized attributes sets, and the sets not in A are called the unauthorized attributes sets. 有那么一组属性组 \(\{A_1, A_2,..., A_n\}\), 设有一二元集合 \(\mathbb{A}\) = \(2^\{A_1,A_2,...,A_n\}\), 如果对与任意的B与C,有B属于A,且B是C的子集,得到 C也属于A.那么二元集合A是单调的. 所以访问结构是属性集合 \(\{A_1, A_2,..., A_n\}\) 的非空子集 \(\mathbb{A}\) ,集合 \(\mathbb{A}\) 称为授权集. 访问树 的具体定义与原理 在这篇文章有详细提及, 在这不详细说. 算法实现细节 该算法是用KP-ABE的结构, 涵括了AA(attribute authority). 由四个算法步骤组成: Setup: 在中心节点生成public key parameters,PK和master key,MK. master key作为私钥在中心节点所用, public key parameters向外公开. Encrypt: 由发送者执行,将消息M输入,中心节点的PK加密输入(确定中心节点),设定属性集r,输出密文CM. key-Generation:由中心节点执行,将访问结构R和中心节点MK输入,根据R输出解密钥匙D. Decrypt: 由接收者执行,输入发送者发送的密文CM,中心节点给的解密钥匙D,中心节点的PK,当R(r)=1时, 可以得出解密后的消息M. 本文的给出的KP-ABE算法 本文所给出的轻量级的ABE是基于ECC的,假定ECC的参数是(q,a,b,G,p). 对于属性集w, 密钥是由基于拉格朗日插值法的secret sharing构建的. 且该方法有一个ECC-based的密钥生成中心. (拉格朗日插值法学习链接) Setup:首先是定义中心节点的属性集U,对U中每个属性\(i\), 在ECC的q阶正整数群内随机找一个对应的数字 \(s_i\),每个属性\(i\)的公钥就是\(P_i=s_i\cdot G\). 同样地,在q阶正整数群内随机找一个数字\(s\)作为中心节点的MK,中心节点的PK就等于 \(PK=s \cdot G\), 所以中心节点的公开参数可以表示为: \(Params=\{ PK,P_1,..,P_\left | U \right|\}\) Encryption(M,w,Params): 与现存的ABE不同的是, 消息M是由ECIES加密的,而不是模指数运算或者双线性配对加密的. 随机从ECC的q阶正整数群选择k来计算C',\(C'=k \cdot PK=(K_x,K_y)\),若C'为0则重选k. 分别对Params中\(P_i\)计算\(C_i\), \(C_i=k \cdot P_i, i \in w\). \(K_x\)为加密密钥,\(K_y\)则是整合的密钥. \(C=ENC(M,K_x)\), \(MAC_M=HMAC(M,K_y)\) 密文cipher-text就可以表示为\(CM=(w,C,MAC_M,C_i,i\in w)\). KeyGeneration(\(\Gamma,MK\)): 当且仅当 \(\Gamma (w)=1\)时,通过算法生成解密的密钥. 对访问控制树 \(\Gamma\)上的每个节点u都自上而下进行定义,这些节点的门限都是\(d_u\). 多项式\(q_u(x)\)由此定义 对于访问树 \(\Gamma\)的根R,设\(q_R(0)=s\) (ps: s就是setup步骤的MK) 并随机选择\(d_R-1\)个其他点做多项式\(q_R(x)\) 对于其他节点u, \(q_u(0)=q_{parent(u)}(index(u))\),也要随机选择\(d_u-1\)个其他点来定义\(q_u(x)\) 当访问树的叶子节点都被定义了之后,叶子节点u的secret share解密密钥就可以表示为: \(\large D_u=q_u(0)/s_i\),其中\(i\)是一个属性,\(s_i\)在setup步骤上就已经定义,\(s_i^-1\)是\(s_i\)在ECC群中的逆元.根据这样的访问树结构就能逐步还原. 最终解密密钥可以表示为: \(D=(D_u=q_u(0)/s_i, i=attr(u)\ and\ \ i\in w)\). Decryption(CM,D,Params):与其他算法相似,在访问树里的节点的解密算法用递归的方法实现. 对每个叶子节点u, 令 \(i=attr(u)\) 有: $ DecryptNode(CM,D,u)=$ \begin{cases} D_u C_i=q_u(0) s_i^-1kP_i\ =q_u(0) s_i^-1ks_iG\ =q_u(0) kG , &(iw)\ , &Otherwise. \end{cases} 对非叶子节点,可以对每个子节点v调用\(DecryptNode(CM,D,v)\). 令\(w_u\)为u的\(d_u\)个子节点的集合, 对每一个\(w_u\)的元素v进行\(DecryptNode(CM,D,v)\). 若存在\(w_u\),那么有: > 对根节点有: \(DecryptNode(CM, D, R) = q_R(0)·k·G = s·k·G = (K′_x, K′_y)\). 其中\(K'_x\)就是消息M的解密密钥,\(K'_y\)是消息M的集合密钥.\(M'=DEC(C,K'_X)\). 如果\(HMAC(M',K'_y)=MAC_M\),那么就表示消息M已经被正确解密. 所以说所有的正确性,完整性都由\(MAC_M\)验证. 算法表现与分析 本文为了评估所提出的ABE方案的轻量级的特点,在 通信开销 和 KP-ABE和CP-ABE的 加算开销 上分析. 并给出该算法的限制. 通信开销指标 通信开销取决于所传输的消息的长度. 传输的消息包括了 密文cipher-text ,公钥 和 私钥. 现有大多数ABE方案都是基于双线性配对的RSA-based方案. 有两个群\(G_1,G_2\), \(G_1\)是一个大素数阶的双线性群, 双线性映射可以表示为 \(G_1 \times G_1 \rightarrow G_2\). 且\(G_1,G_2\) 的基本运算都是模指数运算. 在相同安全级别上,RSA的密钥对比ECC的密钥对长得多.RSA的密钥对长度在 \(G_1\) 是ECC的3.2倍,\(G_2\) 是6.4倍. 在ABE方案中,密文需要包含属性集, 密文的长度与属性集成线性增长. 密文 \(CM=(w,C,MAC_M,C_i,i\in w)\) ,\(C_i\)是椭圆曲线的一点,且长度为\(2l\),由于先前的假设,消息M和MAC的长度都为安全级别\(l\),所以\(C\)和\(MAC_M\)也是\(l\)位长. 所以给出的方案的密文长度是 \((l+l+k*2l)=(2k+2)l\). 另外,公钥是 \(\{PK,P_i,i\in U\}\),每一个元素都是椭圆曲线上的一点,所以公钥长度为 \((2l+n*2l)=(2n+2)l\). 私钥是 \(\{D_u=q_u(0)/s_i,\ i=attr(u)\mbox{ and }i\in w\}\), 长度是\(k\cdot l\). 计算开销指标 本文对比了现有的CP-ABE和KP-ABE. 计算开销一般是由双线性映射(公钥的加密解密操作)的成本衡量的.本方案中没涉及,所以不计算.本文的加密算法包括了(1+k)点标量乘法,且解密的递归过程不超过(2k-1)点标量乘法,所以总的最多有3k个点标量乘法. 与其他的方案的比较如下图: 可以看出在 公私钥长度 都远比其他方案要短, 密文长度 在属性大于10个时大于常数级的方案. 计算开销 也明显小于一般方案. 所以说在 轻量级 的属性加密方案上,该文的方案是很优秀的. 提出的ABE方案的限制 撤销属性灵活性较差: 使用的是单调访问结构和秘密共享机制,都是在"AND"和"OR"门上进行的,不支持"NOT"门, 难以表达复杂的访问策略,属性撤销也很麻烦.通常操作都是重新加密来实现属性撤销. 本文并没有讨论属性撤销属性. 可扩展性差: 通信开销和计算开销都与加密属性数量成线性关系. 通用性较差: 本方案是单一权限上的应用,不适用于多权限结构. 参考文章 Yao X, Tian Y, Tian Y. A lightweight attribute-based encryption scheme for the Internet of Things[J]. Future Generation Computer Systems, 2015, 49(C):104-112. Bitcoin加密技术之椭圆曲线密码学 谈谈有限域那些事儿 离散对数和椭圆曲线加密原理 ECC入门+实例 (身份证比特币加密算法) 数学、英语对程序员来说重要吗?记线性秘密分享方案(Linear Secret Sharing Scheme,LSSS)的实现 [如何直观地理解拉格朗日插值法? @马同学的回答]6 密码学中的离散数学知识学习]]></content>
<categories>
<category>密码学</category>
</categories>
<tags>
<tag>ECC</tag>
<tag>属性加密</tag>
</tags>
</entry>
</search>