我有一个利用网络套接字来传输数据的服务。
我需要一种方法来编码一个树结构,并在websocket上传输该树结构。我一直在阅读有关TLV和子TLV编码的文章,这似乎是一个很好的想法,即它已经在诸如Radius、LLDP等协议中使用,这证明了这是有效的。然而,我的问题是,这些协议通常是在可信设备之间使用的,即在交换机/路由器之间(除了LLDP)。我的问题是,我将传输包括子TLV的TLV,这些子TLV具有随机大小/长度,并且它们没有静态定义的结构,例如,如果您查看第一个TLV中的,其中子TLV的概念已经定义,即
Extended IS Reachability #22那么你会看到这个TLV的结构是这样的:
/* +-------+-------+-------+-------+-------+-------+-------+-------+
* | Type | 1
* +---------------------------------------------------------------+
* | Length ID | 1
* +---------------------------------------------------------------+
* | Neighbour ID | 7
* +---------------------------------------------------------------+
* | TE Metric | 3
* +---------------------------------------------------------------+
* | SubTLVs Length | 1
* +---------------------------------------------------------------+
* | SubTLVs value | variable
* +---------------------------------------------------------------+
* : :
*/通过结构,我的意思是我已经预先定义了7字节的邻居ID,3字节的度量,1字节的SubTLV长度,然后才是可变部分,但至少你有一些位是在高级中定义的,不能改变。
现在,通过阅读一些书籍(主要是H Gredler The Complete IS-IS Routing Protocol 2005 -第296页),我发现了4种验证TLV的技术,即:
1)最大长度校验
2)子TLV溢出检查
3)离散长度校验
4) TLV内容模式检查
我根本不能信任来自用户的东西,但我还有两个问题,即如何验证TLV的值是a)随机长度/大小,即我确实有一个值可以具有的范围,即不小于1字节不大于700kb和b)我不能对该值执行任何模式检查,因为它是加密的,即不是以可读的形式,因此不能在它上执行任何模式。
因此,我的问题是:如何实现相同的目标,即在其他结构中发送树结构,即可能是键值对或类似的结构(http使用此结构,这应该有原因)。
TLV方式是否真的是在树结构中传输数据的最佳选择。我知道如果我以二进制形式发送,我将一枪击中两只兔子,即当发送文件时,如图片,我将不需要使用一些有趣的base64编码等,但我真正想要的是一个在L5-7 (即通过websocket)工作的协议,它将允许be以树结构的形式发送数据,其中接收部分将能够识别和重组树,而不必考虑序列化和反序列化部分。那么,考虑到我一边使用java,另一边使用javasctipt,那么TLV的次佳选择是什么呢?
发布于 2015-12-17 11:11:50
这是对评论中问题的回答,而不是原始问题。
有许多选项可用于检查协议错误:
type使用的是while字节(并且您可能没有256种不同的类型),因此您可以检查type是否有效。如果不是,则是协议错误。value字段之后添加一个两个字节的字段,其中包含value字段的第一个和最后一个字节。如果它们不匹配,则存在协议错误;或者value后面添加一个固定大小的MD5散列字段,并根据散列值检查该值的内容。如果数据无效,则存在协议错误(或中间人攻击)。使用Hash (校验和),如选项3(我建议使用MD-5,但任何校验和方法都可以很好)是检查数据完整性和协议一致性的好方法。
使用第一个和最后一个字节检查(选项2)将仅检查协议一致性,而不会检查数据完整性。
验证type字段(选项1)是检查协议完整性的一种简单方法,但它容易出错(因为随机数据更可能是有效的)。
检查接收到的数据的长度与实际数据的长度(问题中的选项1-3 )将很容易出错,并且很可能导致错误。这是因为多余的数据可能被认为是下一个“帧”的一部分,因此只有在数据丢失并且没有接收到更多数据的情况下才会显示错误。
编辑:有关选项2与选项3的更多详细信息
当使用第一个和最后一个字节验证时,每帧应该有大约1:65,536的随机数据通过此验证测试的机会(对于非关键的单帧数据,这可能是一个足够好的测试)。
此外,如果您的数据树包含许多“数据字段”值,那么这个数字会增长得非常快。(当提供随机数据时,4个数据字段树的有效概率仅为1:2^64。
即
假设数据为1字节长,字节值为10 (十六进制0A)。
第一个字节和最后一个字节都等于0A,这意味着验证字段必须是两个字节值0A0A。这是2^16个选项中唯一可接受的值。
但是,它并不保证数据完整性。
让我们假设客户端使用evilproxy.com的服务连接到我们的服务器...
如果值是值为100001的银行帐号,只要第一位和最后一位数字相同(即199991),evilproxy.com就可以将帐号更改为任何值,从而允许evilproxy.com在协议消息仍然有效的情况下更改数据。
另一方面,使用诸如MD5 hush之类的校验和将意味着在本例中操作帐号时校验和的值将发生变化。
MD5使用128位(16字节),这意味着随机验证字段值有1:2^128机会“命中标记”(这是一个可以忽略不计的机会)。
另一方面,如果evilproxy.com知道您用于校验和的算法的“盐”,则此字段可以与数据一起更新。
因此,如果您希望通信更敏感的数据,最好考虑使用校验和。
https://stackoverflow.com/questions/34285918
复制相似问题