Encrypting powershell script using key parameter to decrypt and run on other computers

So I’ve posed this question on another forum and have had no luck thus far. Not sure if I’m allowed to post that link here. So I followed a tutorial to encrypt a complete powershell script and that script can be decrypted and ran again perfectly fine. Here is what I did that worked to Encrypt a script, and then run it. This doesn’t use the key parameter so it will only work on the machine I encrypted the script on.

Encrypting the code/script:

$Code = Get-Content -RAW ".\scriptdata.txt"
$CodeSecureString = ConvertTo-SecureString $Code -AsPlainText -Force
$Encrypted = ConvertFrom-SecureString -SecureString $CodeSecureString
$Encrypted | Out-File -FilePath ".\scriptdataEncrypted.txt"

Decrypting and running the code/script:

$Instructions = "encrypted data from scriptdataEncrypted.txt goes here"
$Decrypt = $Instructions | ConvertTo-SecureString
$Code = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Decrypt))
Invoke-Expression $Code

I’m very bad with syntax and trying to learn. I wailed away at this for hours and can’t figure it out. Have watched Youtube videos and read articles trying to wrap my head around what I am doing wrong. A good Samaritan in another forum presented me with the following tips to get it working utilizing a key. I don’t care if the key is in the same folder as the script, I’d just like to see this work and run encrypted on a second machine. Here is what was shared with me on the other forum:

# Encrypting the code/script
$Key = "YourSecretKey"  # Replace with your secret key
$Code = Get-Content -Raw ".\scriptdata.txt"
$CodeSecureString = ConvertTo-SecureString -String $Code -Key (ConvertTo-SecureString -String $Key -AsPlainText -Force)
$Encrypted = ConvertFrom-SecureString -SecureString $CodeSecureString
$Encrypted | Out-File -FilePath ".\scriptdataEncrypted.txt"

# Decrypting and running the code/script
$Key = "YourSecretKey"  # Same key used for encryption
$Instructions = Get-Content -Raw ".\scriptdataEncrypted.txt"
$Decrypt = ConvertTo-SecureString -String $Instructions -Key (ConvertTo-SecureString -String $Key -AsPlainText -Force)
$Code = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Decrypt))
Invoke-Expression $Code

I could not even get the encrypt step to work without errors. I’ve tried reading the Microsoft articles that go into how to use the -key param and most of the tutorials cover using it for password and sensitive credentials. I’m just trying to do what the first script I shared does successfully, but with the added bonus of the ability to have it run on other machines. The usage stuff on the Microsoft pages are hard for me to follow because I don’t understand the command structure or syntax well enough. That’s why examples and tutorials are so helpful for me. It’s just something I’m bent on trying to solve, nothing pressing. Thanks for any knowledge out there.

Can I ask why are you trying to encrypt a script and then decrypt it? The key will still need to be passed somehow to run it and will likely show up in a log which defeats the purpose of encryption.

Also if the purpose is to run on remote systems then I would suggest just executing via a PSsession or if you have configuration management tools, app catalogs etc these could be used to run the the script in a safer and more controlled manner on remote systems.

1 Like

This seems like a strange workflow . Can you clarify on why you need to be encrypting a script like this? I think from a general perspective you need to re-evaluate why you are doing this process, as and make sure you’re actually solving a problem.

As for the issue - I’m not quite following the logic on why you or the person who was helping you is passing ConvertTo-SecureString -String $Key -AsPlainText -Force to the Key parameter. Also you need a securestring already to Convert something from a secure string, which you do in the first code that worked, but you didn’t from the other person’s example. It doesn’t seem like that person even tested their code heh.

ConvertTo-SecureString (Microsoft.PowerShell.Security) - PowerShell | Microsoft Learn

couple of examples on that page, you probably can just follow those to accomplish the task. I wrote this real quick which seems to work.

$Key = (1..16)
$Code = Get-Content -Raw ".\scriptdata.txt"
$SecureCode = ConvertTo-SecureString -String $Code -AsPlainText -Force
$Encrypted = ConvertFrom-SecureString -SecureString $SecureCode -Key $Key
$Encrypted | Out-File -FilePath ".\scriptdataEncrypted.txt"

I feel as if I did clarify in my original post. I just like learning stuff. I was able to get it encrypted and ran decrypted. I was even to able to get a HUGE script encrypted in 3 separate blocks to circumvent the character limit and I was a little proud of myself. When I noticed it wouldn’t run on my other machine, I didn’t want to just give up. I wanted to see if I could figure it out.

I agree, he likely didn’t test the code, but I am still thankful he took the time to help as I am glad you have as well. I looked at that Microsoft page but I still structure commands incorrectly all the time. I tried your example and it failed, but I found a mistake I made. I pulled content from the already encrypted script like a moron and the string was beyond the character limit. Once I set it to the proper source file, your script worked perfectly. And this is what I hate about myself. I could not figure this out after LOTS of trying and you whipped it up in a minute. I will analyze how you rewrote the encryption process and try to get the decrypt and run working calling on the key. Does the key need to be stored as a file to decrypt? Sorry if that’s a dumb question.

Your teaching code is very helpful and I appreciate you. I’m like the guy who can’t build the fighter jet, but I will capture the enemies and try to reverse engineer it. :grinning:

Thank you so much @dotnVo !

JamesPowerShellOrg,
Welcome to the forum. :wave:t3:

I’d like to say straight away that I don’t have personal experience on this topic. I never had the need to use or felt the urge to learn.
If someone has control over a computer system he will easily be able to get to the uncrypted code if it runs on the system.

