3

I'm trying to script generation of a single pfx certificate, from one key and one pem file. The following command in Powershell will generate a .pfx as expected:

CertUtil -MergePFX $srcPemPath $outPfxPath

But it prompts me to manually enter the private key password. It'd be most convenient if I didnt have to do this manually.

Looking at the Microsoft documentation I should be able to provide the password as an optional extended property parameter, however when I try the following:

CertUtil -MergePFX $srcPemPath $outPfxPath -p $certPassword

I get an error:

Expected no more than 3 args, received 4
CertUtil: Too many arguments

Neither the usage hint or the documentation makes it clear how this is supposed to be done. Is it possible, and how?

Update

This seems to be purely an issue with my comprehension of certutil.exe's usage: '-p password' is an option, and options should be the first arguments to the certutil executable. For example, -f and -v are also options for force overwrite and verbose output respectively.

Given current working directory only contains fullchain1.pem and fullchain1.key:

In powershell: certutil -f -v -mergepfx .\fullchain1.pem .\testout.pfx

The above creates testout.pfx, overwriting any existing file, verbosely writing the algorithm and public key, prompting the user for a password

In powershell: certutil -p "pass1" -mergepfx .\fullchain1.pem .\testout.pfx

The above creates testout.pfx (provided it doesnt already exist) but will still prompt the user for a password

In powershell: certutil -p "pass1,pass2" -mergepfx .\fullchain1.pem .\testout.pfx The above creates testout.pfx, without prompting the user for a password, the private key password for testout.pfx will be pass2. pass1 and pass2 were arbitrary, pass1 appears to serve no purpose.

So I have a solution, but it'd still be nice to understand why :)

3
  • 1
    Though you are using the PowerShell consolehost to run this command, this is not PowerShell code. You are running an external executable in PowerShell and Powershell has no control over what that executable does or expects. You have to pass it all it needs, in the manner it needs it. You can prove this to yourself by running this in cmd.exe and see you get the same errors. You should not in cmd.exe. To run the external executable in the Powershell console host or the ISE, it has to be done properly. This is well documented by Microsoft. These have to be properly quoted as well.
    – postanote
    Commented Dec 17, 2020 at 20:51
  • Thanks, I hadn't considered that this is an executable and not a powershell command. However I get the same error trying the same from cmd.exe, so I think I have made more than 1 mistake here Commented Dec 18, 2020 at 9:34
  • Understood. and it happens for folks moving from cmd.exe/DOS, Python, etc.
    – postanote
    Commented Dec 19, 2020 at 3:29

1 Answer 1

0

Any external command that has switches, may not be fully understood by PowerShell (consolehost or the ISE or VSCode console), since PowerShell has no idea what those are and would error out or ignore them, thus not passing them.

PowerShell cannot interpret what this is, and thus send it all as is and thus certutil says the error presented because that is not what is expected.

If you want to see what a command is doing, you can use two cmdlets:

  1. Invoke-ScriptAnalyzer
  2. Trace-Command

PowerShell as a command prefernce:

about_Command_Precedence

If you do not specify a path, PowerShell uses the following precedence order when it runs commands for all items loaded in the current session:

  1. Alias
  2. Function
  3. Cmdlet
  4. External executable files (programs and non-PowerShell scripts)

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_command_precedence?view=powershell-7

External command, executables must be properly called, including all needed quoating for parameters from the PowerShell consolehost or ISE or VSCode.

• PowerShell: Running Executables

https://social.technet.microsoft.com/wiki/contents/articles/7703.powershell-running-executables.aspx

  1. Direct - Using the environment path or local folder
  2. Invoke-Expression (IEX)
  3. Invoke-Command (ICM)
  4. Invoke-Item (II)
  5. The Call Operator &
  6. cmd /c - Using the old cmd shell
  7. Start-Process (start/saps)
  8. [Diagnostics.Process] Start()
  9. WMI Win32_Process Create() Method
  10. Stop-Parsing Symbol --%

So, try using, one of the below as per the above pointer:

$CMD = 'SuperApp.exe'
$arg1 = 'filename1'
$arg2 = '-someswitch'
$arg3 = 'C:\documents and settings\user\desktop\some other file.txt'
$arg4 = '-yetanotherswitch'
 
& $CMD $arg1 $arg2 $arg3 $arg4

or ...

$AllArgs = @('filename1', '-someswitch', 'C:\documents and settings\user\desktop\some other file.txt', '-yetanotherswitch')
& 'SuperApp.exe' $AllArgs
2
  • 1
    Thank you for the detailed explanation - I wasn't aware of this, however I have since found that my issue was purely one with my usage of certutil.exe's arguments (see the update to my question). Commented Dec 18, 2020 at 10:16
  • No worries... and as for your comment [So I have a solution, but it'd still be nice to understand why :)], you already have your answer for that. You are bound by the tool(s) you are using. Each tool is 100% responsible for its needs and actions, and you must provided it as it is defined/documented.
    – postanote
    Commented Dec 19, 2020 at 3:32

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .