Protect-CString to encrypt REG_BINARY in registry?

26 views
Skip to first unread message

payaso

unread,
Mar 16, 2021, 2:47:58 PM3/16/21
to carb...@googlegroups.com
I am trying to update the Username and Password for an Internet Printer Port (IPP) via the registry. I am not sure if this is possible with your Carbon script. When you configure the port from the printer management GUI it looks like it uses DPAPI to encrypt the data into a REG_BINARY in the registry under HKCU:\Printers\Inetnet Print Provider\Ports\<<PrinterURL>>/printer

This is what I was able to put together but am missing something because when I check the port via the GUI it username is not the correct string I enter.

Add-Type -AssemblyName System.Security
$String = "TestUser"
$stringBytes = [Text.Encoding]::Unicode.GetBytes( $String )
$scope = [Security.Cryptography.DataProtectionScope]::CurrentUser
$encryptedBytes = [Security.Cryptography.ProtectedData]::Protect( $stringBytes, $null, $scope )
$encryptedBytesBase64String = [Convert]::ToBase64String( $encryptedBytes )

$RegValue = $encryptedBytes
$Regpath = "HKCU:\Printers\Inetnet Print Provider\Ports\<<PRINTERURL>>/printer"
$PropertyType = "Binary"

New-ItemProperty -Path $Regpath -Name UserName -Value $RegValue -PropertyType $PropertyType -force

again not sure if your script has something that can help, I would appreciate it.

Aaron Jensen

unread,
Mar 16, 2021, 4:49:50 PM3/16/21
to payaso, carb...@googlegroups.com
$ciphertext = Protect-CString -String $password -ForUser
Set-CRegistryKeyValue -Path PATH -Name ‘UserName’ -Value ( [Convert]::FromBase64String($ciphertext))

Also try -ForComputer on Protect-CString. 


On Mar 16, 2021, at 11:48, payaso <paya...@gmail.com> wrote:


--
You received this message because you are subscribed to the Google Groups "Carbon" group.
To unsubscribe from this group and stop receiving emails from it, send an email to carbonps+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/carbonps/CACbH2QvWSxF0SacWQOrkYw9-iJoBcfZPWk7hVRV6XX2z_MdoUQ%40mail.gmail.com.

payaso

unread,
Mar 17, 2021, 5:24:52 PM3/17/21
to Aaron Jensen, carb...@googlegroups.com
Thank you. Unfortunately, it still didn't work.
I try both the -ForUser and -ForComputer
The command -Value ( [Convert]::FromBase64String($ciphertext)) didn't work also for me was giving me (Set-CRegistryKeyValue : A parameter cannot be found that matches parameter name 'Value')
So I tried with -Binary and it took the command but still doesn't work. 

image.png

If I open that port via the gui it shows the wrong User Name. 

Any suggestions?

Thank you, I truly appreciated the help.

Aaron Jensen

unread,
Mar 17, 2021, 8:00:04 PM3/17/21
to payaso, carb...@googlegroups.com
Do you need to encrypt the username? Try plaintext. 


On Mar 17, 2021, at 14:24, payaso <paya...@gmail.com> wrote:


Thank you. Unfortunately, it still didn't work.
I try both the -ForUser and -ForComputer
The command -Value ( [Convert]::FromBase64String($ciphertext)) didn't work also for me was giving me (Set-CRegistryKeyValue : A parameter cannot be found that matches parameter name 'Value')
So I tried with -Binary and it took the command but still doesn't work. 

<image.png>

Florian Busch

unread,
Jan 30, 2023, 10:04:28 AM1/30/23
to Carbon
hey everyone,

maybe this is not relevant anymore, but I had the same problem the last months, but I could figure out the problem and could also solve it.
First of all, thanks for this discussion and also the script on top, this was really helpful.

I compared the input from the script with the value which I get if I enter the data manually in the port configuration of the IPP printer.

My Test data:
UserName: printer
Passowrd: password

--- The Byte array for "printer" and "password" (my input value) is:
112 0 114 0 105 0 110 0 116 0 101 0 114 0
----
112 0 97 0 115 0 115 0 119 0 111 0 114 0 100 0

