SNMPv3基于用户的安全模型USM(2)

SNMPv3基于用户的安全模型USM(2)

SNMPv3 Message Format

 

 

 



一个SNMPv3的Message包括以下部分:
1) msgVersion
2) msgID
3) msgMaxSize
发送方支持的最大消息长度/the maximum message size supported by a sender of an SNMP message.
4) msgFlags
8位字段,包含3个flag,最后三位从高到低依次为 reportableFlag, privFlag, authFlag.
reportableFlag如果设置为1,那么如果满足产生report的条件,就会返回一个report给发送方。
所有的request(GET,SET)或者inform,reportableFlag设置为1;Response,Trap,Report中需要设置为0。
privFlag为1表示PDU是加密的。authFlag为1表示PDU是认证的。
5) msgSecurityModel
                     0  reserved for 'any'
                     1  reserved for SNMPv1
                     2  reserved for SNMPv2c
                     3  User-Based Security Model (USM)
6) msgAuthoritativeEngineID
7) msgAuthoritativeEngineBoots
8) msgAuthoritativeEngineTime
9) msgUserName
10) msgAuthenticationParameters
12个字节的HMAC消息摘要(HMAC-MD5-96 或者 HMAC-SHA-96)
11) msgPrivacyParameters
用来产生DES加密算法的初始向量(IV)。
12) contextEngineID
13) contextName
14) PDU
包含了实际请求或者应答数据。
12+13+14一起称为scopedPDU

 

SNMPv1/SNMP2c的报文格式:
version+community+PDU
SNMPv3的报文格式:
SNMPv3的报文格式要复杂一些,可以看作是header+PDU。具体可以看这里http://blog.csdn.net/fw0124/article/details/8557742

PDU的格式:
PDU Type + RequestId + ErrorStatus + ErrorIndex + Variable-Binding
PDU Type
GET 0
GETNEXT 1
RESPONSE 2
SET 3
TRAP-V1 4
GETBULK 5
INFORM 6
Notification(TRAP-V2) 7
Report 8

PDU使用ASN.1来定义数据格式,使用BER进行编码。

ASN.1
ASN.1 (Abstract Syntax Notation dot one)是定义抽象数据类型规格形式的标准。
它是用于描述数据的表示、编码、传输、解码的灵活的记法。它提供了一套正式、无歧义和精确的规则,以描述独立于特定计算机硬件的对象结构。
ASN.1是通信协议中描述数据传输的正式标记(notation),它与语言实现和物理表示无关,与应用的复杂度无关。ASN.1特别适合表示现代通信应用中那些复杂的、变化的及可扩展的数据结构。
ASN.1 本身只定义了表示信息的抽象句法,但是没有限定其编码的方法。各种ASN.1 编码规则提供了由ASN.1描述其抽象句法的数据的值的传送语法(具体表达)。
标准的ASN.1 编码规则有基本编码规则(BER,Basic Encoding Rules)、规范编码规则(CER,Canonical Encoding Rules)、唯一编码规则(DER,Distinguished Encoding Rules)、压缩编码规则(PER,Packed Encoding Rules)和XML编码规则(XER,XML Encoding Rules)。

BER
BER(Basic Encoding Rules)是ASN.1中最早定义的编码规则。
BER传输语法的格式一直是TLV三元组<Type, Length, Value>也可以认为是<Tag, Length, Value>。
TLV每个域都是一系列八位组,对于组合结构,其中V还可以是TLV三元组。
BER传输语法是基于八位组(为了避免不同系统上的混淆,没有采用Byte为单位)的,自定界的编码,因为其中L明确界定了八位组的长度。

BER编码常见的Type:BOOL(0x01);INT(0x02);OCTSTR(0x04);NULL(0x05);OBJID(0x06);ENUM(0x0A);SEQ(0x30);SETOF(0x31);IPADDR(0x40);COUNTER(0x41);GAUGE(0x42);TIMETICKS(0x43);OPAQUE(0x44)

BER编码中Length表示Value部分所占八位组的个数,有两大类:定长方式(Definite Form)和不定长方式(Indefinite Form)。
采用不定长方式时,Length所在八位组固定编码为0x80,但在Value编码结束后以两个0x00结尾。
在定长方式中,按照Length所占的八位组个数又分为短、长两种形式。
length<=127:使用一个八位组。
length>127:使用多个八位组。第一个八位组最高位1,低七位表示的是Length所占的长度,后续的八位组表示长度的实际值。
例如,
长度等于23(0x17) -> 17
长度等于255(0xFF) -> 81 FF
长度等于273(0x111) -> 82 01 11

BER中各种类型的值编码也有详细规定。其中OID的编码规则比较特殊。
以1.2.34.56789为例
A[1] = 1
A[2] = 2
A[3] = 34
A[4] = 56789
BER编码后的八位组用B[m]表示。
1) 两个数字a.b编码为40*a+b。
B[1] = A[1]×40 + A[2] → B[1] = 1 × 40 + 2 = 42(0x2A) = 00101010b
A[1]当前只定义了ccitt(0), iso(1), joint(2)三种。
2) A[3]~A[N]先转化为无符号二进制数
A[3] = 34 = 100010b
A[4] = 56789 = 1101110111010101b
3) 然后从低位开始按照7bit分割
A[3] = 34 = 100010b → 0100010b
A[4] = 56789 = 1101110111010101b → 0000011b, 0111011b, 1010101b
4) 第一个七位组的最高位补上0,其他的七位组的最高位补上1。
A[3] 0100010b → 00100010b
A[4] 0000011b, 0111011b, 1010101b → 10000011b, 10111011b, 01010101b
5) B[2]开始依次放入上面补好位的各个8位组
B[2] = 0100010b = 34(0x22)
B[3] = 10000011b = 131(0x83)
B[4] = 10111011b = 187(0xBB)
B[5] = 01010101b = 85(0x55)

 

