CryptoNight 文档
概要
CryptoNote Standards 介绍了一种点对点的匿名支付系统本文档是 CryptoNote Standards 的一部分定义了 CryptoNote 的缺省工作量证明散列函数CryptoNight。
版权及授权说明
版权所有c2013 CryptoNote。 本文档可在知识共享署名3.0许可证国际许可权限范围内查询。
许可副本 http://creativecommons.org/licenses/by/3.0/
目录
- 算法介绍
- 名词解释
- 初始化流程
- 内存处理流程
- 结果计算流程
1.算法介绍
CryptoNight是一个使用物理内存的高强度hash算法函数。 它的设计适用于GPUFPGA和ASIC架构上的有效性算力。流程的第一步是初始化大型暂存器与伪随机数据下一步是算法对暂存器中包含伪随机地址的大量的读/写计算操作最后一步是将整个暂存器的hash值进行hash效验验证本次计算产生的价值。
2. 算法定义
hash函数映射数据的有效计算函数对于固定大小的数据、构造特定算法行为产生类似随机数结果
暂存器在算法过程中申请用于存储计算时中间值的部分内存
3. 初始化流程
首先使用参数 b = 1600
和 c = 512
.对输入内容进行Keccak计算 [ KECCAK ]。计算结果的0..31字节用作AES-256密钥[AES]并扩展为10个循环密钥申请一个分配了2097152字节2 MB空间的暂存器从计算结果的64..191字节处提取出来数据并分割成8个块每个块16字节。使用以下步骤对每个块进行加密
for i = 0..9 do:
block = aes_round(block, round_keys[i])
aes_round()
函数执行一轮AES加密对本块执行 SubBytes
ShiftRows
和 MixColumns
步骤其结果与round_key进行异或运算。但这不同于AES加密算法第一轮计算和最后一轮计算没什么不同。
一轮下来得到的计算结果写入暂存器的前128个字节然后这些结果再次代入加密循环再把这次循环结果写入暂存器的第二个128字节里。这里每次往暂存器里写入下一个128字节都代表对先前写入的128字节内容在新一轮加密的结果。流程一直循环直到暂存器写满。至此一次算法的初始化就完成了。
该图表示暂存器初始化
+-----+
|Input|
+-----+
|
V
+--------+
| Keccak |
+--------+
|
V
+-------------------------------------------------------------+
| Final state |
+-------------+--------------+---------------+----------------+
| Bytes 0..31 | Bytes 32..63 | Bytes 64..191 | Bytes 192..199 |
+-------------+--------------+---------------+----------------+
| |
V |
+-------------+ V
| Round key 0 |------------+---+->+-----+
+-------------+ | | | |
| . | | | | |
| . | | | | AES |
| . | | | | |
+-------------+ | | | |
| Round key 9 |----------+-|-+-|->+-----+ +---+
+-------------+ | | | | | | |
| | | | +------------------->| |
| | | | | | |
| | | | V | |
| | | +->+-----+ | |
| | | | | | S |
| | | | | | |
| | | | AES | | c |
| | | | | | |
| | | | | | r |
| | +--->+-----+ | |
| | | | a |
| | +------------------->| |
| | . | t |
| | . | |
| | . | c |
| | +------------------->| |
| | | | h |
| | V | |
| +----->+-----+ | p |
| | | | |
| | | | a |
| | AES | | |
| | | | d |
| | | | |
+------->+-----+ | |
| | |
+------------------->| |
| |
+---+
4. 内存处理流程
在主循环之前对输入内容进行Keccak计算后取0..31字节和32..63字节进行异或所得到的32字节结果用于初始化变量a和b分别各占16字节这两个变量将用于主循环主循环进行524,288次迭代当一个16字节值需要转换成暂存器中的一个地址将以低字节顺序压入内存21位低字节用作索引但是索引中的4个低字节将被清除以确保地址索引统一16字节对齐。 数据从16字节块中读取并写入暂存器。
迭代流程伪代码
scratchpad_address = to_scratchpad_address(a)
scratchpad[scratchpad_address] = aes_round(scratchpad [scratchpad_address], a)
b, scratchpad[scratchpad_address] = scratchpad[scratchpad_address],
b xor scratchpad[scratchpad_address]
scratchpad_address = to_scratchpad_address(b)
a = 8byte_add(a, 8byte_mul(b, scratchpad[scratchpad_address]))
a, scratchpad[scratchpad_address] = a xor scratchpad[scratchpad_address], a
8byte_add()
函数将每个参数表示为一对64位低位值并将它们组合在一起以分量形式进行快速模除 2 ^ 64。 其结果返回16字节。
8byte_mul()
函数仅使用每个参数的前8个字节并分别解析为无符号64位低位字节整数并相乘。 其结果返回16字节最后结果分半两边的8字节相互交换。
内存处理流程图
+-------------------------------------------------------------+
| Final state |
+-------------+--------------+---------------+----------------+
| Bytes 0..31 | Bytes 32..63 | Bytes 64..191 | Bytes 192..199 |
+-------------+--------------+---------------+----------------+
| |
| +-----+ |
+-->| XOR |<--+
+-----+
| |
+----+ +----+
| |
V V
+---+ +---+
| a | | b |
+---+ +---+
| |
--------------------- REPEAT 524288 TIMES ---------------------
| | address +---+
+-------------|----------------------------------->| |
| +-----+ | read | |
+-->| AES |<--|------------------------------------| |
| +-----+ V | |
| | +-----+ | S |
| +-->| XOR | | |
| | +-----+ write | c |
| | | +------------------------------>| |
| | +----+ address | r |
| +------------------------------------------>| |
| | +-----------+ read | a |
| +->| 8byte_mul |<--+------------------------| |
| | +-----------+ | | t |
| | | | | |
| | V | | c |
| | +-----------+ | | |
+------|->| 8byte_add | | | h |
| +-----------+ | | |
| | | write | p |
| +---------|----------------------->| |
| | | | a |
| V | | |
| +-----+ | | d |
| | XOR |<-----+ | |
| +-----+ | |
+------+ | | |
+-------------|-+ | |
| | +---+
-------------------------- END REPEAT -------------------------
| |
5. 结果计算流程
在内存操作完成之后使用与第一步骤初始化步骤分相同的方式进行Keccak计算最终结果的32..63字节被扩展成10个AES循环密钥。
从Keccak结果里提取64..191字节并与暂存器里前128个字节进行异或运算。然后结果以与第一步初始化步骤使用相同的方式进行加密但是使用新的密钥。结果继续与暂存器中的第二个128个字节进行异或运算依次循环加密迭代。
在暂存器的最后128个字节进行异或运算后就是流程的最后一次加密完成后将原本Keccak结果的64..191字节内容替换为本次加密内容。然后以b = 1600对整个块内容进行Keccak-fKeccak排列。
然后结果中第一个字节的2个低位比特用于进行散列函数运算0 = BLAKE-256 [BLAKE]1 = Groestl-256 [GROESTL]2 = JH-256 [JH] 3 = Skein-256 [SKEIN]
。最后将所选的散列函数应用于Keccak最终结果生成的散列就是CryptoNight算法的计算输出。
结果计算流程图
+-------------------------------------------------------------+
| Final state |
+-------------+--------------+---------------+----------------+
| Bytes 0..31 | Bytes 32..63 | Bytes 64..191 | Bytes 192..199 |
+-------------+--------------+---------------+----------------+
| | | |
| +--------+ | |
| V | | |
|+-------------+ | | |
|| Round key 0 |-|---+---+ | |
|+-------------+ | | | | |
|| . | | | | | |
|| . | | | | | |
|| . | | | | | |
|+-------------+ | | | | |
+---+ || Round key 9 |-|-+-|-+ | V |
| | |+-------------+ | | | | | +-----+ |
| |-|----------------|-|-|-|-|->| XOR | |
| | | | | | | | +-----+ |
| S | | | | | | | | |
| | | | | | | | V |
| c | | | | | | +->+-----+ |
| | | | | | | | | |
| r | | | | | | | | |
| | | | | | | | AES | |
| a | | | | | | | | |
| | | | | | | | | |
| t | | | | | +--->+-----+ |
| | | | | | | |
| c | | | | | V |
| | | | | | +-----+ |
| h |-|----------------|-|-|----->| XOR | |
| | | | | | +-----+ |
| p | | | | | | |
| | | | | | . |
| a | | | | | . |
| | | | | | . |
| d | | | | | | |
| | | | | | V |
| | | | | | +-----+ |
| |-|----------------|-|-|----->| XOR | |
| | | | | | +-----+ |
+---+ | | | | | |
| | | | V |
| | | +----->+-----+ |
| | | | | |
| | | | | |
| | | | AES | |
| | | | | |
| | | | | |
| | +------->+-----+ |
| | | |
V V V V
+-------------+--------------+---------------+----------------+
| Bytes 0..31 | Bytes 32..63 | Bytes 64..191 | Bytes 192..199 |
+-------------+--------------+---------------+----------------+
| Modified state |
+-------------------------------------------------------------+
|
V
+----------+
| Keccak-f |
+----------+
| |
+-----------+ |
| |
V V
+-------------+ +-------------+
| Select hash |->| Chosen hash |
+-------------+ +-------------+
|
V
+--------------+
| Final result |
+--------------+
计算结果举例
Empty string:
eb14e8a833fac6fe9a43b57b336789c46ffe93f2868452240720607b14387e11.
"This is a test":
a084f01d1437a09c6985401b60d43554ae105802c5f5d8a9b3253649c0be6605.