Search code examples
snmpsnmpsharpnet

Change authKey of a user


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.


Solution

  • 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.