stringpowershellopensslenvironment-variablespasswords

Cannot read password from powershell and give it to openssl


I'm trying to give a password to openssl from powershell :

PS>$pfxFile = "toto.pfx"
PS>$ext= ls $pfxFile | % Extension
PS>$pwd = Read-Host "Enter Import Password" -AsSecureString
PS>$env:pwd = $pwd
PS>openssl pkcs12 -nokeys  -nodes -in $pfxFile -out $pfxFile.replace( $ext , "-FULL.pem" ) -passin env:pwd
Mac verify error: invalid password?
PS>

I've tried casting the pwd variable to string but it does not work either :

PS>$pfxFile = "toto.pfx"
PS>$ext= ls $pfxFile | % Extension
PS>$pwd = Read-Host "Enter Import Password" -AsSecureString
PS>$pwd
System.Security.SecureString
PS>$env:pwd = [string]$pwd
PS>openssl pkcs12 -nokeys  -nodes -in $pfxFile -out $pfxFile.replace( $ext , "-FULL.pem" ) -passin env:pwd
Mac verify error: invalid password?
PS>

How can I make this work ?


Solution

  • A SecureString is not really the same as a regular string - it's a data structure that intentionally obscures the string contents in memory to make it harder to accidentally leak secrets to disk during a memory dump for example.

    You can either materialize the underlying string contents and read it back like so:

    $passwd = Read-Host "Enter Import Password" -AsSecureString
    
    try {
      $secureStringPtr = [System.Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($passwd)
      $cleartextPasswd = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($secureStringPtr)
    }
    finally {
      [System.Runtime.InteropServices.Marshal]::ZeroFreeCoTaskMemUnicode($secureStringPtr)
    }
    

    ... or you can offload it to PSCredential.GetNetworkCredential() - the resulting network credential object will expose the password in clear text:

    $cleartextPasswd = [pscredential]::new('dummyusername', $passwd).GetNetworkCredential().Password
    

    $cleartextPasswd will now contain a regular string with the contents input to Read-Host, which you can then pass to openssl