It would have been nice to have this link. This way we wouldn’t have to guess what answer you might have gotten already. :wink:

Using the built in functionality to encrypt and decrypt you’re limitted to this one user on this one computer. It will not work on another computer even with the same user. To make your key portable you have to use either a third party software or the Microsoft Secret Management Module.

Here’s the link, as long as I’m not breaking any rules.

I’ve read a bunch of things and I’ve found this not to be the case, where the built in tools are used to encrypt, and create a key to a file that can be carried with the script or it’s folder and referenced to decrypt on another machine.

Tomorrow’s my Bday and I’m going to have cake with my awesome son. If I can this weekend I’m going to try to get decrypt and run working without bugging @dotnVo if I can. I have low expectations, but I gotta try :sunglasses:

Gotcha, no worries! Keep working at it and do not hate yourself, we all start somewhere, and as long as you expose yourself to PS everyday, and keep trying, you’ll get better and better. Glad the code assisted!

Damn I lost my whole draft somehow, here it goes again. Here’s where I asked elsewhere if I am not breaking any rules. Encrypting powershell script using AES key to decrypt and run on other computers

@Olaf Olaf I’ve read a ton about it and I believe people are doing this without third party. They are encrypting with a key, the key gets stored in the script or to a file somewhere. That just needs to be accessible on the 2nd computer to be referenced to decrypt.

My Bday is tomorrow so going to have cake with my son. If I have time this weekend I’m going to try to decrypt and run the code @dotnVo helped me create. I have low expectations but I have to try.

Thanks going to try to figure out the next step without bugging you but before I do, will I have to create some sort of Key file or will I be able to decrypt and run in one shot if I write that script correctly?

I keep meaning to play around w/ the secret module - I heard great things.

Regardin the portability aspect - It depends on how you encrypt it. Using Windows DPAPI, for example (Export-CLIXML uses this) it really only works on that computer, but that can be handy depending on the use case.

Another way would be to use a certificate, which, as long as you have the cert installed and can read the private key, you’re good to go. In my head i consider this ‘what you have’ security. There’s other ways I think of doing this but I’ve used Unprotect-CMSMessage and Protect-CMSMessage for this very successfully.

In this example it’s a key that’s doing the encryption (what you know). So if you ran the decryption code that the OP provided on one computer, and exported it, then moved that file to another system, and then tried to get that data, and decrypt, then convert from a secure string using the marshal process, it will work as long as you have the proper key.

There’s probably even other ways out there.

TBH i haven’t used the process and didn’t know it was a thing until you posted about it, but basically all you need is that key to unlock it, no matter where the file resides. I tested that real quick when I was writing back to Olaf, and indeed, it worked like a charm. The issue always becomes, if you have something that needs encrypted - how you are safely storing the thing that decrypts it and securely passing it? Because of this, we’ve, more often than not, use a certificate to encrypt and decrypt things. Then, we just install the cert and grant the proper account(s) access to the cert, and bam, those accounts on only that system can decrypt whatever thing you need to decrypt.

A lot of that is over my head, are you saying the certificate is the only built in method and likely the best way to get it to run on another machine? And the cert needs to be installed on the other machine? Was hoping just a key file with the script would suffice. Either way I see my topic was marked as resolved. I guess the struggle will continue for me. Hopefully I can figure it out before giving up. Thanks for getting me past the first hurdle.

basically all you need is that key to unlock it

I cannot figure how to call for decrypt properly using a key, is it easy and I’m just slow? Just tried for a few hours giving up for not very frustrated with myself.

It’s basically going in reverse of the encryption process (ish):

# Key you use
$Key = (1..16)
# This gets the data into PS
$Data = Get-Content -Raw ".\scriptdataEncrypted.txt"
# This decrypts the data using your key that you encrypted it with
$Decrypt = ConvertTo-SecureString -String $Data -Key $Key
# This changes it from a secure string into plain text
$Code = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Decrypt))
# Output to make sure the code is what you expect it to be.
$Code
1 Like

I’m gonna try this when I can THANK YOU! Don’t know how that decrypt knows where to get the decryption key from, but I’ll try it anyway haha thanks! Because I want to decrypt on a different computer.

I changed your code to this using notes from all my testing and it not only worked… $Code wasn’t doing anything in PowerShell ISE when testing.

# Key you use

$Key = (1..16)
# This gets the data into PS
$Data = Get-Content -Raw ".\scriptdataEncrypted.txt"
# This decrypts the data using your key that you encrypted it with
$Decrypt = ConvertTo-SecureString -String $Data -Key $Key
# This changes it from a secure string into plain text
$Code = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Decrypt))
# Output to make sure the code is what you expect it to be.
#$Code
Invoke-Expression $Code

It also worked on my other computer… And after trying to figure out how I guess the key is in the body of scriptdataEncrypted.txt… But it works. Man you are an effin genius. What a beautiful birthday present. Thank you so very much. Now can you make me smarter?

@dotnVo and everyone here. Thank you for the teaching and guidance and patience! I’m not very gifted intellectually but I am stubborn and like to make things work even if not necessary. Nick, I tried to find a way to private message you as I wanted to share my unencrypted script with you. Then you can see what a complete Powershell noob had produced over a long period of learning and pain trying to make something fun. As much as I’ve learned I’m amazed at how bad I still am at understanding sytax and such. My new covid damaged brain doesn’t help. I made a fun PowerShell GUI utility and just wanted to see if I could get things I read about and came across working (like encryption and functions I thought I’d never figure out how to make work). Anyway, you are one smart and patient person. I really appreciate the teachings Sensei. Been a good birthday today.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.