{"content":{"title":"零知识证明-SRP协议","body":"# 零知识证明-SRP协议\r\n\r\n## 简介\r\n\r\n​\t\tSRP 是 Secure Remote Password 协议的缩写，是一种密码协议，用于在客户端和服务器之间建立安全的身份验证。该协议的设计旨在避免将用户密码明文传输到服务器，从而提高了安全性。\r\n\r\n​\t\t在 SRP 协议中，客户端和服务器之间的身份验证是通过一个互相协商的共享会话加密密钥进行的，而该密钥是基于用户的密码和随机数生成的。这个过程涉及到数学计算和密码学。因此，即使传输过程中被截获，攻击者也无法获取用户的密码。\r\n\r\n\r\n\r\n## 优势\r\n\r\n​\t\t这是一个零知识证明协议，服务器不需要存储密码等价信息（散列版本），客户可以安全地对服务器进行认证。而窃听者或中间人无法获得任何有意义的信息来进行攻击。SRP提供了很大的好处，例如。\r\n\r\n- 不需要在网络上发送密码就能进行认证\r\n- 抵御主动和被动攻击，如MITM或暴力字典攻击。\r\n- 证明服务器和客户端的身份，并确保没有冒名顶替者参与。\r\n- 此外还提供一个安全的会话加密密钥，因此客户端和服务器可以传输加密数据，在TLS的基础上提供更高的安全性。\r\n\r\n## 流程详解\r\n\r\n该流程模拟了一个用户通过浏览器或者其他终端与服务端进行通信，该流程主要分为两部分：\r\n\r\n- 注册\r\n- 生成共享会话加密密钥\r\n\r\n- 验证\r\n\r\n### 注册\r\n\r\n- 生成salt（随机数）\r\n- 客户端将用户名（email）、密码和salt传递给数学函数（KDF）以导出x\r\n- 使用x和SRP组生成一个名为verifier的东西。\r\n- 将verifier、salt和SRP组以及用户名发送到服务器，服务器将为用户存储verifier和salt。\r\n\r\n\r\n\r\n> Salt：随机字符串\r\n>\r\n> KDF：一种密钥派生函数，将密码转换为非常大的数字，例如: PBKDF等。\r\n>\r\n> SRP组：由一个大质数组成的一个生成器。您可以在几个组之间进行选择，例如: 1024位，2048位等，在客户端和验证端可以事先约定使用几位的组。\r\n>\r\n> verifier：这是从x生成的随机字符串，它不是密码的散列版本，也不能有效地用来猜测密码。\r\n>\r\n\r\n\r\n\r\n\r\n```\r\n//                ┌──────────────┐                       ┌──────────────┐\r\n//                │   Browser    │                       │  Web Server  │\r\n//                └──────────────┘                       └──────┬───────┘\r\n//                        │\r\n//                                                              │\r\n//     .─.              ┌─┴─┐        GET /register.html       ┌───┐\r\n//    (   )             │   │◀────────────────────────────────│   │\r\n//     `┬'              │   │                                 └───┘\r\n//  ────┼────           │   │                                   │\r\n//      │  email,passwd │   │\r\n//     ┌┴┐ ─────────────▶   ├──┐                                │\r\n//     │ │              │   │  │         generateSalt()\r\n//     │ │              │   │  │ generateVerifier(email,passwd) │\r\n//   ──┘ └──            │   │◀─┘\r\n//                      │   │                                   │\r\n//                      │   │\r\n//                      │   │                                   │\r\n//                      │   │   POST {email,salt,verifier}    ┌───┐\r\n//                      │   ├────────────────────────────────▶│   │\r\n//                      │   │                                 └───┘\r\n//                      └───┘                                   │\r\n//                        │\r\n```\r\n\r\n### 生成共享会话加密密钥\r\n\r\n**客户端**\r\n\r\n- 客户端向服务器发出请求，以获得给定用户名的salt和SRP组。\r\n\r\n- 把用户名、密码、salt当做参数传递给KDF以得出x（与注册时相同）。\r\n\r\n- 使用SRP组生成一个一次性的短暂值a（私有）和它的对应值A（公有），私有的a被保存在内存中，它的公有值A被发送到服务器上。\r\n\r\n**服务端**\r\n\r\n- 使用SRP组生成一次性短暂值b（私有）其对应部分B（公共），将私有值b存储在临时存储器中，并将公共值B发送给客户端。\r\n\r\n此时，一个拥有（x，a，B）的客户和拥有（verifier，b，A）的服务器使用不同的计算方法可以得出相同的值，其被用作会话加密密钥。\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n```\r\n//                  ┌──────────────┐                       ┌──────────────┐\r\n//                  │   Browser    │                       │  Web Server  │\r\n//                  └──────────────┘                       └──────────────┘\r\n//                          │                                     │\r\n//      .─.               ┌───┐         GET /login.html         ┌───┐\r\n//     (   ) email,passwd │   │◀────────────────────────────────│   │\r\n//      `┬' ─────────────▶│   │                                 └───┘                .───────────.\r\n//   ────┼────            │   │     AJAX /challenge {email}       │                 (  Database   )\r\n//       │                │   ├ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ▶───┐               (`───────────')\r\n//      ┌┴┐               │   │                               ┌─┤   │◀──────────────(`───────────')\r\n//      │ │               │   │     step1(email,salt,verifier)│ │   │{salt,verifier}(`───────────')\r\n//      │ │               │   │                               │ │   │                `───────────'\r\n//    ──┘ └──             │   │                               └▶│   │\r\n//                        │   │            {salt,B}             │   │    store b     .───────────.\r\n//                      ┌─┤   │◀─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┤   ├──────────────▶(    Cache    )\r\n//   step1(email,passwd)│ │   │                                 └─┬─┘               (`───────────')\r\n//         step2(salt,B)│ │   │     POST /auth {email,A,M1}     ┌───┐     load b    (`───────────')\r\n//                      └▶│   ├─────────────────────────────────│   │◀──────────────(`───────────')\r\n//                        └───┘                               ┌─┤   │                `───────────'\r\n//                          │                      step2(A,M1)│ │   │         ┌───────────────────┐\r\n//                                                            │ │   │         │You have to retain │\r\n//                        ┌─┴─┐             {M2}              └▶│   │         │the private \"b\"    │\r\n//               step3(M2)│   │◀────────────────────────────────┤   │         │which matches the  │\r\n//                        └─┬─┘     REDIRECT /home.html OR      └─┬─┘         │public challenge   │\r\n// ┌──────────────────────┐              /login.html                          │\"B\". This can be in│\r\n// │step3 confirms a      │ │                                     │           │the main DB or a   │\r\n// │shared private key. A │                                                   │cache.             │\r\n// │mobile running        │ │                                     │           └───────────────────┘\r\n// │embedded JavaScript   │ ▼                                     ▼\r\n// │also confirms the     │\r\n// │server knows the      │\r\n// │verifier that the user│\r\n// │registered with.      │\r\n// └──────────────────────┘\r\n```\r\n\r\n### 验证\r\n\r\n​\t\t在上一步中，我们只是在客户端和服务端创建了相同的会话加密密钥，而没有交换任何敏感信息，但我们没有验证双方是否导出了相同的值。所以这里介绍一下验证流程，如下所示：\r\n\r\n- 客户端使用会话加密密钥加密消息并将其发送到服务器。\r\n- 服务器解密消息并对其进行验证，如果未验证，则验证过程失败。\r\n- 如果验证成功，服务器将使用其会话加密密钥对消息进行加密，并将其发送回客户端。\r\n  客户端解密消息并验证它。\r\n- 此时，客户端和服务器都成功地验证了他们知道用户的密码和合法性，现在可以使用会话加密密钥作为对称加密密钥来交换加密消息。\r\n\r\n---\r\n参考链接： https://medium.com/swlh/what-is-secure-remote-password-srp-protocol-and-how-to-use-it-70e415b94a76"},"author":{"user":"https://learnblockchain.cn/people/66","address":"0xCCF0761Ff668AAc57881af58607765573515CDA4"},"history":"QmRcZQW5DJW9dznqndF6EvYMP3axwGZCkwh3EUb116ceNb","timestamp":1677487552,"version":1}