In this guide, you will learn how to encrypt and decrypt files on a Windows computer with the help of PowerShell and PGP (Pretty Good Privacy).

File encryption is commonplace these days. You can encrypt files in many ways with a lot of different tools. One way to do this is through an open-source encryption system called Pretty Good Privacy. PGP has been around a long time, and we can encrypt just about any form of data by using it. For now, we’re going to focus on encryption files using PGP and PowerShell.

To encrypt and decrypt files on Windows with PGP, we must download the GNU Privacy Guard for Windows utility. This free, open-source utility uses the OpenPGP Standard to bring PGP to Windows. We first need to download and install this.

We could go out to the website and do this manually, but we’re using PowerShell! Let’s stick to the command line. We could also figure out how to build a PowerShell tool around GnuPG for Windows ourselves, but why do that when a community module already exists?

Let’s save some time; downloading a PowerShell module from GitHub will expedite this process dramatically. To do that, I’ll reach out to GitHub and download a module called GnuPG and place it in a module path on my system.

$uri = 'https://raw.githubusercontent.com/adbertram/Random-PowerShell-Work/master/Security/GnuPg.psm1'
$moduleFolderPath = 'C:\Program Files\WindowsPowerShell\Modules\GnuPg'
$null = New-Item -Path $moduleFolderPath -Type Directory
Invoke-WebRequest -Uri $uri -OutFile (Join-Path -Path $moduleFolderPath -ChildPath 'GnuPg.psm1')

Once I download the module, I can see I’ve got a few commands available to me.

Get-Command -Module GnuPg | ft -a
Commands in the GnuPG PowerShell module

Commands in the GnuPG PowerShell module

One of those commands is Install-GnuPG. Let’s run that and see what happens.

PS> Install-GnuPG -DownloadFolderPath 'C:\'

Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
     30       2      476        940       0.00   4460   2 gpg4win-2.2.5

This command went out to the GnuPG website, downloaded the installer, and then silently installed it. That saved some time!

Next, I need to encrypt a bunch of important files in a folder with a password only a few other people and I know. To do that, I can use the Add-Encryption command that comes with this module by simply using the Add-Encryption command specifying the folder of files I’d like to encrypt as well as the password I’d like use to secure them.

You can see below that I have a folder with a single file in it. I’m using the Add-Encryption command, which calls the GnuPG utility under the covers to encrypt this file using the password I’m specifying. It returns a GPG file that is the contents of the file encrypted. At this point, I could just remove the original file if I desired.

 Add-Encryption -FolderPath C:\ImportantFiles\ -Password 'secret'
Encrypting a file with PowerShell

Encrypting a file with PowerShell

Now that the file is encrypted in the GPG file, it can’t be read unless decrypted. This GnuPG utility processes the file by first decrypting it, then creating a file of the same name with the unencrypted contents.

You can see below that I’m using the Remove-Encryption command and passing the path of the folder and the secret. The GnuPG utility is creating a keyring if it doesn’t exist yet, decrypting the file, and the Remove-Encryption function is returning the path to the folder that I passed in.

