Open mreams13 opened 5 years ago
I think the KeyChange
algorithm (the way to initialize kcvalue
) is not readily implemented in pysnmp yet. If you have cycles to write one and contribute to pysnmp, I'd happily merge it. ;-)
The algorithm itself is defined in RFC2574 within the KeyChange
TEXTUAL-CONVENTION:
The object's value is a manager-generated, partially-random
value which, when modified, causes the value of the secret
key K, to be modified via a one-way function.
The value of an instance of this object is the concatenation
of two components: first a 'random' component and then a
'delta' component.
The lengths of the random and delta components
are given by the corresponding value of the protocol P;
if P requires K to be a fixed length, the length of both the
random and delta components is that fixed length; if P
allows the length of K to be variable up to a particular
maximum length, the length of the random component is that
maximum length and the length of the delta component is any
length less than or equal to that maximum length.
For example, usmHMACMD5AuthProtocol requires K to be a fixed
length of 16 octets and L - of 16 octets.
usmHMACSHAAuthProtocol requires K to be a fixed length of
20 octets and L - of 20 octets. Other protocols may define
other sizes, as deemed appropriate.
When a requester wants to change the old key K to a new
key keyNew on a remote entity, the 'random' component is
obtained from either a true random generator, or from a
pseudorandom generator, and the 'delta' component is
computed as follows:
- a temporary variable is initialized to the existing value
of K;
- if the length of the keyNew is greater than L octets,
then:
- the random component is appended to the value of the
temporary variable, and the result is input to the
the hash algorithm H to produce a digest value, and
the temporary variable is set to this digest value;
- the value of the temporary variable is XOR-ed with
the first (next) L-octets (16 octets in case of MD5)
of the keyNew to produce the first (next) L-octets
(16 octets in case of MD5) of the 'delta' component.
- the above two steps are repeated until the unused
portion of the keyNew component is L octets or less,
- the random component is appended to the value of the
temporary variable, and the result is input to the
hash algorithm H to produce a digest value;
- this digest value, truncated if necessary to be the same
length as the unused portion of the keyNew, is XOR-ed
with the unused portion of the keyNew to produce the
(final portion of the) 'delta' component.
For example, using MD5 as the hash algorithm H:
iterations = (lenOfDelta - 1)/16; /* integer division */
temp = keyOld;
for (i = 0; i < iterations; i++) {
temp = MD5 (temp || random);
delta[i*16 .. (i*16)+15] =
temp XOR keyNew[i*16 .. (i*16)+15];
}
temp = MD5 (temp || random);
delta[i*16 .. lenOfDelta-1] =
temp XOR keyNew[i*16 .. lenOfDelta-1];
The 'random' and 'delta' components are then concatenated as
described above, and the resulting octet string is sent to
the recipient as the new value of an instance of this object.
At the receiver side, when an instance of this object is set
to a new value, then a new value of K is computed as follows:
- a temporary variable is initialized to the existing value
of K;
- if the length of the delta component is greater than L
octets, then:
- the random component is appended to the value of the
temporary variable, and the result is input to the
hash algorithm H to produce a digest value, and the
temporary variable is set to this digest value;
- the value of the temporary variable is XOR-ed with
the first (next) L-octets (16 octets in case of MD5)
of the delta component to produce the first (next)
L-octets (16 octets in case of MD5) of the new value
of K.
- the above two steps are repeated until the unused
portion of the delta component is L octets or less,
- the random component is appended to the value of the
temporary variable, and the result is input to the
hash algorithm H to produce a digest value;
- this digest value, truncated if necessary to be the same
length as the unused portion of the delta component, is
XOR-ed with the unused portion of the delta component to
produce the (final portion of the) new value of K.
For example, using MD5 as the hash algorithm H:
iterations = (lenOfDelta - 1)/16; /* integer division */
temp = keyOld;
for (i = 0; i < iterations; i++) {
temp = MD5 (temp || random);
keyNew[i*16 .. (i*16)+15] =
temp XOR delta[i*16 .. (i*16)+15];
}
temp = MD5 (temp || random);
keyNew[i*16 .. lenOfDelta-1] =
temp XOR delta[i*16 .. lenOfDelta-1];
The value of an object with this syntax, whenever it is
retrieved by the management protocol, is always the zero
length string.
Note that the keyOld and keyNew are the localized keys.
Thank you for the information. I'll see if I can implement that.
Using net-snmp's snmpusm, I can change a user's authKey and privKey by doing this:
C:\net-snmp\bin\snmpusm -v 3 -u snmpadmin -l authPriv -a SHA -A "SekretSqwerrel" -x AES -X "SekretSqwerrel" fdc8:1437:b763:07eb::1 passwd "SekretSqwerrel" "changeme" normaluser
This command succeeds (normaluser is originally cloned from snmpadmin.)
I'm trying to do the same from pysnmp, but I'm running into the problem that I have no idea what to do with the passwords. (For this purpose authKey and privKey are the exact same.)
I see the process from RFC3414, but I can't find where anyone actually defines what makes up the kcValue. (I also found from Wireshark that net-snmp doesn't bother with the usmUserSpinLock or the usmUserPublic, so I can discard those.)
I'm want to do something like below...
I tried playing around with the output of localizeKey, but I'm not sure that's how that is intended.
What is supposed to go there and is there already a helper function to generate it?