首页
Search
1
yamux: how to work?
79 阅读
2
The Art of Memory Allocation: Malloc, Slab, C++ STL, and GoLang Memory Allocation
70 阅读
3
How to receive a network packet in Linux
63 阅读
4
Maps and Memory Leaks in Go
54 阅读
5
C++ redis connection pool
52 阅读
测试
Wireguard
K8s
Redis
C++
Golang
Libcurl
Tailscale
Nginx
Linux
web3
Uniswap V2
Uniswap V3
EVM
security
solidity
openzeppelin
登录
Search
标签搜索
web3
solidity
web3 security
c++
uniswapV3
redis
evm
uniswap
性能测试
k8s
wireguard
CNI
http
tailscale
nginx
linux
设计模式
Jericho
累计撰写
51
篇文章
累计收到
13
条评论
首页
栏目
测试
Wireguard
K8s
Redis
C++
Golang
Libcurl
Tailscale
Nginx
Linux
web3
Uniswap V2
Uniswap V3
EVM
security
solidity
openzeppelin
页面
搜索到
1
篇与
的结果
2022-12-01
wireguard protocol
wireguard使用了ECDH协商算法及noise安全框架故研究了相关知识,针对wireguard握手、数据传输通过源码进行研究。{lamp/}ECDHE密钥协商算法DH数学性质已知数据独有数据离散对数及离散对数的幂运算有交换律指数P、原根a指数P、原根a离散对数及离散对数的幂运算有交换律 指数P、原根a 各自有自己的离散对数数学公式:离散对数如果对于一个整数b和质数p的一个原根a,可以找到一个唯一的指数i,使得: 其中 成立,那么指数i称为b的以a为基数的模p的离散对数。离散对数难题是指:当已知一个大质数p和它的一个原根a,如果给定一个b,要计算i的值是相当困难的a为A的私钥 b为B的私钥 a或b为静态公开 A与BA:A = G ^ a ( mod P ) B:B = G ^ b ( mod P )A: B ^ a ( mod P ) = k B: A ^ b ( mod P ) = kDHE随机生成临时的私钥a与bECDHE利用了 ECC 椭圆曲线特性,可以用更少的计算量计算出公钥,以及最终的会话密钥数学性质已知数据独有数据椭圆曲线及椭圆曲线上满足乘法交换和结合律椭圆曲线、椭圆曲线上一基点G各自有自己的随机数私钥A: 私钥 d1 公钥 Q1 = d1xG B: 私钥 d2 公钥 Q2 = d2xGA: d1xQ2 = k B:d2xQ1Noise安全协议框架为那些想创建自己的安全协议的开发者提供了一套模板,Noise 协议虽然其初衷是为网络协议提供安全信道,但它并没有规定使用什么样的通讯协议 — TCP / UDP 甚至是任何满足 read / write 接口的子系统,比如文件,管道(pipe),都可以使用 Noise 协议在握手阶段,发起者和应答者(initiator / responder,注意 Noise 没有使用 Client / Server,但我们可以简单认为 initiator 是 client,而 responder 是 server)通过交换信息对使用何种算法,密钥是什么达成一致。握手阶段双方需要使用同样的协议变量 —— 和 TLS 不同的是,Noise 把协议变量设计为静态而非协商出来的。这是一个很大的简化,而从用户的角度,用户写出来的使用 Noise 的应用往往是自己的节点跟自己的节点通讯,因而无需协商。WireGuard 使用的是这样的变量:Noise_IKpsk2_25519_ChaChaPoly_BLAKE2sI:发起者的固定公钥未加密就直接发给应答者K:应答者的公钥发起者预先就知道psk2:把预设的密码(Pre-Shared-Key )放在第 2 个握手包之后ChaChaPoly:对称加密算法BLAKE2s:哈希算法协议变量各个部分是这样规定的:Noise <握手的模式> <公钥算法> <对称加密算法> <哈希算法>。其中握手模式有很多种,适用于各种不同的场合。握手的过程中,Noise 会生成一个 HandshakeState,它用来记录当前收到的对端传来的固定公钥和临时公钥,以及通过 ECDH 算法算出来的临时数据。当整个握手结束后,双方都有对等的信息,可以生成一致的密钥。于是发起者和应答者对于它们各自的接收端和发送端生成密钥对。之后,Noise 允许用户将协议状态切换成传输模式(Transport Mode)。切换过程中,HandshakeState 转换成 CipherState,然后就可以用 encrypt / decrypt 来加密和解密应用的数据了。wireguard中具体细节见 wireguard.pdf wireguard内核模块源码分析源码分析数据结构wireguard的消息主要分为三种 message_handshake_initiation、message_handshake_response、message_handshake_cookie发起者 : 发送第一条握手消息// 消息类型 enum message_type { MESSAGE_INVALID = 0, MESSAGE_HANDSHAKE_INITIATION = 1, MESSAGE_HANDSHAKE_RESPONSE = 2, MESSAGE_HANDSHAKE_COOKIE = 3, MESSAGE_DATA = 4 }; message_handshake_initiation = handshake_initiation { u8 message_type //消息类型 u32 sender_index u8 unencrypted_ephemeral[32] //发送方为这次握手临时生成的公钥(未加密,用于 ECDH) u8 encrypted_static[AEAD_LEN(32)] //用对端公钥和临时生成的私钥 ECDH 出的临时密钥 key1 对称加密对方的公钥 u8 encrypted_timestamp[AEAD_LEN(12)] //用对端公钥和自己的私钥 ECDH 出 key2,key2 混淆进 key1,来加密当前的时间戳 u8 mac1[16] //自己的固定公钥加上整个报文内容后的哈希 u8 mac2[16] } initiator.chaining_key = HASH(CONSTRUCTION) initiator.hash = HASH(HASH(initiator.chaining_key || IDENTIFIER) || responder.static_public) initiator.ephemeral_private = DH_GENERATE() msg.message_type = 1 msg.reserved_zero = { 0, 0, 0 } msg.sender_index = little_endian(initiator.sender_index) msg.unencrypted_ephemeral = DH_PUBKEY(initiator.ephemeral_private) initiator.hash = HASH(initiator.hash || msg.unencrypted_ephemeral) temp = HMAC(initiator.chaining_key, msg.unencrypted_ephemeral) initiator.chaining_key = HMAC(temp, 0x1) temp = HMAC(initiator.chaining_key, DH(initiator.ephemeral_private, responder.static_public)) initiator.chaining_key = HMAC(temp, 0x1) key = HMAC(temp, initiator.chaining_key || 0x2) msg.encrypted_static = AEAD(key, 0, initiator.static_public, initiator.hash) initiator.hash = HASH(initiator.hash || msg.encrypted_static) temp = HMAC(initiator.chaining_key, DH(initiator.static_private, responder.static_public)) initiator.chaining_key = HMAC(temp, 0x1) key = HMAC(temp, initiator.chaining_key || 0x2) msg.encrypted_timestamp = AEAD(key, 0, TAI64N(), initiator.hash) initiator.hash = HASH(initiator.hash || msg.encrypted_timestamp) msg.mac1 = MAC(HASH(LABEL_MAC1 || responder.static_public), msg[0:offsetof(msg.mac1)]) if (initiator.last_received_cookie is empty or expired) msg.mac2 = [zeros] else msg.mac2 = MAC(initiator.last_received_cookie, msg[0:offsetof(msg.mac2)])接收者:发送第一条握手回复消息// 消息类型 enum message_type { MESSAGE_INVALID = 0, MESSAGE_HANDSHAKE_INITIATION = 1, MESSAGE_HANDSHAKE_RESPONSE = 2, MESSAGE_HANDSHAKE_COOKIE = 3, MESSAGE_DATA = 4 }; message_handshake_initiation = handshake_initiation { u8 message_type //消息类型 u32 sender_index u32 receiver_index u8 unencrypted_ephemeral[32] //接收方为这次握手临时生成的公钥(未加密,用于 ECDH) u8 encrypted_nothing[AEAD_LEN(0)] u8 mac1[16] //对端公钥加上整个报文内容后的哈希 u8 mac2[16] }1.wireguard 维护一张哈希表(key: peer-pubkey value: &peer),如果不做peer移除处理peer数量将会持续增长,超出peer最大限制10^20个。2.wireguard中对于peer是通过配置文件读取创建的,对peer的处理只能通过用户使用命令进行增删。3.wireguard中keeplive包只有initiator或者responder设置了peer的persistent keeplive time会发送,目前逻辑中responder peer没有设置persistent keeplive time 故responder端不会发送keeplive包。4.wireguard中initiator与responder握手成功之后,initiator会主动发一个数据包或者keeplive包给responder,为了交换并检验双方session key协商的结果。5.wireguard中的session key有9分钟过期时间,创建密session key的时候双方将会启动内核定时器,定时9分钟清空peer对应的session key与临时公私钥。
2022年12月01日
30 阅读
1 评论
2 点赞