1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
try:
from hashlib import sha1
except ImportError:
import sha
sha1 = sha.new
import string
from pysnmp.proto.secmod.rfc3414.auth import base
from pysnmp.proto.secmod.rfc3414 import localkey
from pysnmp.proto import errind, error
_twelveZeros = '\x00'*12
_fortyFourZeros = '\x00'*44
# 7.2.4
class HmacSha(base.AbstractAuthenticationService):
serviceID = (1, 3, 6, 1, 6, 3, 10, 1, 1, 3) # usmHMACSHAAuthProtocol
__ipad = [0x36]*64
__opad = [0x5C]*64
def hashPassphrase(self, authKey):
return localkey.hashPassphraseSHA(authKey)
def localizeKey(self, authKey, snmpEngineID):
return localkey.localizeKeySHA(authKey, snmpEngineID)
# 7.3.1
def authenticateOutgoingMsg(self, authKey, wholeMsg):
# 7.3.1.1
# Here we expect calling secmod to indicate where the digest
# should be in the substrate. Also, it pre-sets digest placeholder
# so we hash wholeMsg out of the box.
# Yes, that's ugly but that's rfc...
l = string.find(wholeMsg, _twelveZeros)
if l == -1:
raise error.ProtocolError('Cant locate digest placeholder')
wholeHead = wholeMsg[:l]
wholeTail = wholeMsg[l+12:]
# 7.3.1.2a
extendedAuthKey = map(ord, str(authKey) + _fortyFourZeros)
# 7.3.1.2b -- noop
# 7.3.1.2c
k1 = string.join(
map(lambda x,y: chr(x^y), extendedAuthKey, self.__ipad), ''
)
# 7.3.1.2d -- noop
# 7.3.1.2e
k2 = string.join(
map(lambda x,y: chr(x^y), extendedAuthKey, self.__opad), ''
)
# 7.3.1.3
d1 = sha1(k1+wholeMsg).digest()
# 7.3.1.4
d2 = sha1(k2+d1).digest()
mac = d2[:12]
# 7.3.1.5 & 6
return '%s%s%s' % (wholeHead, mac, wholeTail)
# 7.3.2
def authenticateIncomingMsg(self, authKey, authParameters, wholeMsg):
# 7.3.2.1 & 2
if len(authParameters) != 12:
raise error.StatusInformation(
errorIndication=errind.authenticationError
)
# 7.3.2.3
l = string.find(wholeMsg, str(authParameters))
if l == -1:
raise error.ProtocolError('Cant locate digest in wholeMsg')
wholeHead = wholeMsg[:l]
wholeTail = wholeMsg[l+12:]
authenticatedWholeMsg = '%s%s%s' % (
wholeHead, _twelveZeros, wholeTail
)
# 7.3.2.4a
extendedAuthKey = map(ord, str(authKey) + _fortyFourZeros)
# 7.3.2.4b --> noop
# 7.3.2.4c
k1 = string.join(
map(lambda x,y: chr(x^y), extendedAuthKey, self.__ipad), ''
)
# 7.3.2.4d --> noop
# 7.3.2.4e
k2 = string.join(
map(lambda x,y: chr(x^y), extendedAuthKey, self.__opad), ''
)
# 7.3.2.5a
d1 = sha1(k1+authenticatedWholeMsg).digest()
# 7.3.2.5b
d2 = sha1(k2+d1).digest()
# 7.3.2.5c
mac = d2[:12]
# 7.3.2.6
if mac != authParameters:
raise error.StatusInformation(
errorIndication=errind.authenticationFailure
)
return authenticatedWholeMsg
|