--- The Byte array for "printer" and "password"  (the value coming from the registry after "[Security.Cryptography.ProtectedData]::Unprotect"
112 0 114 0 105 0 110 0 116 0 101 0 114 0 0 0
----
112 0 97 0 115 0 115 0 119 0 111 0 114 0 100 0 0 0

The differences are the appending "zero". 

Then I have changed my script to append the zero

**************************************
$stringBytes = [Text.Encoding]::Unicode.GetBytes($username)
$addBytes = [System.Byte[]]::CreateInstance([System.Byte],2);
$newString = [byte[]]::new($stringBytes.Length + $addBytes.Length)
       
$stringBytes.CopyTo($newString, 0)
$addBytes.CopyTo($newString, $stringBytes.Length)
**************************************

The "$newString" variable looks now like the one coming from the registry for the username. You have to to this for the password as well.

If I now use "[Security.Cryptography.ProtectedData]::Protect" function and change the registry attribute, then it works.

It tooks me a lot of time. But maybe other need this information as well, so I want to share it here. 

- my script - It has not the best style. But it works.

***** script snippet *****

Add-Type -AssemblyName System.Security

class Helper {
    static [byte[]]CreateByteString([string]$inputString) {
        $stringBytes = [Text.Encoding]::Unicode.GetBytes( $inputString )
        $addBytes = [System.Byte[]]::CreateInstance([System.Byte],2);
        $newString = [byte[]]::new($stringBytes.Length + $addBytes.Length)
       
        $stringBytes.CopyTo($newString, 0)
        $addBytes.CopyTo($newString, $stringBytes.Length)
        return $newString
    }
}

$printerFullName = "https://myprinter.my.domain.eu"

$username = "printer"
$password = "password"

$stringBytesUser = [Helper]::CreateByteString($username);
$stringBytesPassword = [Helper]::CreateByteString($password);
$scope = [Security.Cryptography.DataProtectionScope]::CurrentUser
$regValueUser = [Security.Cryptography.ProtectedData]::Protect( $stringBytesUser, $null, $scope )
$regValuePassword = [Security.Cryptography.ProtectedData]::Protect( $stringBytesPassword, $null, $scope )

$versionCheck = Get-Item -LiteralPath "HKCU:\Printers\Inetnet Print Provider" -erroraction 'silentlycontinue';
if($versionCheck) {
    $RegInternetPath = "HKCU:\Printers\Inetnet Print Provider\";
    $RegPortsPath = "HKCU:\Printers\Inetnet Print Provider\Ports"
    $RegPrinterpath = "HKCU:\Printers\Inetnet Print Provider\Ports\"+$printerFullName
} else {
    $RegInternetPath = "HKCU:\Printers\Internet Print Provider\";
    $RegPortsPath = "HKCU:\Printers\Internet Print Provider\Ports"
    $RegPrinterpath = "HKCU:\Printers\Internet Print Provider\Ports\"+$printerFullName
}

$KeyPortExists = Get-Item -LiteralPath $RegPortsPath -erroraction 'silentlycontinue';
if(!($KeyPortExists)) {
    New-Item -Path $RegPortsPath;
}
$KeyPrinterExists = Get-Item -LiteralPath $RegPrinterpath -erroraction 'silentlycontinue';
if(!($KeyPrinterExists)) {
    $key = (Get-Item -LiteralPath $RegInternetPath).OpenSubKey("Ports", $true).CreateSubKey($printerFullName)
}

$PropertyType = "Binary"

New-ItemProperty -Path $RegPrinterpath -Name "UserName" -Value $regValueUser -PropertyType $PropertyType -Force | Out-Null
New-ItemProperty -Path $RegPrinterpath -Name "Password" -Value $regValuePassword -PropertyType $PropertyType -Force | Out-Null
New-ItemProperty -Path $RegPrinterpath -Name "Authentication" -Value "4" -PropertyType "DWord" -Force | Out-Null
Reply all
Reply to author
Forward
0 new messages