IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 区块链 -> 高级的E2EE——交叉签名(区块链密码签名)(第一篇-SAS) -> 正文阅读

[区块链]高级的E2EE——交叉签名(区块链密码签名)(第一篇-SAS)

? 如果你使用了上篇文章技术,在客户端中成功实现了端到端加密。那么恭喜你!这是真正值得骄傲的一步,也是值得庆祝的一步!但是,您可能已经注意到,有些事情仍处于粗糙边缘:您必须通过比较公钥来手动验证所有其他设备,解密密钥不会在您的设备之间共享等。如果您想在自己的客户端中实现更进一步这些功能,那么本指南适合您

?这是实现以下所有内容所需的一般路线图:

  1. 表情符号验证(SAS 或短验证字符串)
  2. 根据交叉签名状态显示验证状态
  3. SSSS(安全秘密存储和共享)
  4. 其他密钥的签名
  5. 房间内验证(通过房间内的消息进行验证)
  6. 杂项交叉签名的东西
  7. 引导 SSSS 和交叉签名
  8. 在线密钥备份

??1.实施表情符号验证(SAS)

? 表情符号验证是称为 SAS 的验证模型的一部分,用于短验证字符串。除了表情符号验证,还有数字验证。预计所有支持 SAS 的客户端都至少支持数字验证。这是为了确保仍然可以验证可能无法显示表情符号的客户端(可能是某些 CLI 应用程序或嵌入式设备显示)

验证过程概览

验证通过两个设备相互发送消息,通过 to_device 消息或通过房间中的消息进行。想要验证另一个设备 (Bob) 的设备 (Alice) 会发送一条m.key.verification.request?消息及其支持的方法。Bob 用 回答m.key.verification.ready,同时通知 Alice 它支持哪些方法。在客户端 UI 中,Bob 在收到m.key.verification.request?消息后会弹出一个新的验证请求。在双方都接受开始后,任何一方(Alice 和/或 Bob)都可以发送一个m.key.verification.start特定于所使用的验证方法的 。如果 Alice 和 Bob 都发送 a?m.key.verification.start且验证方式不匹配,则取消验证请求。如果验证匹配,则m.key.verification.start使用按字典顺序较小的用户 ID。如果它们也匹配(例如,如果您正在验证自己的设备),则使用字典顺序较小的设备 ID。这确保了m.key.verification.start?使用哪个是明确的。从现在开始,使用的设备m.key.verification.start就是发起请求的设备(这很重要,因为 SAS 中的某些事情取决于谁发起了请求)。之后,会发生一些验证过程,即特定的验证方法。如果一切都成功,则双方m.key.verification.done互相发送一个。

为了使所有这些工作,每个验证请求都有一个唯一的交易 ID,这是一个不透明的字符串,用于标识特定的验证请求。在房间验证的情况下,这是第一个发送消息的事件 ID (?m.key.verification.request)。任何一方都可以随时取消验证请求,方法是发送一个m.key.verification.cancel以及有关取消原因的一些信息。

send由于发送的所有消息都会添加一些通用元数据,因此编写一个包装函数来发送密钥验证数据可能是一个好主意。此函数还可以将发送事件处理为 to_device 消息或房间事件。to_device 和房间验证的消息内容略有不同:

对于 to_device 消息,transaction_idfrom_device被简单地添加到发送的对象中。?transaction_id表示交易的唯一 ID,而from_device只是一个包含您自己的设备 ID 的字符串。有效载荷,例如

{
  "foo": "bar"
}

因此看起来像:

{
  "foo": "bar",
  "transaction_id": "some-awesome-id",
  "from_device": "DXKKF"
}

对于房间消息,事务ID,即第一个事件的事件ID,被添加到?m.relates_to事件的部分。设备 ID 与 to_device 消息相同;它应该设置为发送设备的 ID。所以上面的payload就变成了:

{
  "foo": "bar",
  "from_device": "DXKKF",
  "m.relates_to": {
    "rel_type": "m.reference",
    "event_id": "$firstEventId"
  }
}

为简单起见,下面提到的所有有效负载都将在没有这些额外键的情况下显示。

发送的 to_devices 不必加密,因为验证请求的整个想法是它们可以公开。然而,客户端无论如何都可以选择这样做,例如,如果它们发送 to_device 消息的功能默认为加密发送它们。房间消息是否加密通常取决于发送它们的房间是否加密。

m.key.verification.request

发送这个会启动一个验证请求。它会发送您知道的所有验证方法(在 SAS 的情况下仅为m.sas.v1),以及当前时间戳(以毫秒为单位)。

{
  "methods": ["m.sas.v1"],
  "timestamp": 1590314157821
}

如果过去超过 10 分钟或未来超过 5 分钟,接收客户端将拒绝该请求。