SNMPv3发送和接受消息的处理过程
RFC 3414中详细的描述了这个过程。
下载SNMP4J(http://www.snmp4j.org/html/download.html)的源代码,亦可以比较清楚地看到发送和接受消息的处理过程。
发送消息主要的处理在org.snmp4j.security.USM.generateRequestMessage()中(此函数又调用了generateResponseMessage(),实际上的处理在这个函数中)。
接受消息主要的处理在org.snmp4j.security.USM.processIncomingMsg()中。

发送消息首先根据请求数据生成平文的PDU,在PDU头上加上contextEngineID和contextName,得到scopedPDU。
然后对上面所说的SNMPv3 Message Format的1~14各部分设定相应的值,得到整个消息体,
其中msgAuthenticationParameters的12个字节数据置为全零。
然后对scopedPDU部分进行加密。
最后使用HMAC算法作用在加密后的整个消息体上,生成12个字节信息摘要,替换msgAuthenticationParameters。

接受消息和发送相反,首先把收到的消息体中msgAuthenticationParameters的12个字节数据替换为全零。
然后使用HMAC算法作用在替换了msgAuthenticationParameters后的消息体上,生成12个字节信息摘要,
把这个信息摘要和原始的msgAuthenticationParameters比较,如果不等,返回错误。
之后解密scopedPDU。

1) Key Localization
用户的认证(authKey)和加密密码(privKey)不会直接使用。
对于同一个用户的密码,通过Key Localization,用于不同的authoritative SNMP engine的密钥实际上是不一样的。

对于认证密码,Key Localization的过程如下:
org.snmp4j.security.AuthGeneric.passwordToKey(OctetString passwordString, byte[] engineID)
a) 使用用户密码重复填充1个64字节块,使用此64字节块重复填充得到1M字节的数据,
b) 使用认证算法(MD5/SHA1)作用于上面得到的1M字节的数据,得到的摘要为Ku
c)  在snmp engine id的前后加上Ku, 然后再次使用认证算法(MD5/SHA1),得到的摘要即为localized key: Kul

加密密码的处理过程如下:
org.snmp4j.security.SecurityProtocols.passwordToKey(OID privProtocolID, OID authProtocolID, OctetString passwordString, byte[] engineID)
authProtocolID和privProtocolID分别是当前用户的Authentication Protocol和Privacy Protocol.
a) 根据authProtocolID得到当前的AuthenticationProtocol
b) 调用org.snmp4j.security.AuthGeneric.passwordToKey(passwordString, engineID),实际上就是上面认证密码的Key Localization过程。
c) 根据privProtocolID得到加密算法,比较加密算法要求的密钥最小/最大长度和上面得到的localized privKey的长度,
    如果过长截断,如果过短,调用privProtocol.extendShortKey()方法延长。

2) 认证
org.snmp4j.security.AuthGeneric.authenticate(byte[] authenticationKey, byte[] message, int messageOffset , int messageLength, ByteArrayWindow digest)
认证实际上就是根据HMAC计算消息摘要(digest)的过程。
传入的authenticationKey就是localized authKey.
计算摘要的过程见HMAC算法->http://blog.csdn.net/fw0124/article/details/8473858
注意只使用计算得到摘要的前12个字节(96位)

3) 加密解密
CBC-DES加密的处理在函数
org.snmp4j.security.PrivDES.encrypt(byte[] unencryptedData, int offset, int length, byte[] encryptionKey, long engineBoots, long engineTime, DecryptParams decryptParams)
里面。
参数encryptionKey就是16字节的localized privKey, 它的前8个字节用来作为DES key, 因为DES只使用56 bits,每个字节的最低位实际上被丢弃。
The first 8 octets of the 16-octet secret (private privacy key) are  used as a DES key.  Since DES uses only 56 bits, the Least Significant Bit in each octet is disregarded.

CBC模式需要一个64 bit的IV(Initialization Vector)。
encryptionKey的后8个字节用作pre-IV。
为了让每个packet能有不同的IV, 需要对pre-IV进行salt。
使用32-bit的snmpEngineBoots和一个32-bit的随机数一起产生一个64-bit(8字节)的salt。
salt的前4个字节是32-bit的snmpEngineBoots,后4个字节是32-bit的随机数。
然后salt和pre-IV进行异或运算得到IV, IV=salt XOR pre-IV。
最后salt放入msgPrivacyParameters字段发送给接受方用来产生正确的IV进行解密。

解密的处理在函数org.snmp4j.security.PrivDES.decrypt(byte[], int, int, byte[], long, long, DecryptParams)里面。 

posted @ 2023-03-20 11:05  我家有只江小白  阅读(389)  评论(0编辑  收藏  举报