0

Using SNMP version 3, I am creating a user. Right now, I have it set up where I clone a user and that works just fine. However, I need to change the new user's authKey. How can I do this? I know the oid for authKeyChange, however, I don't know how to generate the new key. How do I generate that key? Can it be done using SNMPSharpNet? If there is an easier way to do this while I'm creating the user, I can do that as well. ANY way to change the authKey (and privKey, but one step at a time) is much appreciated. I'm using VB.net if it means anything.

Lex Li
  • 52,595
  • 8
  • 102
  • 129
Brandon Willis
  • 135
  • 2
  • 14
  • Everyone says "generate the keyChange value based on the secret privKey of the clone-from user and the secret key to be used for the new user" but no one says HOW. – Brandon Willis Jun 12 '17 at 19:20

1 Answers1

0

So I've figured out how to do this. It's a bit of a complex process. I followed this document, which is rfc2574. Do a ctrl+F for "keyChange ::=" and you'll find the paragraph walking you through the algorithm to generate the keyChange value. The following code has worked reliably to generate the keyChange value. All you have to do from this point is push the keyChange value to the usmAuthKeyChange OID. If you are changing the privacy password, you push the keyChange value to the usmPrivKeyChange OID. I'm ashamed to say that due to the time crunch, I did not have time to make this work completely, so when using SHA, I had to code an entirely new method that did almost the exact same thing. Again, I'm ashamed to post it, but I know how much I was banging my head against a wall, and if someone comes here later and sees this, I would like them to know what to do without going through the struggle.

Here is all of the code you need using VB.Net and the SNMPSharpNet library:

Private Function GenerateKeyChange(ByVal newPass As String, ByVal oldPass As String, ByRef target As UdpTarget, ByRef param As SecureAgentParameters) As Byte()

    Dim authProto As AuthenticationDigests = param.Authentication
    Dim hash As IAuthenticationDigest = Authentication.GetInstance(authProto)
    Dim L As Integer = hash.DigestLength
    Dim oldKey() As Byte = hash.PasswordToKey(Encoding.UTF8.GetBytes(oldPass), param.EngineId)
    Dim newKey() As Byte = hash.PasswordToKey(Encoding.UTF8.GetBytes(newPass), param.EngineId)
    Dim random() As Byte = Encoding.UTF8.GetBytes(GenerateRandomString(L))
    Dim temp() As Byte = oldKey
    Dim delta(L - 1) As Byte
    Dim iterations As Integer = ((newKey.Length - 1) / L) - 1
    Dim k As Integer = 0
    If newKey.Length > L Then
        For k = 0 To iterations

            'Append random to temp
            Dim merged1(temp.Length + random.Length - 1) As Byte
            temp.CopyTo(merged1, 0)
            random.CopyTo(merged1, random.Length)

            'Store hash of temp in itself
            temp = hash.ComputeHash(merged1, 0, merged1.Length)

            'Generate the first 16 values of delta
            For i = 0 To L - 1
                delta(k * L + i) = temp(i) Xor newKey(k * L + i)
            Next
        Next
    End If

    'Append random to temp
    Dim merged(temp.Length + random.Length - 1) As Byte
    temp.CopyTo(merged, 0)
    random.CopyTo(merged, temp.Length)

    'Store hash of temp in itself
    temp = hash.ComputeHash(merged, 0, merged.Length)

    'Generate the first 16 values of delta
    For i = 0 To (newKey.Length - iterations * L) - 1
        delta(iterations * L + i) = temp(i) Xor newKey(iterations * L + i)
    Next

    Dim keyChange(delta.Length + random.Length - 1) As Byte
    random.CopyTo(keyChange, 0)
    delta.CopyTo(keyChange, random.Length)
    Return keyChange
End Function

Private Function GenerateKeyChangeShaSpecial(ByVal newPass As String, ByVal oldPass As String, ByRef target As UdpTarget, ByRef param As SecureAgentParameters) As Byte()

    Dim authProto As AuthenticationDigests = param.Authentication
    Dim hash As IAuthenticationDigest = Authentication.GetInstance(authProto)
    Dim L As Integer = 16

    Dim oldKey() As Byte = hash.PasswordToKey(Encoding.UTF8.GetBytes(oldPass), param.EngineId)
    Dim newKey() As Byte = hash.PasswordToKey(Encoding.UTF8.GetBytes(newPass), param.EngineId)

    Array.Resize(oldKey, L)
    Array.Resize(newKey, L)

    Dim random() As Byte = Encoding.UTF8.GetBytes(GenerateRandomString(L))
    Dim temp() As Byte = oldKey
    Dim delta(L - 1) As Byte
    Dim iterations As Integer = ((newKey.Length - 1) / L) - 1
    Dim k As Integer = 0
    If newKey.Length > L Then
        For k = 0 To iterations
            'Append random to temp
            Dim merged1(temp.Length + random.Length - 1) As Byte
            temp.CopyTo(merged1, 0)
            random.CopyTo(merged1, random.Length)

            'Store hash of temp in itself
            temp = hash.ComputeHash(merged1, 0, merged1.Length)
            Array.Resize(temp, L)

            'Generate the first 16 values of delta
            For i = 0 To L - 1
                delta(k * L + i) = temp(i) Xor newKey(k * L + i)
            Next
        Next
    End If

    'Append random to temp
    Dim merged(temp.Length + random.Length - 1) As Byte
    temp.CopyTo(merged, 0)
    random.CopyTo(merged, temp.Length)

    'Store hash of temp in itself
    temp = hash.ComputeHash(merged, 0, merged.Length)
    Array.Resize(temp, L)

    'Generate the first 16 values of delta
    For i = 0 To (newKey.Length - iterations * L) - 1
        delta(iterations * L + i) = temp(i) Xor newKey(iterations * L + i)
    Next

    Dim keyChange(delta.Length + random.Length - 1) As Byte
    random.CopyTo(keyChange, 0)
    delta.CopyTo(keyChange, random.Length)
    Return keyChange
End Function

Private Function GenerateRandomString(ByVal length As Integer) As String
    Dim s As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
    Dim r As New Random
    Dim sb As New StringBuilder
    For i As Integer = 1 To length
        Dim idx As Integer = r.Next(0, 51)
        sb.Append(s.Substring(idx, 1))
    Next
    Return sb.ToString()
End Function

Again, I am oh so well aware this code is hideous, but it works, and that is all I needed in the meantime. I understand this is technical debt and not the way I should code, but it's here and I hope you can get some use out of it.

If this doesn't work, don't forget to go to frc2574 and look at the algorithm.

Brandon Willis
  • 135
  • 2
  • 14