m.key.verification.ready

发送此信息表示您接受密钥验证请求,并另外显示您自己支持的方法。这样,两个验证合作伙伴都将能够弄清楚他们有哪些共同的方法。

{
  "methods": ["m.sas.v1"],
}

m.key.verification.start

发送此信息表示您正在使用特定方法开始验证。确切的有效载荷取决于验证方法。

{
  "method": "m.sas.v1",
  // additional keys specific to m.sas.v1
}

m.key.verification.done

发送此信息表示验证过程已完全完成。

{}

m.key.verification.cancel

发送此消息会取消验证(超时、密钥不匹配、用户取消等)。它有一个人类可读的原因,以及一个取消代码。

{
  "reason": "The verification timed out",
  "code": "m.timeout"
}

回顾

回顾一下,Alice 想要验证 Bob的一般验证过程如下:

  1. Alice 向 Bob 发送m.key.verification.request了她支持的方法。
  2. Bob 收到该请求。他的设备询问他是否想与 Alice 进行验证。他点击接受。
  3. m.key.verification.readyBob连同他支持的方法一起发送。
  4. Alice 收到 Bob 的方法,并根据该方法和她自己的m.key.verification.start方法,发送一个他们共有的方法。
  5. Bob 也发送了一个m.key.verification.start,这恰好和 alices 是同一个方法
  6. 由于 Alice 的用户 ID 在字典上较小(@alice:example.orgvs?@bob:example.org),所以使用 Alice 发送的启动命令。
  7. 具体验证方法如下。
  8. 当 Alice 和 Bob 完全完成验证后,他们会互相发送一个m.key.verification.done.

看看SAS

好的,现在我们已经了解了验证过程框架的一般工作原理,让我们具体看看 SAS。

由于遗留原因,不幸的是,有些客户直接希望使用 开始 SAS 验证?m.key.verification.start,因此需要进行处理。如果有这样的启动请求进来,并且是 SAS,提示用户是否接受验证。然后照常继续 SAS 流程。

SAS 验证的一般思想是希望相互验证的双方 Alice 和 Bob 生成一个临时的公钥/私钥对并交换公钥。使用??ECDH,只要中间没有人,它们都会生成相同的密钥。然后使用表情符号或数字对生成的密钥进行比较。在验证它们在任一侧都匹配之后,就知道ECDH的输出是相同的。因此,相互发送的 ECDH 的临时公钥得到了成功验证。使用这些密钥,可以形成一个安全通道,发送想要相互验证的实际设备密钥。收到后,验证过程完成!

在实践中,它的工作原理如下:Alice 向 Bob 发送 am.key.verification.start以及她支持的一堆不同参数(哈希方法、表情符号/数字验证、要使用的特定 ECDH 等),Bob 将回复 a?m.key.verification.accept,这将基于根据 Alice 所宣传的能力,并根据 Bob 知道他自己可以做的事情,确定使用哪种确切的方法。之后,他们都生成并向对方发送 ECDH 的临时公钥,并且表情符号或数字会显示在屏幕上。一旦他们都使用某种安全的第三方渠道(例如亲自见面)验证他们匹配,他们将互相发送一个m.key.verification.mac,其中包含他们应该验证的密钥的 MAC。验证后,他们都互相发送a?m.key.verification.done并且他们被验证了!

m.key.verification.start

这会发送一堆发送设备支持的参数。请注意,在执行承诺检查(将在下一节中解释)时,您必须记住该对象,该对象包含transaction_id和的元数据from_device,在这些示例中省略。

{
  "method": "m.sas.v1",
  "key_agreement_protocols": ["curve25519-hkdf-sha256"],
  "hashes": ["sha256"],
  "message_authentication_codes": ["hkdf-hmac-sha256"],
  "short_authentication_string": ["emoji", "decimal"]
}

承诺生成

承诺是一个额外的验证过程。它是您生成的连接临时公钥和?m.key.verification.start正文的规范 json 的哈希值(基于指定的哈希方法)。Libolm 提供散列方法和公钥/私钥生成。计算承诺的代码如下所示:

var sas = olm.SAS(); // save for later. This will generate our ephemeral public/private keypair
var canonicalJson = ""; // the canonical json of the `m.key.verification.start` request

var commitment = "";
if (hashMethod == "sha256") {
  var olmutil = olm.Utility();
  commitment = olmutil.sha256(sas.get_pubkey() + canonicalJson);
  olmutil.free();
} else {
  throw "Unknown hash method";
}

m.key.verification.accept

这接受m.key.verification.start请求,并发送双方支持的参数。除此之外,它还发送一个commitment,如上定义。

