Inedo Community Forums Forums
    • Recent
    • Tags
    • Popular
    • Login

    Welcome to the Inedo Forums! Check out the Forums Guide for help getting started.

    If you are experiencing any issues with the forum software, please visit the Contact Form on our website and let us know!

    Question about Salt_Bytes

    Scheduled Pinned Locked Moved Support
    7 Posts 3 Posters 25 Views 1 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • steviecoasterS Offline
      steviecoaster
      last edited by

      Re: Reset ProGet Admin Password via API

      I've got code using the Native API which creates a user account and works wonders. But as I'm doing this programmatically I need to also generate a random password for the account, and set it. Seems pretty straightforward to do....but I'm unsure about what to do with the Salt_Bytes parameter available on the API. Any pointers would be outstanding.

      1 Reply Last reply Reply Quote 0
      • steviecoasterS Offline
        steviecoaster
        last edited by

        Here's what I'm using currently, but it's complaining about Salt_Bytes. I'm fairly certain this is a PowerShell problem, but more eyes on it never hurt.

        function Set-ProGetUserPassword {
            [Cmdletbinding()]
            Param(
                [Parameter(Mandatory)]
                [String]
                $Username,
        
                [Parameter(Mandatory)]
                [SecureString]
                $OldPassword,
        
                [Parameter(Mandatory)]
                [SecureString]
                $NewPassword
            )
        
            begin {
                $confirm = Read-Host "Please re-enter your new password" -AsSecureString
        
                $identical = Compare-SecureString -SecureString1 $NewPassword -SecureString2 $confirm
        
                if(-not $identical){
                    Write-Error 'Passwords do not match!'
                    break
                }
            }
        
            end {
        
                $unmanagedString = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($NewPassword)
                $plainTextPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($unmanagedString)
                [System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($unmanagedString) # Clean up
                $iterations = 10000
                $saltLength = 10
                $hashLength = 20
        
                $rfc2898 = [System.Security.Cryptography.Rfc2898DeriveBytes]::new($plainTextPassword, $saltLength, $iterations)
                $passwordBytes = $rfc2898.GetBytes($hashLength)
                $saltBytes = $rfc2898.Salt
        
                $base64Password = [System.Convert]::ToBase64String($passwordBytes)
        
                $body = @{
                    User_Name = $UserName
                    Password_Bytes = $base64Password
                    Salt_Bytes = $saltBytes
                }
        
                Write-Verbose ($body | ConvertTo-Json)
        
                $Params = @{
                    Slug = '/api/json/Users_SetPassword'
                    Method = 'POST'
                    Body = $body
                }
        
                Invoke-ProGet @Params
            }
        }
        
        1 Reply Last reply Reply Quote 0
        • atrippA Offline
          atripp inedo-engineer
          last edited by

          Hi @steviecoaster ,

          I'm not really a PowerShell guru, but I think you'll want to do ...

              $base64Salt= [System.Convert]::ToBase64String($saltBytes)
          

          ... and then pass that in.

          Hope that does it!

          Alana

          1 Reply Last reply Reply Quote 0
          • steviecoasterS Offline
            steviecoaster
            last edited by

            In my playing around yesterday, I did try to convert that to base64 and it still produced the same error. I'm very perplexed! For my use case I really need this functionality so I'm hopeful I can find a solution.

            1 Reply Last reply Reply Quote 0
            • steviecoasterS Offline
              steviecoaster
              last edited by

              Sweet mother Mary, I got it! It was the content type. I was using application/json and it wanted application/x-ww-form-urlencoded

              This code works properly to set the password for a user:

              function Set-ProGetUserPassword {
                  [Cmdletbinding()]
                  Param(
                      [Parameter(Mandatory)]
                      [String]
                      $Username,
              
                      [Parameter(Mandatory)]
                      [SecureString]
                      $OldPassword,
              
                      [Parameter(Mandatory)]
                      [SecureString]
                      $NewPassword
                  )
              
                  begin {
                      $confirm = Read-Host "Please re-enter your new password" -AsSecureString
              
                      $identical = Compare-SecureString -SecureString1 $NewPassword -SecureString2 $confirm
              
                      if (-not $identical) {
                          Write-Error 'Passwords do not match!'
                          break
                      }
                  }
              
                  end {
              
                      $unmanagedString = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($NewPassword)
                      $plainTextPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($unmanagedString)
                      [System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($unmanagedString) # Clean up
                      $iterations = 10000
                      $saltLength = 10
                      $hashLength = 20
              
                      $rfc2898 = [System.Security.Cryptography.Rfc2898DeriveBytes]::new($plainTextPassword, $saltLength, $iterations)
                      $passwordBytes = $rfc2898.GetBytes($hashLength)
                      $saltBytes = $rfc2898.Salt
              
                      $base64Password = [System.Convert]::ToBase64String($passwordBytes)
                      $base64Salt = [System.Convert]::ToBase64String($saltBytes)
              
                      $body = @{
                          User_Name = $Username
                          Password_Bytes = $base64Password
                          Salt_Bytes = $base64Salt
                      }
              
                      Write-Verbose $body
              
                      $Params = @{
                          Slug     = '/api/json/Users_SetPassword'
                          Method   = 'POST'
                          Body = $body
                          ContentType = 'application/x-www-form-urlencoded'
                      }
              
                      Invoke-ProGet @Params
                  }
              }
              
              steviecoasterS 1 Reply Last reply Reply Quote 0
              • steviecoasterS Offline
                steviecoaster @steviecoaster
                last edited by

                @steviecoaster said in Question about Salt_Bytes:

                Sweet mother Mary, I got it! It was the content type. I was using application/json and it wanted application/x-ww-form-urlencoded

                This code works properly to set the password for a user:

                function Set-ProGetUserPassword {
                    [Cmdletbinding()]
                    Param(
                        [Parameter(Mandatory)]
                        [String]
                        $Username,
                
                        [Parameter(Mandatory)]
                        [SecureString]
                        $OldPassword,
                
                        [Parameter(Mandatory)]
                        [SecureString]
                        $NewPassword
                    )
                
                    begin {
                        $confirm = Read-Host "Please re-enter your new password" -AsSecureString
                
                        $identical = Compare-SecureString -SecureString1 $NewPassword -SecureString2 $confirm
                
                        if (-not $identical) {
                            Write-Error 'Passwords do not match!'
                            break
                        }
                    }
                
                    end {
                
                        $unmanagedString = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($NewPassword)
                        $plainTextPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($unmanagedString)
                        [System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($unmanagedString) # Clean up
                        $iterations = 10000
                        $saltLength = 10
                        $hashLength = 20
                
                        $rfc2898 = [System.Security.Cryptography.Rfc2898DeriveBytes]::new($plainTextPassword, $saltLength, $iterations)
                        $passwordBytes = $rfc2898.GetBytes($hashLength)
                        $saltBytes = $rfc2898.Salt
                
                        $base64Password = [System.Convert]::ToBase64String($passwordBytes)
                        $base64Salt = [System.Convert]::ToBase64String($saltBytes)
                
                        $body = @{
                            User_Name = $Username
                            Password_Bytes = $base64Password
                            Salt_Bytes = $base64Salt
                        }
                
                        Write-Verbose $body
                
                        $Params = @{
                            Slug     = '/api/json/Users_SetPassword'
                            Method   = 'POST'
                            Body = $body
                            ContentType = 'application/x-www-form-urlencoded'
                        }
                
                        Invoke-ProGet @Params
                    }
                }
                

                Spoke to soon. This code functions and doesn't produce an error. However, the user cannot login with the credential set. More playing to do!

                dean-houstonD 1 Reply Last reply Reply Quote 0
                • dean-houstonD Offline
                  dean-houston inedo-engineer @steviecoaster
                  last edited by dean-houston

                  Hi @steviecoaster ,

                  The Native API can be a little finicky, especially since you can invoke with JSON, forum-encoded values, querystring, and I think even XML. But it sounds like you're on the right track.

                  Let me share the C# code that ProGet uses to set the password:

                      using (var rfc2898 = new Rfc2898DeriveBytes(password ?? string.Empty, 10, 10000, HashAlgorithmName.SHA1))
                      {
                          var bytes = rfc2898.GetBytes(20);
                          DB.Users_SetPassword(userName, bytes, rfc2898.Salt);
                      }
                  

                  ... it looks a little different than the code you're using, so hopefully that will help!

                  -- Dean

                  1 Reply Last reply Reply Quote 0

                  Hello! It looks like you're interested in this conversation, but you don't have an account yet.

                  Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.

                  With your input, this post could be even better 💗

                  Register Login
                  • 1 / 1
                  • First post
                    Last post
                  Inedo Website Home • Support Home • Code of Conduct • Forums Guide • Documentation