PS C:\> Remove-Encryption -FolderPath C:\ImportantFiles\ -Password secret
gpg: keyring `C:/Users/adam/AppData/Roaming/gnupg/secring.gpg' created
gpg: CAST5 encrypted data
gpg: encrypted with 1 passphrase
gpg: WARNING: message was not integrity protected


    Directory: C:\ImportantFiles


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        2/24/2018   9:36 PM              0 NuclearLaunchCode.txt
-a----        2/24/2018   9:33 PM             60 NuclearLaunchCode.txt.gpg

We can now read that original file like normal!

Subscribe to 4sysops newsletter!

By using the GnuPG utility along with the GnuPG PowerShell module, we can quickly create a handy little tool that can apply encryption to any number of files on the fly. This is an excellent solution for times when you don’t need anything fancy but need a quick way to encrypt files securely with a password.

avataravataravatar
32 Comments
  1. Indra A 4 years ago

    Sir,

    I have used your code for encryption and decryption for PGP files in file server. But when I am decrypting, it is asking for password even though Im using the same code

    param
    (
    [Parameter(Mandatory)]
    [ValidateNotNullOrEmpty()]
    #[ValidateScript({ Test-Path -Path $_ -PathType Container })]
    [string]$FolderPath,

    [Parameter(Mandatory)]
    [ValidateNotNullOrEmpty()]
    [string]$Password,

    [Parameter()]
    [ValidateNotNullOrEmpty()]
    [string]$GpgPath = 'C:\Program Files (x86)\GnuPG\bin\gpg.exe'
    )
    process
    {
    try
    {
    Get-ChildItem -Path $FolderPath -Filter '*.pgp' | foreach {
    $decryptFilePath = $_.FullName.TrimEnd('.pgp')
    Write-Verbose -Message "Decrypting [$($_.FullName)] to [$($decryptFilePath)]"
    $startProcParams = @{
    'FilePath' = $GpgPath
    'ArgumentList' = "--batch --yes --passphrase $Password -o $decryptFilePath -d $($_.FullName)"
    'Wait' = $true
    'NoNewWindow' = $true
    }
    $null = Start-Process @startProcParams
    }
    Get-ChildItem -Path $FolderPath | where {$_.Extension -ne 'pgp'}
    }
    catch
    {
    Write-Error $_.Exception.Message
    }
    }

    But it is opening a window pinquery -qt

    asking for passphrase

     

    • JB 2 years ago

      Hi Indra,

      I also have this issue & wondered if you found a way to disable the additional password prompt?

      Thanks,

      JB

  2. Adam 3 years ago

    Keep getting error:

    Add-Encryption : This command cannot be run due to the error: The system cannot find the file specified.
    At line:1 char:1
    + Add-Encryption -FolderPath c:\pgptest -Password dellwatts1
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Add-Encryption

    At my wits end. There are files in that directory. I've reached the end of google. I've tried single and double quotes. Tried run as admin. Any help would be much appreciated thank you. And thank you for the great tutorial. I wouldn't even get this far without it.

    • Adam 3 years ago

      nevermind got it. installation issue.

      • Ravit Kumar 3 years ago

        Hey Adam,

        I am facing the same issue here with powershell unable to find the file specified.

        How did resolve this?

        • @ravit

          You must first execute the 4 lines at the beginning of this article in order to install the function.

  3. New 3 years ago

    Has anyone been able to get Remove-Encryption to actual work via Powershell?

    Error:

    Remove-Encryption : Cannot validate argument on parameter 'FolderPath'. The " Test-Path -Path $_ -PathType Container " validation script for the argument with value
    "\\NDH2CPRW2FSR001\ftp\Tallahassee\Hold\*gpg" did not return a result of True. Determine why the validation script failed, and then try the command again.

     

    • @New
      That's because you used a wildcard.
      If you have several folders to uncypher, use the Foreach statement.
      For example:

      Get-ChildItem -Path '\\NDH2CPRW2FSR001\ftp\Tallahassee\Hold\*gpg' | ForEach-Object -Process {Remove-Encryption -FolderPath $PSItem.FullName -Password secret}

      • John C Brenner 2 years ago

        Nope same error even with your script block.  

        I have a working script that functions interactively but not as a scheduled task 

        $list = gci '\\someuncpath\'

        foreach ($file in $list.name)
        {$out = $File -replace ".pgp", ""

        & gpg2 --batch --passphrase "secret" --armor --output $out --decrypt $file 2> $null}

  4. Crow 3 years ago

    Running this script on A LOT of files and ran into a rather strange issue. the files are [filename].zip.gpg. When I run this script, it renames the files to .zi, removing the P in .zip.

    • Hi Crow,

      Script just has below trim code to remove the gpg extension. 
      $_.FullName.TrimEnd('.gpg')

      Is this behaviour just specific to zip files?
      Is the decryption-renaming working fine for other files?

  5. Martin 2 years ago

    This method fails if the filename contains any spaces... 🙁

    avatar
    • Please use below block for Remove-Encryption function within gnupg module for a workaround on space in the filename error.

      process {
      		try {
      			Get-ChildItem -Path $FolderPath -Filter '*.gpg' | foreach {
      				$decryptFilePath = $_.FullName.TrimEnd('.gpg')
      				Write-Verbose -Message "Decrypting [$($_.FullName)] to [$($decryptFilePath)]"
      			    & $GpgPath --batch --yes --passphrase $Password -o $decryptFilePath -d $_.FullName
      			}
      			Get-ChildItem -Path $FolderPath | where {$_.Extension -ne 'gpg'}
      		} catch {
      			Write-Error $_.Exception.Message
      		}
      	}

      • Also, don't forget to unload the 'gnupg' module using remove-module and re-load the module using import-module cmdlets one you make above changes.

  6. Nemo 2 years ago

    As mentioned above, the "Remove-Encryption" function was converting my ".zip.gpg" files to ".zi" using the "TrimEnd(".gpg") method. To get around it, I changed the code to use the "Substring" method instead and now it correctly converts my ".zip.gpg" files to ".zip". Here's my code snippet :

    #region Edited by 'Me' to fix a bug for renaming .gpg to .zip
                    $gpgFilename = $_.FullName
                    $len = $gpgFilename.Length
    				#$decryptFilePath = $_.FullName.TrimEnd('.gpg')
                    $decryptFilePath = $_.FullName.Substring(0,$len-4)
    #endregion Edited by 'Me' to fix a bug for renaming .gpg to .zip

  7. Frank 2 years ago

    If you cannot get it to work you nee to use "Install-GnuPG -DownloadFolderPath 'C:\'" which will get you gpg4win-2.2.5.exe, gpg4win-3.1.10.exe will not work.

  8. Shreyas 2 years ago

    Hi All,

    I am trying to decrypt a file with command line using gpg4win-3.1.10.exe.

    I am facing with a run time error on gpg4win while executing the script available in below link

    https://gallery.technet.microsoft.com/scriptcenter/Encrypt-and-Decrypt-Files-214db670

    Error:

    --batch --yes --passphrase $Password -o $decryptFilePath -d $($_.FullName) unrecognized command.

    I am totally new to powershell, could someone please help with the issue.

    Thanks,

    Shreyas

     

  9. PowerShell is made of .NET and the .NET Framework has very good build in Classes to encrypt / decrypt.

    If you do not need PGP i recommend this module which do not need a third party tool:

    Encrypt / Decrypt files with PowerShell using symmetrical encryption

    .Example
    
        #Create Key 
        $key = New-CryptographyKey -Algorithm AES -AsPlainText
    
        # now you can save the key as text elsewhere!
     
        #Encrypt the file 
        Protect-File '.\secrets.txt' -Algorithm AES -KeyAsPlainText $key -RemoveSource 
     
        #Decrypt the file 
        Unprotect-File '.\secrets.txt.AES' -Algorithm AES -KeyAsPlainText $key -RemoveSource

     

  10. Nemo 2 years ago

    Thanks Peter Kriegel for pointing to this excellent source. I have been looking for something like this do to file encryption and decryption using native .NET classes and Powershell commands. This works great !!

  11. Jeff S 2 years ago

    I'll echo that. Thanks Peter Kriegel. I've successfully been using GnuPG to decrypt with powershell for years but recent installations have been nothing but trouble (plus missing/poor documentation.)

    Currently I get prompted for a password even if it's passed in a parameter where that used to work in older versions of GnuPG. I'm going to move to the native libs.

  12. KP 2 years ago

    Hello Sir,

    Can I use this module to PGP encrypt files in a folder using a public key provided by the client, as opposed to using  a password? The public key provided is in .asc format and the client holds the private key used for decrypting the files.

    Thank you!
    KP

  13. Sam 1 year ago

    Do you have to use this software, can't you just powershell this script?

  14. Jeff Reddy 10 months ago

    This example is confusing. Why are we downloading and installing software in step 1, then downloading a PS script library in step 2 that has a command that downloads and installs software in step 3? Is this really all necessary? Care to explain exactly what's happening? This seems fraught with risk.

    Then, after installing 3 different third party software bundles, you give no instruction on how to use them beyond a simple password encryption example. What about support for these three libraries? Is there any? Is there any documentation for these? How do we use an asc key instead of a password? This would be great information.

    • Brian Aborg Weje 9 months ago

      Hi Jeff,
      Did you find a solution?
      I have the exact same. I have recieved an .asc from a partner, and supposed to encrypt the file with .asc file before uploading with SFTP.
      I have done all but the encryption in Powershell (with Posh-SSH module)
      /Brian

      • Jeff Reddy 9 months ago

        I ended up using a .Net solution, https://github.com/Cinchoo/ChoPGP
        I then called the .Net code from my powershell script. This allowed me to do the PGP encryption and I didn't have to install any applications. I need to run my PS script on a server via Task Scheduler. This unattended execution meant that a Public Key could not be used from a user's KeyRing. My solution required no install, the public key file simply had to exist on disk, and everything worked without issue.

        • Brian Aborg Weje 9 months ago

          Hi Jeff

          Great. I have the exact same situation. need to be able to run the powershell from a SSIS package.
          I've downloaded the ChoPGP as a zip.
          If you have a tip/code snippet on how to execute it from Powershell, it would much appreciated.

          • Jeff Reddy 9 months ago

            [Reflection.Assembly]::LoadFile(“C:\PHPEncryption\ChoPGP.dll”)
            [Reflection.Assembly]::LoadFile(“C:\PHPEncryption\BouncyCastle.Crypto.dll”)

            $publicKeyFile = "C:\PHPEncryption\Concur\concursolutionsrotate.asc"
            $workingPath = "C:\PHPEncryption\TestWorkingPath\"
            $destination = "$($workingPath)Encrypted\"

            # simple gpg wrapper
            function Encrypt-File {
            [cmdletbinding()]
            Param([string]$fileToEncrypt)
            Process {
            $nameGen = New-Object -TypeName EncryptedFileNameGenerator
            $encrypteFileName = $($destination) + "encryptedFile.gpg"

            Write-Host "Encrypting file " + $fileToEncrypt + " as " $encrypteFileName
            $choPgpEncryptDecrypt = new-object Cinchoo.PGP.ChoPGPEncryptDecrypt

            $choPgpEncryptDecrypt.EncryptFile($fileToEncrypt, $encrypteFileName, $publicKeyFile, $true, $false)

            Write-Host "File encrypted"
            }
            }

            Encrypt-File -fileToEncrypt "C:\PHPEncryption\testfile.txt"

  15. Guilherme Matheus 8 months ago

    How do I decrypt a message that is in the CSV file, instead of decrypt a file itselft?

    And then, save the decrypted message to another CSV.

    • Leos Marek (Rank: 4)
      8 months ago

      Do you mean to store a secure string in a CSV/TXT file and then recall it somewher else?

  16. Alex 8 months ago

    Hi Jeff,

    Hopeing you can help ,  I've tried your code example above and I can't get it to work, the error suggested the assemblies aren't loaded but I have confirmed that they are.  Is there something obviousl I could be missing?

     

    I have tried multipl ecombinations of chopgp and bouncycastle versions but no joy

     

    Error below if it helps

     

     Encrypt-File -fileToEncrypt "C:\Users\me\Downloads\chopgp.1.0.1.3\lib\test.pdf"
    New-Object:
    Line |
       5 |  $nameGen = New-Object -TypeName EncryptedFileNameGenerator
         |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         | Cannot find type [EncryptedFileNameGenerator]: verify that the assembly containing this type is loaded.
    Encrypting file  + C:\Users\me\Downloads\chopgp.1.0.1.3\lib\test.pdf +  as  C:\Users\me\Downloads\chopgp.1.0.1.3\libencryptedFile.gpg
    MethodInvocationException:
    Line |
      11 |  $choPgpEncryptDecrypt.EncryptFile($fileToEncrypt, $encrypteFileName,  …
         |  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         | Exception calling "EncryptFile" with "5" argument(s): "Could not load file or assembly 'BouncyCastle.Crypto, Version=1.8.1.0, Culture=neutral, PublicKeyToken=0e99375e54769942'. The system cannot find the file specified."

  17. Deepu 6 months ago

    Hi,

     

    How can we use the public key to encrypt and decrypt the file using PGP

    • Jeff Reddy 6 months ago

      The Encrypt has already been posted. Decrypt is another function of ChoPgp, so it's pretty simple.

       

Leave a reply

Please enclose code in pre tags

Your email address will not be published. Required fields are marked *

*

© 4sysops 2006 - 2021

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account