{
  "method": "m.sas.v1",
  "key_agreement_protocol": "curve25519-hkdf-sha256",
  "hash": "sha256",
  "message_authentication_code": "hkdf-hmac-sha256",
  "short_authentication_string": ["emoji", "decimal"],
  "commitment": "the-commitment-calculated"
}

m.key.verification.key

这会将临时公钥相互发送。如果您尚未生成它(由于尚未计算承诺),请立即var sas = olm.SAS();使用sas.get_pubkey();.?确保如果您收到了承诺,则使用收到的公钥来验证您之前收到的承诺。公钥既被添加到sas对象中,sas.set_their_key(payload["key"]);?又被保存在一个单独的变量中,因为稍后您将需要它,不幸的是,该sas对象不允许再次检索它。

{
  "key": "your-public-key"
}

显示表情符号/数字

根据商定的key_agreement_protocolshort_authentication_string支持的 s,现在应该提示用户使用表情符号/数字,以便他们可以验证它们是否匹配。为此,您必须生成字节以从中派生表情符号以进行比较。为此,创建了“SAS 信息”。对于密钥协商协议curve25519-hkdf-sha256,它的工作方式如下:

SAS 信息与开始验证的用户 ID 加上开始验证的设备 ID 加上开始验证的 SAS 公钥加上接收验证的用户 ID 加上接收验证的设备 IDMATRIX_KEY_VERIFICATION_SAS|连接在一起。验证加上接收验证的 SAS 公钥加上交易 ID。在可能如下所示的代码中:

var ourInfo = '${client.userID}|${client.deviceID}|${sas.get_pubkey()}|';
var theirInfo = '${request.userId}|${request.deviceId}|${theirPublicKey}|';
var sasInfo = 'MATRIX_KEY_VERIFICATION_SAS|' +
    (request.startedVerification
        ? ourInfo + theirInfo
        : theirInfo + ourInfo) +
    request.transactionId;

密钥协商协议curve25519已弃用,不应实施。因此,这里没有概述。

生成字节

获得该 SAS 信息后,您可以使用它通过sas.generate_bytes(sasInfo, bytes).?表情符号验证需要 6 个字节,数字验证需要 5 个字节。但是,您可以始终生成 6 个字节,并且对于数字验证,只使用前 5 个字节。

如果双方都说他们可以显示表情符号,那就显示那些!如果一方只支持号码,则显示号码。以防万一,最好有一个按钮在表情符号和数字之间来回切换。

数字

要获得您比较的数字,您需要使用上述方法生成 5 个字节。将它们分成三块,每块 13 位,丢弃最后一位。然后将 1000 添加到每个数字,这意味着它们可以在 1000 到 9191 的范围内。预计显示的数字之间带有一些分隔符,例如1337-4242-9001

表情符号

要让表情符号进行比较,您需要使用上述方法生成 6 个字节。将它们分成 7 块,每块 6 位,丢弃最后 6 位。

表情符号/数字匹配:计算 MAC

一旦用户说他们的表情符号/数字匹配,这意味着他们有一个安全的渠道!然后根据您希望对方验证的设备 ID 和公钥计算 MAC。目前,仅使用该方法发送您自己的公钥。在本指南的后面部分,您还将发送您的主交叉签名密钥。为此,创建了一个基本信息,它是连接的字符串?MATRIX_KEY_VERIFICATION_MAC,您自己的用户 ID,您自己的设备 ID,其他用户的 ID,其他设备的 ID,以及交易 ID。请注意,与 SAS 不同,它不|使用分隔符,并且顺序不取决于谁开始验证:

var baseInfo = 'MATRIX_KEY_VERIFICATION_MAC' +
    client.userID +
    client.deviceID +
    request.userId +
    request.deviceId +
    request.transactionId;

接下来计算您的设备 ID 的 MAC 和您要发送的指纹:

String _calculateMac(String input, String info) {
  if (messageAuthenticationCode == "hkdf-hmac-sha256") { // this is from the m.key.verification.accept call
    return sas.calculate_mac(input, info); // the same sas object we used previously, from libolm
  } else {
    throw "Unknown message authentication code";
  }
}

Map<String, String> mac = {}; // create the map for the MACs
List<String> keyList = []; // the list / array holding all the key Ids to verify

// now add all the keys we want to verify
var deviceKeyId = "ed25519:${client.deviceID}";
mac[deviceKeyId] = _calculateMac(client.fingerprintKey, baseInfo + deviceKeyId); // client.fingerprintKey is here the public key string for our device
keyList.add(deviceKeyId);

// now we still need to sort the key list
keyList.sort();
var keys = _calculateMac(keyList.join(","), baseInfo + "KEY_IDS");

m.key.verification.mac

将密钥的 MAC 发送给对方以进行验证。

