《精通门罗币》第5章-深入探究门罗币与密码学

发布时间:2019-07-03 16:49:59 来源:宝运莱-宝运莱下载-宝运莱官网点击:4

  在计算机问世之前,数学和密码学就已经是通信与信息交换的核心学科。密码学最早可以追溯到罗马共和国时期恺撒使用的简单密码(一种广为人知的替换加密技术,后世称之为恺撒密码)。

  现代密码学则开始于世界大战时期,用于重要机密信息加密处理。最开始投入研究密码学的都是各国政府与军队,以保护国家机密为主要研究方向。

  现在,密码学已不再局限于间谍和军事活动中使用,而是互联网时代通信和安全的支柱,世界各地的学术与行业研究人员都在对密码学进行广泛与深入的研究。

  作为现代十分普及的幕后工具,密码学在保密、管理、通信等很多连接层面上改善着我们日常生活。例如:Secure Socket Laye(安全套接层,简称 SSL,一种网络安全协议,不推荐使用 TSL)采用了数据加密签名技术。医院、银行、政府和企业均采用密码学技术保护用户数据。

  在本章,我们将主要讨论:加密工具如何应用一个去中心化金融数据库生产出加密数字货币(重点介绍门罗币)。

  1. 数学基础

  以下先简要介绍/回顾密码学的几个核心数学原理。

  1.1 欧几里德除法(A/B)

  将任意一个数 A 除以另一个数 B(写为 A/B 或 A÷B)会得到一个结果,该结果既可写为商与余数,也可单独写为小数。

  通常:

  

  A/B=q,余数为 r

  例:

  12/4=3,余数为 0,可写为小数 3.0

  13/4=3,余数为 1,可写为小数 3.25

  27/5=5,余数为 2,可写为小数 5.4

  1.2 质数

  质数是只能被“1”和自身整除的整数,例如:

  20 不是质数,因为可以被 2、4、5 和 10 整除,得到整数,

  例:20 ÷ 4=5 或 20 ÷ 10=2

  7 是质数,因为除了 1 和自身外,除以任何整数均不会得到整数,

  例:7 ÷ 3=2.3333

  其他例子:

  质数包括 3,5,7,11,13,97,223,

  997,3413,4421,17837,145601,

  428567,1171967,甚至更大的数字像

  2074722246773485207821695222107

  6085874809964747211172927529925

  8991219668475054965831008441673

  2550077 或者孪生质数

  2,996,863,034,895×2^1,290,000±1,

  每个质数均超过 350,000 位!

  1.3 模算术

  模算术描述的是会绕过特定整数的数字。

  一个直观的示例为 12 小时制。如果在晚上 11 点以后熬夜 5 个小时,那么,你不会经历下午 16 点!因为在午夜,时间会转而绕到零点(因此晚上 11 点过去 5 个小时后,是第二天早上 4 点)。

  给定任意两个正数,A(被除数)和 B(除数),

  模数 B=A/B 的余数 r

  就时钟而言,晚上 11 点后熬夜 5 小时可表示为:

  (晚上 11 点 + 5 小时)mod 12=…

  =16:00 mod 12

  =4:00(早上)

  1.4 整数表示

  整数可用许多不同的编码表示,其中一些在计算机科学中经常遇到。

  大多数人都非常熟悉 base-10“十进制”数制,该数制用 10 个字符表示数字:0,1,2,3,4,5,6,7,8,9。

  对于一个 base-16 集合,“十六进制”编码额外增加了 6 个字符:0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f。

  以十进制写为 11719682 的整数可以用十六进制表示为 B2D402。请注意,较大的字符集通常需要较少的位数(较短的字符串)来表示相同的数字。

  计算机以 base-2“思考”时,只使用字符“0”和“1”。这称为二进制,例如数字11719682(base-10)可表示为

  101100101101010000000010。

  门罗币以 base-58 打印最终地址和密钥,其中使用阿拉伯数字和大多数拉丁字符集(大写和小写)。base-58 类似于另一个 Base64 方式,但其已经修改,以避免数字和字母在打印时混淆不清。门罗币使用这种格式,目的完全在于方便人们使用,因其经常须人工阅读或转录长地址。

  base-58 字母表包括:

  123456789ABCDEFGHJKLMNPQRSTU-

  VWXYZabcdefghijkmnopqrstuvwxyz

  注:该 Base58 字母表不包括零(0)、字母 I(i 的大写)、字母 O(o 的大写)和字母 l(L 的小写),因其彼此间易混淆不清。

  1.5 椭圆曲线

  1.5.1 概述

  

  椭圆曲线被定义为满足以下等式的一组二维(x,y)点:

  

  例如,在固定系数 a=2 和 b=3 的情况下,该等式变为

  这由许多对点来满足,例如:

  x=3 和 y=6

  x=3 和 y=-6

  x=-1 和 y=0

  1.5.2 Ed25519 扭曲爱德华兹曲线

  门罗币使用特殊的扭曲爱德华兹(Twisted Edwards)椭圆曲线 Ed25519 进行加密操作,该曲线是蒙哥马利曲线 Curve25519 的二元等效物。

  ed25519 曲线可以代数形式表示为

  -x2+y2=1-(121665/121666)x2y2.

  回想我们的一般椭圆曲线等式,该扭曲爱德华兹曲线是一个使用以下参数的特例:

  a=-1 和 b=121665/121666

  近期发现,NIST(National Institute of Standards and Technology 的简写,意为:美国国家标准技术研究所)支持的 PRNG(Pseudo-random Number Generator Algorithm 的简写,意为:伪随机数发生器算法)明显带有缺陷,含有潜在的后门。由于 NIST4 标准算法最近出现一些问题,因此密码界的许多问题选择采用扭曲爱德华兹曲线来解决。

  从更广泛的角度来看,NSA(National Security Agency 的简称,意为:美国国家安全局)也在暗中支持 NIST 选择的曲线。鉴于之前 NSA 利用其对 NIST 的权威削弱由后者所提出的算法一事,密码和密码货币界对这些背书持怀疑态度。

  扭曲爱德华兹曲线 Ed25519 不受任何专利的限制,其背后团队已开发和调整了基本加密算法,并考虑到了算法效率。据认为,该曲线目前是安全的。

  1.5.3 椭圆操作

  椭圆曲线点加法和标量乘法是椭圆曲线密码方案的基本运算。在深入研究门罗币的计算机制之前,我们应对这些概念有一个基本了解。

  椭圆曲线点加法不同于日常算术中遇到的典型加法。如需将椭圆曲线上的两点相加,则须找到这两点之间的直线,然后找到曲线与该直线的交点。然后,沿 x 轴映射该点直至到达最终点。

  向自身添加点(所谓的点加倍)时,必须找到起点切线,以到达该切线与曲线的交点。然后,沿 x 轴映射该点直至到达最终点。

  标量乘法利用曲线上的一个点和一个整数。如需将一个点 P 乘以一个整数 S,则将该点以 S 次添加至其自身。许多加密方案(例如门罗币使用的方案)使用椭圆曲线上的公共基点作为生成器点,从私钥生成公钥。

  当曲线生成器点被多次添加至曲线自身时,所得点不能用于确定操作发生的次数。该问题通常称为椭圆曲线离散对数问题。这种标量乘法被认为是单向函数,因其反转运算非常困难。

  2 密码学基础

  由于具有面向隐私的独特加密特性,门罗币成为一种领先的安全的且不可追踪的加密数字货币,这一点我们会在本章中进行更深入地探讨。由于密码学的数学本质,书中列有更多关于密码学的技术性章节。更加复杂的技术建立在被称为加密原语的简单原理之上。

  加密原语是一种算法,用作加密协议的构建模块。门罗币为各种用途使用了不同的加密原语,我们在第 3 章和第 4 章中会从概念上讨论其中部分内容。门罗币对隐私和(ASIC 抗性)工作证明的有意方法需要比许多其他加密数字货币使用更复杂的加密工具。

  2.1 对称和非对称密码学

  对于加密数据,根据所使用的密钥类型,可将其算法描述为对称或非对称。

  对称加密要求参与者共享一个秘密,例如,你用密码 “hunter2” 加密信息,而接收人用密码 “hunter2” 解密信息。如需以该方式交流,双方必须事先就共享(对称)秘密达成一致。这个实际问题限制了对称加密在许多应用中的利用。

  不对称加密允许双方在不共享特定秘密的情况下安全交互。这种类型的密码学已深植在互联网安全、端到端通讯工具和加密数字货币的框架中。

  比特币使用两个密钥的不对称加密:

  ? 私钥 - 用于签署交易和解密数据

  ? 公钥 - 用于签名验证和加密数据

  门罗币密码框架更复杂,其需要有四个密钥:

  ? 查看公钥 - 用于验证地址的有效性

  ? 查看私钥 - 用于查看余额、费用和交易金额等数据(查看密钥无法创建或签署交易)

  ? 支付公钥 - 交易验证的另一个公钥

  ? 支付私钥 - 用于签署交易,即发送门罗币

  这对公钥可直接表示为你的公共门罗币地址,而比特币(和复制体)使用其单个公钥的散列。EdDSA 密钥(私有和公开)长 256 位,或有 64 个十六进制字符。并非每个 256 位整数均为有效的 EdDSA 标量(私钥);其必须小于 Ed25519 函数部分等式中描述的“曲线顺序”。

  2.2 散列

  第 4 章讨论了散列的概念及其使用范围,从确认数据保真度到在工作证明中分配奖励。散列示例显示于第 4 章末尾的密码学部分。

  选择一个良好散列算法对于以安全方式生成地址和密钥至关重要。如果两个不同的输入产生相同的散列输出,则称其为冲突。散列凭借其有效唯一性在区块链系统中通常被用作标识符。此外,种子生成过程中的冲突会导致多个个人拥有相同的密钥和地址;显然,这会出现严重问题!

  门罗币使用 CryptoNight PoW 系统,该系统采用一种建立在 Keccak 散列基础上的特殊 CryptoNote 散列算法。Keccak 算法赢得 NIST 竞赛,被指定命名为 SHA3,由非 NSA 工程师设计。门罗币对交易和区块散列均使用 32 字节输出的 Keccak-256 散列函数。

  2.3 门罗币伪随机数生成(PRNG)

  当用户和计算机创建新的密钥时,找到别人无法猜到的新密钥是至关重要的一点。这实际上是一项非常困难的任务,因为硬件和软件通常均为支持再现性而设计。如果计算机以可预测的方式产生随机性,则输出可能在表面上为随机性,但更容易猜测。

  例如,考虑到一个 PRNG,其简单地将当前时间的数字洗牌,生成一个4位数密钥。因此,在“10:34”时,它可能会输出“0413”或“1403”或“0134”……

  如果想对输出密钥保密,则这会是一个糟糕的方法,原因如下:

  ? 当攻击者知晓你在中午 12:45 左右开始工作时使用了密钥时,便会知晓数字“1”和“2”会出现,从而将选择范围缩小到明显更少的选项。

  ? 一天中不会出现三个“9”的 HH:MM 时间。事实上,不会出现从 中所选任何三个数字的时间,因为 17:89、18:78 等都是不可能出现的时间。这个规则消除了许多 4 位数的密码,让攻击者从更小的范围中进行猜测。

  上述基于时钟的随机数生成器非常糟糕,因为使用一天中的时间作为初始种子是可预测的。最初的种子对于攻击者而言应该更难猜测。良好随机数生成器会引入大量熵,使其输出不可预测。简单地移动4位数不会引入太多熵,这也是上述 PRNG 不安全的另一个原因。

  生成钱包时,用户的操作系统提供初始种子/熵源。然后,门罗币反复应用 Keccak 散列函数,以导致不可预测和不可复制的输出。每轮散列产生一个输出,用作下一轮散列的输入。

  3. 生成门罗币密钥和地址

  3.1 挑选种子

  在第 2 章中,我们谈及钱包的核心:也就是种子。你的钱包生成了这个秘密,用来派生你所有的密钥,以及存取/支出你的资金。在概述中,我们简单地考虑了25个单词的种子助记词。

  在幕后,种子是一个唯一的 256 位整数,从中派生密钥和地址,例如:

  112699108505435943726051051450940377552177626778909564691673845134467691053980

  这些数字通常表示为 64 位的 base-16 数字,例如:

  f9296f587419f1cdede67de160fca14d1069ecaa4c52f012af031eeA09ee039c

  (对于助记词类型密钥,种子的这种表示实际上就是支付私钥本身!)

  写下上述任何一种密钥类型都是相当困难的一件事,大多数人都容易犯至少一个错误。转换成种子助记短语是另一个步骤,只是对于人们来说有可解释性和可用性。助记短语本质上将上述 256 位数字转换为 24 位(24 个单词)base-1626“数字”(因为种子字典中有 1626 个单词)。这种长种子字符串的表示法更易于阅读:

  lamb hexagon aces acquire twang bluntly argue when unafraid awning academy nail threaten sailor palace selfish cadets click sickness juggled border thumbs remedy ridges border

  羔羊 六边形 王牌 获得 鼻声 迟钝 争论 何时 无惧 遮阳篷 学院 钉子 威胁 水手 宫殿 自私 学员 点击 疾病 歪曲 边界 拇指 补救 山脊 边界

  当你的钱包显示 24 单词种子时,便会添加第 25 个单词作为校验和,以便以后可检测到打字错误或差错。门罗币的助记词法编码的比例最小为 4:3。换言之,四个字节创建三个单词,加上一个校验和单词;八个字节创建六个单词,加上一个校验和单词;依此类推。

  查看私钥是通过 Keccak-256 散列种子派生,产生第二个 256 位整数,然后将其发送到称为 sc_reduce32 的函数,以确保它与椭圆曲线兼容。通过这种方法创建的种子始终是有效的标量,因为它们首先被发送至 sc_reduce32 函数。

  3.2 密钥派生

  3.2.1 所有密钥

  上述门罗币种子实际上是支付密钥,所有其他密钥均从该密钥派生而来。查看私钥是支付私钥的简化散列,转换为ed25519曲线的有效标量。

  这两个私钥乘以生成器点,得到钱包的两个公钥(支付公钥和查看公钥)。这种派生密钥的方法称为确定性方法。

  3.2.2 仅查看钱包

  你可通过使用查看私钥(而非支付私钥)设置钱包来授予对门罗币帐户的仅查看权限。这些仅查看的钱包可查看所有收入交易,但不能支付门罗币或查看支出交易。

  有几种情况下,在没有发送访问权限时检查收入交易非常有用。例如,拥有冷钱包的人可使用查看密钥来检查资金是否到达,同时将他们的支付密钥安全地封存起来。同样,开发人员可构建能够检测和响应收入支付的系统,而无需具有转移这些资金的能力。

  这项功能对慈善机构尤其有价值,因为慈善机构可分享自己的查看密钥,以确保捐赠的透明度和责任感。如果向公共地址捐款,则可使用查看密钥来验证慈善机构是否收到资金。

  例如,考虑主要门罗币捐赠地址:

  44AFFq5kSiGBoZ4NMDwYtN18obc8AemS33DBLWs3H7otXft3XjrpDt QGv7SqSsaBYBb98uNbr2VBBEt7f2wfn3RVGQBEP3A.

  由于混淆地址会阻止公共地址在区块链受记录或搜索,因此社区还会发布查看密钥(f359631075708155cc3d92a32b75a7d02a5dcf27756707b47a2b31b21c389501),以便公众可查看捐赠活动。

  由于任何持有查看密钥的人均可看到钱包收到的总金额,因此被授予 100 XMR 的透明慈善机构不能挪用 90 XMR 并声称他们只收到 10 XMR。对于必须达到特定捐赠门槛的众筹情况,此功能尤其有用。

  无法从仅查看钱包中查看支出交易是一个特性,而非错误!如果支出交易公开,则其将揭示何时花费输出。这存在严重问题,因为环签名依赖于支出状态的模糊性。假设一个慈善机构揭示了何时花费了输出资金;所有未来(和先前)环签名中的表现均可受识别为诱饵。因此,不公开支出交易对于维护整体网络隐私的完整性而言是必要因素。

  3.3 地址生成

  门罗币钱包的标准地址由上一节中派生的两个公钥(支付公钥+查看公钥)组成。其还包含一个校验和和网络字节,用于标识网络和地址类型。

  3.3.1 网络字节

  网络字节用于区分各种加密货币和网络。

  例如,CryptoNote 类型的币在文件 src/CryptoNote_config.h 中指定适当的值,例如:

  uint64_t const CRYPTONOTE_PUBLIC_

  ADDRESS_BASE58_ PREFIX=18;

  门罗币的主网络使用“18”来表示主地址(这便是门罗币的主地址以“4”开头的原因,这是 ASCII 表示)。

  门罗币开发人员使用有自己独特网络字节的测试网(用于开发者)和阶段网(用于用户体验):

  

  3.3.2 级联公钥

  支付公钥和查看私钥被连接并附加到网络字节,以产生原始地址(除校验和之外的所有内容)。尽管该地址仍然是原始格式,但其包含所有密钥信息:用于创建交易的密钥和网络元数据,以确保交易得以传达至正确的网络。

  3.3.3 校验和

  由于门罗币交易不可逆,因此将付款发送至正确的地址至关重要!为帮助避免打字错误和小错误,地址包括校验和。如果发送人输入错误或没有捕获整个地址,则校验和将不匹配,表明输入的字符串并非有效地址。

  该校验和是由 Keccak 对上一节中收集的地址信息进行散列处理而生成。哈希摘要被缩短为前 4 个字节,并用作校验和。

  3.3.4 将所有此类信息结合起来:地址最终确定

  最后,根据门罗币规范连接网络字节、密钥和校验和:

  

  最后,该 69 字节的输出字符串受编码成门罗币 base-58 格式。这种转换会将长度增加到 95 个字符串,便于读写。全部过程便是如此!门罗币主地址仅包含:

  [网络字节+支付公钥+查看公钥+校验和]标准地址示例:

  4BKjy1uVRTPiz4pHyaXXawb82XpzLiowSDd8rEQJGqvN6AD6kWosLQ6VJXW9sghopxXgQSh1RTd54JdvvCRsXiF41xvfeW5

  以下伪代码描述了生成公共地址的过程,使用 Hs() 表示 Keccak 散列,使用“||”表示字符串连接。

  Checksum=Hs(Varint(Prefix) || public spend key|| public view key)

  SerializedString=Base58(Prefix || public spend key || public view key || checksum)

  第 7 章包含实际的 Python 代码,用于自身生成密钥和地址!

  3.4 子地址

  门罗币交易的隐私通过三个主要构建实现:环签名、混淆(一次性)地址和 RingCT。这些减轻了交易因与那些可以被分析的区块链数据链接的风险。然而,必须考虑“链外”链接风险(即,从除区块链数据本身之外的其他来源收集的信息)。

  例如,假设主地址收到几个不同个人的付款。由于门罗币的混淆地址技术,你的公共地址从未在交易中得到明确记录,因此无人可通过分析区块链(包括消费者)来链接这些交易。但是,如果两个发送人互相通信,并发现他们都将门罗币发送至同一个地址,则这种加密隐私便完全被规避了!

  你可通过生成多个子地址、与每个发送人共享一个唯一的子地址来避免这种风险。该子地址与你的主地址来自相同的密钥,因此收到的任何子地址的资金都将归集至相同的总钱包余额。然而,不同的子地址在加密上不可链接,因此多个发送门罗币到同一个钱包的人,也无法通过比较他们的地址列表来识别这一点。

  3.4.1 创建子地址

  回想一下,每个钱包都有两对密钥。查看私钥(pV?)和支付私钥(pS?)受保密,而查看公钥(PV?)和支付公钥(PS?)被编码至每个地址中。如前所述,公钥是通过将私钥乘以椭圆曲线上的生成器点(G)生成,即 (PV?, PS?)=(pV?, pS?)G。

  你的钱包可创建大量子地址,每个子地址都有不同的索引 “i”(通常从 i=1 开始)。每个子地址在每个索引处均有自己的密钥集,含有唯一的私钥 (pV?, pS?) 和公钥 (PV?, PS?)。

  为第i个子地址创建支付公钥的公式是:PS?=Hs(pV? || i)G+PS?

  这个过程从连接索引“i”到主地址查看私钥(pV?)开始,并通过 hash_to_scalar 函数传递该结果(注:在实践中,引用客户端钱包也将字符串子地址连接到数据,作为散列的常用盐)。所得标量乘以曲线生成器点,并通过椭圆曲线点加法添加到主要支付公钥。

  该子地址支付公钥乘以主要支付私钥,得到子地址查看公钥:PV?=pV?*PS?

  子地址公钥按照与主地址相同的惯例被编码至公共地址中:

  Subaddress_i=base58(network byte || PS? || PV? || checksum)

  然而,子地址主网的网络字节为 0x42,这便是其均以数字“8”开头的原因。

  3.4.2 发送至子地址

  这种识别第一个网络位的不同方法是至关重要的一点,因为交易到子地址的构建必须与正常情况略有不同。

  构建交易时,钱包通常会生成 32 个随机字节作为私钥。当发送到主地址时,该随机密钥通过椭圆曲线标量乘法与椭圆曲线生成器点相乘,以产生交易公钥。但是,当发送到子地址时,交易私钥反而会乘以接收子地址的支付公钥。

  3.4.3 接收到子地址

  由于门罗币区块链的模糊性质,钱包必须扫描每笔交易,以确定其是否属于所有者。为确定给定的输出 X(带有支付公钥 R)是否被发送至主地址,钱包根据其查看公钥和支付公钥检查计算。如果等式 X==Hs(pV?*R)G+PS? 为真,则可解锁和花费输出!

  然而,检查哪些输出属于子地址的过程略有不同。除了从输出中减去 hash_to_scalar 项并与子地址支付公钥进行比较之外,计算基本相同。如果等式 PS?==X - Hs(pV?*R)G 为真,则钱包知道它建立在自己的输出上。

  3.5 密钥派生的其他方法

  更令人困惑的是,目前在门罗币中使用的至少有三种不同的私钥派生方法(比特币也是如此)。这些方法在几种“密钥”方面有所不同:

  ? 原始(非确定性类型):支付私钥和查看私钥均独立和随机选择,以形成一个帐户。除了保留每个文件的副本之外,并无好的方法来备份不确定的帐户。由于有更好的选择,因此不再推荐这种笨拙方法。

  ? 助记词(确定性或“Electrum”)类型:在这种类型中,所有的密钥均是从一个单独的支付私钥中派生而来,该支付私钥被称为种子。查看私钥是通过用 Keccack-256 散列支付私钥以产生有效的 EdDSA 标量而派生。这些帐户是很容易备份的,因为你只需要写下种子(通常用 base-1626 助记短语表示)。

  ? MyMonero 类型:MyMonero 钱包系列使用类似于 Electrum 惯例的方法,但是种子短语是 13 个单词,而非通常的 25 个单词。这 13 个单词转换为 128 位整数,用于支出和查看密钥派生。用 Keccak-256 对种子整数进行散列,并转换为支付私钥。用 Keccak-256 对该支付私钥再次进行散列,并转换成查看私钥。

  你可能已注意到 MyMonero 类型和 Electrum 种子类型之间的一个重要区别。MyMonero 通过散列一个随机整数来创建查看私钥,而 Electrum 类型散列支付私钥。这意味着 13 单词和 25 单词的种子并不兼容——不可能创建一个与 MyMonero 类型帐户相匹配的 Electrum 类型帐户(反之亦然),因为查看密钥对总是不同。

  4. 隐私技术

  4.1 混淆地址

  第 3 章从概念上描述了一次性地址(也称为混淆地址)如何允许交易在不暴露接收人真实地址的情况下发布到网络上。本节将更深入地解释一次性公钥背后的加密技术。

  4.1.1 发送

  CryptoNote 协议根据公式 X=Hs(r*PV|i)G+PS 计算接收一次性地址。让我们逐步了解这些符号的含义,以及 Maria 向 George 付钱时会如何生成一个一次性地址。

  变量 r 是交易私钥,这是一个 256 位的伪随机标量。Maria(发送人)是唯一知道该密钥的人;甚至 George(接收人)也从来不知 Maria 钱包里选的 r 的随机数。

  Maria 然后将 George 的查看公钥 PV 乘以 r,然后附加输出索引 i。该量 (r*PV|i) 随后通过 hash_to_scalar 函数 Hs() 运行。该函数使用 Keccak-256 算法对其输入进行散列,然后将得到的散列结果对质数进行取模

  2^255+27742317777372353535851937790883648493。

  将上段中计得的 Hs(r*PV|i) 项乘以 ed25519 基点 G。最后,Maria 将该量加到 George 的支付公钥 PS 中,以产生最终输出 X,即混淆地址。

  这一错综复杂的过程使得 Maria 能够使用一个随机生成的一次性地址向区块链的 George 进行隐秘交易,但无人能够与他联系。

  4.1.2 接收

  鉴于 Maria 将发送给 George 的门罗币隐藏得那么好(受 George 不知的交易私钥所掩蔽),你可能想了解 George 如何能在区块链找到它!

  如第 3 章所述,George 必须扫描区块链,寻找属于他的输出。这个过程与 Maria 用来生成地址的方法非常相似。

  George 从区块链获得交易公钥 R,并将 R 乘以他的查看私钥 pV。按照与 Maria 相似的步骤,George 附加输出索引 i,然后将 hash_to_scalar 函数应用于 (pV*R|i)。然后,他将结果乘以 G,并加上自己的支付公钥 PS。如果该值与输出匹配,则其属于他。

  换言之,George 的钱包扫描了区块链的每一笔交易,以确定 X=Hs(pV*R|i)G+PS 的输出。

  4.2 环机密交易

  环机密交易(RingCT)模糊了交易中发送的门罗币的数量。RingCT 于 2017 年 1 月实施,并于 2017 年 9 月之后成为所有交易的强制性规定。

  只有创造新门罗币作为 coinbase 奖励的交易才具有可见的数量,且不会受 RingCT 所掩蔽。这是一个审计功能,允许任何网络参与者计数并验证已生成多少门罗币。在币公开释放之后,这些交易在进一步使用之前被转换成 RingCT。

  所有非 coinbase 交易均使用 RingCT 加密交易金额。每笔交易的金额以两种不同的方式加密,这两种方式均包含在消息中。

  首先,该金额由从接收人地址中的公共信息导出的密钥加密。该版本记录在 ecdhInfo 字段中,只能由接收人使用交易共享秘密解密和读取。

  其次,该金额被纳入佩德森承诺,如此可允许其他门罗币用户自己验证交易的有效性。无人可从佩德森承诺中检索交易金额,但是任何人均可检查结果,以数学方式验证输出与输入是否平衡。如此防止任何试图伪造门罗币的交易。

  RingCT 的验证有两个关键方面:

  发送人使用范围证明,可验证性证明所有输出均包含正数。范围证明表明,掩蔽数可被生成为 2 的正幂之和,而不会揭示这些幂是什么。如果没有范围证明,则一个拥有 5 XMR 的恶意的用户可用一对包含 +13 XMR 和 -8 XMR 的输出创建一个交易。

  发送人还能证明输入与输出平衡,这是十分厉害的技能,因为环签名包含诱饵,以防止验证方知悉输入资金的真正来源!同态的佩德森承诺使发送人能够证明其中一个潜在的输入与输出之间的差异为零,而不会揭示过程中的数量。

  为进行简单的类比,请考虑以下等式示例。类似掩蔽交易金额,你可验证每个等式是否有效,而无需知道 A 值。

  A=我们的输出,无人知晓

  5A+1A+4A=10A 真!已验证,不知晓A

  6A+4A+2A=14A 假!未通过验证,拒绝!

  4.3 环签名

  门罗币利用环签名技术来保护每个交易发送人的隐私。环签名是一种加密签名,允许一个有效参与者代表一个组对消息进行签名。有效签名者拥有的私钥与来自其他成员的公钥信息混合,以产生单个签名。任何人均可对照公钥验证签名的消息,以验证某个环成员发起了签名,但是无法确定哪个成员贡献了私钥。

  在门罗币背景下,消息是由环签名授权的交易。实际支出的输出是真正的签名者,来自其他输出(来自过去的交易)的公钥受混合作为诱饵签名者。实际签名者和诱饵签名者在数学上同等有效;不可用密码检查得到的环签名来确定哪个成员主动发起了签名。因此,任何外部方(包括接收人)均无法确定交易中引用的输出中的哪一项被实际支出了。

  每个环签名产生一个单一密钥镜像,该图像是从实际支出的输出中派生而来。这是一个加密安全的过程:每个输出对应一个密钥镜像,且生成密钥镜像并不能揭示环中真正的签名者。

  当输出的所有者在新的交易中支出该输出时,网络将存储由环签名产生的密钥镜像。由于网络无法识别哪些输出被支出了,反而会跟踪那些被支出的密钥镜像!如果所有者试图欺诈性地再次支出该输出(双花),则将会产生相同的密钥镜像,因此网络会拒绝交易。

  让我们深入研究生成环签名的实际数学运算。在本示例中,假设 HS 是返回标量(在适当的字段中)的散列函数,HP 是返回点(在适当的曲线组中)的散列函数。我们有意避免正式定义这些域和上域,以避免复杂化。让 G 成为各方均知晓的固定点。

  你将使用环签名在交易消息M上签名。门罗币目前要求每个签名有 11 个环成员,但是应考虑一个有 3 个环成员的简化示例。你拥有所支出的输出的密钥对(公开和私有),并选择另外两个输出(及其公钥)作为诱饵。自然而然,环成员的索引应为随机性,因为如果真正的签名者总是在 1 号币口中,则密码匿名将被规避。对于有 3 个环成员的简化示例,假设你的钱包已随机选择将资金的真正来源放在 2 号币口中。

  你从区块链检索诱饵(P?和P?)的公开输出密钥,且你拥有所支出的输出的私钥(p?)和公钥(P?=p?G)。你先选择一个稍后会丢弃的随机数 u。首先你构建以下承诺,从你为密钥选择的一个索引开始:

  c?=Hs(M,uG,uHp(P?))

  为构建其余的承诺,你还可选择稍后需要的随机数 s? 和 s?:c?=Hs(M,s?G+c?P? , s?Hp(P?)+c?p?Hp(p?))

  请注意,此处包含了几条信息:你从区块链提取的公钥 P?、你想出的随机数 s_3、之前的承诺 c? 以及由你自己的密钥形成的值 p?Hp(P?)。继续:c?=Hs(M, s?G+c?P?, s?Hp(P?)+c?p?Hp(P?))

  但是你还未完成!为隐藏实际密钥,你巧妙地定义 s?=u-c?p?。你发送到区块链和世界的签名包含几个数量:(c? , s? , s? , s? , J),其中 J=p?Hp(P?) 是每个承诺中使用的关键图像。我们在此将其重新命名,以强调一个事实:公众对构建承诺的碎片不了解。

  这便是高明之处:通过设置 s?=u-c?p?,你可重新排列来得出 u=s?+c?p?。这意味着公众认为你构建的第一个承诺 c? 如下:c?=Hs(M, s?G+c?P?, s?Hp(P?)+c?p?Hp(P?))

  这看起来和其他承诺完全一样!尽管你从未广播 u,但你用它巧妙地让每个承诺在观察者眼中看起来都一样。这便是环签名的力量。无人能确定哪个承诺隐藏了你真正的密钥,但是每个人均可采用数学方法来证明:

  1. 发送人知晓由公钥表示的一个私钥

  2. 密钥镜像计算正确

  观察到密钥镜像 J=p?Hp(P?) 是从真实输出的密钥对中唯一计算出的、无任何随机数或诱饵的公钥。因此,任何试图欺诈性地第二次支出这笔输出(双花)的情况都将生成相同的密钥镜像。由于网络可跟踪使用的密钥镜像,因此任何重用输出的尝试均会被轻易地检测到并被拒绝。

  请注意,上述 Back 类型 LSAG 环签名示例是出于培训目的而纳入,不应用作产品实现的参考文档。

  4.4 更多资源

  如果想更深入地研究这些技术背后的计算,可以看看《Zero to Monero》,这将是一段高技术性地数学旅程,也是一个社区资助的免费 PDF。

  5. 门罗币区块链

  现在你已熟悉区块链作为分布式公开账本的重要性和实用性。这些区块被结构化并排序到不可变的只加数据库中,由防止任何篡改或欺骗的加密工具进行保护。对于该独一无二的门罗币区块链,我们将会在本节中讨论其技术和规格。

  5.1 闪电记忆映射数据库

  门罗币使用闪电记忆映射数据库(LMDB)系统来存储其区块链。LMDB 是一个软件库,可以密钥值存储形式提供高性能嵌入式交易数据库。这意味着其非常高效,且易于搜索。

  LMDB 是由 C++ 编写的,具有多种编程语言的 API 绑定。由 Symas 公司开发。以下是 LMDB 的一些特征:

  ? 任意密钥/数据对存储为字节数组

  ? 基于范围的搜索能力

  ? 支持具有多个数据项的单个密钥

  ? 在数据库末尾添加记录的高级方法,与其他类似存储相比,该方法大大提高了写入性能

  5.2 区块结构

  CryptoNote 标准定义了在区块内和区块链上存储和描绘数据的规范。区块结构包含三个主要部分:

  ? 区块头

  ? 基础交易(一种产生新币的交易)

  ? 交易标识符列表(在区块中挖掘出的交易散列)

  5.2.1 区块头

  每个区块均以包含密钥元数据的区块头开始。字段“major_version”定义了区块头解析规则,因此其可获得正确解释。字段“minor_version”定义了与主区块头解析无关的解释细节。

  即使“minor_version”未知,用特定“major_version”解析区块头也始终安全。用未知的“major_version”解析区块头有风险,因为区块头内容可能会受到误解。

  

  5.2.2 基础交易

  每个有效区块包含一个单一的基础交易,该交易将其 coinbase 奖励发送给矿工。基础交易必须遵循发币规则,并包含区块高度字段。

  5.2.3 交易标识符列表

  

  基础交易之后是交易标识符列表。这些标识符是通过获取交易本身的 Keccak 散列来计算。列表开头为标识符数量,后面为标识符本身(如果区块不为空)。

  5.2.4 区块标识符的计算

  区块标识符通过用 Keccak-256 散列下列数据产生:

  ? 区块头的尺寸

  ? 区块头

  ? Merkle 根哈希

  ? 交易数量(变量)

  Merkle 根哈希将区块主体中引用的交易“添加”到区块头:一旦 Merkle 根哈希固定后,交易便不能被修改。该安全特性使区块链免受篡改或任何形式的追溯性修改。

  5.3 挖矿经济

  第 2 章和第 4 章从概念上提及区块奖励和费用。现在,你将真正了解区块大小、奖励以及与费用关系的复杂性。

  5.3.1 挖矿 coinbase 奖励

  正如第 4 章所讨论那样,所有门罗币均是作为对矿工成功完成区块奖励而产生。该 coinbase 奖励支付的规模取决于当前供应量(A)和原子单位的初始数量(S=2-1)。原子单位是门罗币目前可由网络(1x10?12 XMR)识别的最小单位

  基础奖励=2*((S-A)*2?2?*10?12)

  门罗币有一个“尾部发行”,这是一个小的固定基础奖励,将在大部分供应开采后继续进行。门罗币的最低基础奖励是每区块 0.6 XMR,因此矿工们将永远不必仅依靠交易手续费维生。

  5.3.2 动态区块大小

  与许多使用静态(固定)区块大小的加密货币相比,门罗币动态区块大小可随着网络的增长而不断调整。例如,比特币最初的 1 MB 固定区块大小会通过限制每个区块中可包含的交易数量(从而限制网络的总交易量)进行缩放。2017 年,该瓶颈导致了极高的费用和交易处理的延迟。因此针对该问题提出了各种拟议的解决办法,导致在一段时间内出现了有争议的辩论。

  为避免这些问题,门罗币采用了动态区块大小机制,允许矿工使用更大的区块来容纳增加的流量。但是,如果区块大小完全不受限,则门罗币网络可能容易受到垃圾交易攻击,即,会有许多小额交易通过使区块链扩张过快来耗尽网络和存储资源。

  为防止区块大小过度增长,门罗币挖矿协议包括一个惩罚函数,以降低对超大区块的 coinbase 奖励。最初的 CryptoNote 作者纳入了该共识规则,以限制区块大小扩展的速率,避免快速的区块链膨胀。

  如果所开采区块的大小(B)大于最后 100 个区块(M?)的中值大小,将会根据以下条件扣留部分基础奖励:

  惩罚=基础奖励*((B/M?)-1)2

  矿工可获得全部奖励只要区块尺寸在 300 kB 以内;对于任何更大的区块,惩罚函数“开始生效”。最大区块大小为 2*M?,此时所有 coinbase 奖励都会被扣缴。