{
  "mac": { // is the "mac" object calculated above
    "ed25519:CCKDF": "<calculated MAC here>"
  },
  "keys": "<MAC for keys here>" // is the calculated "keys" string above
}

接收/验证 MAC

在收到 MAC 并让用户验证表情符号匹配(因此也发送您自己的 MAC)后,您必须验证收到的 MAC 是否有效,并且仅在 MAC 有效时验证密钥。为此,从对方的角度生成基础信息;本质上是把别人的信息放在你自己之前:

final baseInfo = 'MATRIX_KEY_VERIFICATION_MAC' +
    request.userId +
    request.deviceId +
    client.userID +
    client.deviceID +
    request.transactionId;

然后从接收到的对象的字典键中生成键列表mac并验证 MAC 是否匹配:

final keyList = payload["mac"].keys.toList();
keyList.sort();
if (payload["keys"] != _calculateMac(keyList.join(","), baseInfo + "KEY_IDS")) {
  await request.cancel("m.key_mismatch");
  return;
}

然后通过迭代对象来验证密钥本身的 MAC,并如上所述再次计算密钥的 MAC。您自己应该已经拥有公钥,因为您只是在验证密钥是否匹配。如果您收到了您不知道的密钥的 MAC,请忽略它。它可能是您还不知道如何处理的交叉签名密钥。但是,如果只有一个MAC 不匹配,则不要验证任何设备并取消整个请求。

最后发送一个m.key.verification.done,你就完成了!

回顾

所以,整个 SAS 验证流程简而言之如下:

  1. (可选)Alice 向 Bob a 发送m.key.verification.request她支持的方法,包括?m.sas.v1.
  2. (可选)Bob 收到该请求。他的设备询问他是否想与 Alice 进行验证。他点击接受。
  3. (可选)Bob 发送一个m.key.verification.ready连同他支持的方法,包括m.sas.v1.
  4. Alice 收到 Bob 的方法,并基于此,以及她自己知道如何做的方法,她发送一个m.key.verification.startfor?m.sas.v1。这将包含一系列关于 SAS 如何具体工作的参数。Alice 的设备记下请求的规范 json,以供以后的承诺验证。
  5. Bob 也可以发送一个m.key.verification.startfor?m.sas.v1。但是,由于 Alice 用户 ID 在字典上较小,因此被丢弃。
  6. Bob 收到m.key.verification.start,并使用 生成他自己的临时密钥对var sas = olm.SAS();。然后,他使用请求的规范 json 来计算承诺m.key.verification.start,然后将?m.key.verification.accept回传给 Alice,以及用于此 SAS 验证的特定参数。
  7. Alice 收到m.key.verification.accept并存储承诺以供以后验证。她现在创建自己的临时密钥对,var sas = olm.SAS();并通过 向 Bob 发送公钥m.key.verification.key
  8. Bob 从 Alice 那里收到公钥并发送他自己的公钥。Bob 的设备现在显示表情符号/数字以供验证。
  9. Alice 收到 Bob 的公钥,最终可以验证她之前保存的承诺。如果全部匹配,Alice 的设备现在将显示表情符号/数字以进行验证。
  10. 如果表情符号/数字都匹配,它们将相互发送一个m.key.verification.mac带有 MAC 的应验证密钥信息。
  11. 最后,如果全部check out,则互相发送a?m.key.verification.done,验证过程结束。

需要注意的事项

  1. 始终验证传入消息是否具有有效的已知事务 ID。
  2. 始终验证传入消息不超过过去 10 分钟。
  3. m.key.verification.cancel无论出于何种原因,一旦收到 ,请务必立即停止验证过程。
  4. 不要只是盲目地假设方法message_authentication_code等如这里所述。未来可能会添加更多内容,因此始终验证您实际支持哪些漏洞并采取相应措施。
  5. sas.free();在验证结束或超时或取消时,不要忘记生成的 SAS 对象。
  6. 不要忘记计算和验证承诺!
  7. 概括处理验证流程的代码可能是一个好主意,以便您可以在m.sas.v1以后轻松添加其他方法。

  区块链 最新文章
盘点具备盈利潜力的几大加密板块,以及潜在
阅读笔记|让区块空间成为商品,打造Web3云
区块链1.0-比特币的数据结构
Team Finance被黑分析|黑客自建Token“瞒天
区块链≠绿色?波卡或成 Web3“生态环保”标
期货从入门到高深之手动交易系列D1课
以太坊基础---区块验证
进入以太坊合并的五个数字
经典同态加密算法Paillier解读 - 原理、实现
IPFS/Filecoin学习知识科普(四)
上一篇文章      下一篇文章      查看所有文章
加:2022-08-19 19:11:13  更:2022-08-19 19:11:25 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 3:05:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计