functions/Invoke-JS7Decrypt.ps1
function Invoke-JS7Decrypt { <# .SYNOPSIS Decrypts a value or file using an X.509 Private Key .DESCRIPTION The cmdlet decrypts results of a previous, asymmetric encryption, for details see https://kb.sos-berlin.com/display/JS7/JS7+-+Encryption+and+Decryption .PARAMETER Value Specifies the result that was returned by previous encryption. The result includes the following elements separated by spaces: * encrypted symmetric key * initialization vector * encrypted secret or path to encrypted file .PARAMETER File Specifies the location of the encrypted file that should be decrypted. .PARAMETER OutFile Specifies the location of the decrypted output file that should be created if the -File parameter is used. If the output file exists, then it will be overwritten. .PARAMETER Key Specifies the X.509 Certificate object holding the Private Key that should be used to decrypt an encrypted value or file. Certificate objects can be retrieved from a Windows certificate store using the Certificate's thumbprint like this: $cert = Get-ChildItem cert:\CurrentUser\my | Where { $_.Thumbprint -eq '2B03EA68F103E80D83228ABCF88A3B448CC8B257' } Only one of the parameters -Key or -KeyPath can be used. Decryption requires use of the -JavaLib parameter that points to the location of JS7 encryption libraries. .PARAMETER KeyPath Specifies the location of the Private Key file that is required to decrypt an encrypted value or file. Only one of the parameters -Key or -KeyPath can be used. Decryption requires use of the -JavaLib parameter that points to the location of JS7 encryption libraries. .PARAMETER KeyCredential Specifies a credential object holding the password that is optionally used to protect the Private Key. The password can be specified from a credential object in a number of ways, for example $credential = (New-Object -typename System.Management.Automation.PSCredential -ArgumentList 'key', ( 'jobscheduler' | ConvertTo-SecureString -AsPlainText -Force)) The 'key' credential name can be chosen arbitrarily, the 'jobscheduler' password as added to the credential object from a Secure String. .PARAMETER JavaHome Specifies the location to which Java is installed. Java is required to decrypt values or files. If the parameter is not specified then Java will be used from the value of the JAVA_HOME or PATH environment variables. .PARAMETER JavaOptions Specifies the Java options used when invoking Java for decryption using the -Key or -KeyPath parameters. Java options can be used for example to limit memory usage as with -JavaOptions "-Xmx32m". .PARAMETER JavaLib Specifies the location of the JS7 encryption libraries. The libraries ship with Agents and are available from the Agent's <agent-home>/lib directory. For decryption outside of JS7 products the JS7 encryption libraries are available for download. .OUTPUTS This cmdlet returns the decrypted secret. If the -File parameter is used then no output is returned and instead the decrypted file specified with the -OutFile parameter will created. .EXAMPLE Invoke-JS7Decrypt -Value $result -KeyPath C:\js7\js7.encryption\agent.key -KeyCredential (New-Object -typename System.Management.Automation.PSCredential -ArgumentList 'key', ( 'jobscheduler' | ConvertTo-SecureString -AsPlainText -Force)) -JavaLib C:\js7\js7.encryption\lib Returns the decrypted secret of a previous encryption operation. The -KeyPath argument specifies the location of the Private Key file. The -JavaLib argument specifies the location of the JS7 encryption libraries. .EXAMPLE Invoke-JS7Decrypt -Value $result -File /tmp/secret.txt.enc -OutFile /tmp/secret.txt.dec -KeyPath C:\js7\js7.encryption\agent.key -KeyCredential (New-Object -typename System.Management.Automation.PSCredential -ArgumentList 'key', ( 'jobscheduler' | ConvertTo-SecureString -AsPlainText -Force)) -JavaLib C:\js7\js7.encryption\lib Creates the decrypted file from a previous encryption operation. The -KeyPath argument specifies the location of the Private Key file. The -JavaLib argument specifies the location of the JS7 encryption libraries. .LINK about_JS7 #> [cmdletbinding(SupportsShouldProcess)] param ( [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] [string] $Value, [Parameter(Mandatory=$False,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] [string] $File, [Parameter(Mandatory=$False,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] [string] $OutFile, [Parameter(Mandatory=$False,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] [System.Security.Cryptography.X509Certificates.X509Certificate2] $Key, [Parameter(Mandatory=$False,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] [string] $KeyPath, [Parameter(Mandatory=$False,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] [System.Management.Automation.PSCredential] $KeyCredential, [Parameter(Mandatory=$False,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] [string] $JavaHome, [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] [string] $JavaLib, [Parameter(Mandatory=$False,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] [string] $JavaOptions ) Begin { Approve-JS7Command $MyInvocation.MyCommand $stopWatch = Start-JS7StopWatch if ( $File -and !$OutFile ) { throw "$($MyInvocation.MyCommand.Name): Use of the -File parameter requires to specify the -OutFile parameter." } if ( !$Key -and !$KeyPath ) { throw "$($MyInvocation.MyCommand.Name): One of the parameters -Key and -KeyPath must be used." } if ( $Key -and $KeyPath ) { throw "$($MyInvocation.MyCommand.Name): Only one of the parameters -Key or -KeyPath can be used." } } Process { try { $parts = $Value.split(' ') if ( $parts.count -ne 3 ) { throw "$($MyInvocation.MyCommand.Name): value does not include symmetric key, initialization vector and encrypted secret separated by space: -Value $Value" } $encryptedKey = $parts[0] $iv = $parts[1] $encryptedSecret = $parts[2] if ( $File -and !(Test-Path -Path $File -PathType leaf) ) { throw "$($MyInvocation.MyCommand.Name): file not found: -File $File" } if ( $Key ) { $tempPrivateKeyFile = New-TemporaryFile "-----BEGIN PRIVATE KEY-----" | Out-File $tempPrivateKeyFile [System.Convert]::ToBase64String($EncryptCertificate.RawData, [System.Base64FormattingOptions]::InsertLineBreaks) | Out-File $tempPrivateKeyFile -Append "-----END PRIVATE KEY-----" | Out-File $tempPrivateKeyFile -Append $KeyPath = $tempPrivateKeyFile } if ( $KeyPath -and !(Test-Path -Path $KeyPath -PathType leaf) ) { throw "$($MyInvocation.MyCommand.Name): file not found: -PrivateKeyPath $KeyPath" } if ( $JavaHome -and !(Test-Path -Path $JavaHome -PathType container) ) { throw "$($MyInvocation.MyCommand.Name): directory not found: -JavaHome $JavaHome" } if ( $JavaHome -and !(Get-Command "$($JavaHome)/bin/java" -ErrorAction silentlycontinue) ) { throw "$($MyInvocation.MyCommand.Name): Java binary ./bin/java not found from Java Home directory: -JavaHome $JavaHome" } if ( $KeyPath -and !$JavaHome ) { if ( $env:JAVA_HOME ) { $java = (Get-Command "$($env:JAVA_HOME)/bin/java" -ErrorAction silentlycontinue) } else { $java = (Get-Command "java" -ErrorAction silentlycontinue) if ( $java ) { $javaHomeDir = (Get-Item -Path $java.Source).Directory.Parent.Name [Environment]::SetEnvironmentVariable('JAVA_HOME', $javaHomeDir) } } if ( !$java ) { throw "$($MyInvocation.MyCommand.Name): Java home not specified and no JAVA_HOME environment variable in place: -JavaHome" } } if ( $KeyPath -and $JavaOptions ) { [Environment]::SetEnvironmentVariable('JAVA_OPTIONS', $JavaOptions) } if ( $KeyPath -and !$JavaLib ) { throw "$($MyInvocation.MyCommand.Name): parameter is required when using -PrivateKeyPath argument: -JavaLib" } if ( $JavaLib -and !(Test-Path -Path $JavaLib -PathType container) ) { throw "$($MyInvocation.MyCommand.Name): directory not found: -JavaLib $JavaLib" } } catch { if ( $tempPrivateKeyFile -and (Test-Path -Path $tempPrivateKeyFile -PathType leaf) ) { Remove-Item -Path $tempPrivateKeyFile -Force } throw $_.Exception | Format-List -Force | Out-String } Write-Debug ".. $($MyInvocation.MyCommand.Name):" } End { try { if ( [System.Environment]::OSVersion.Platform -match 'Win32NT' ) { $separator = ';' } else { $separator = ':' } $cmdArgList = @() $javaOptionsArgument = ( " $($env:JAVA_OPTIONS)" -split ' -') for( $i=0; $i -lt $javaOptionsArgument.length; $i++ ) { if ( $javaOptionsArgument[$i].Trim() ) { $cmdArgList += "-$($javaOptionsArgument[$i])" } } $cmdArgList += @( '-classpath', "$($JavaLib)/patches/*$($separator)$($JavaLib)/sos/*$($separator)$($JavaLib)/3rd-party/*$($separator)$($JavaLib)/stdout", "com.sos.commons.encryption.executable.Decrypt", "--key=$($KeyPath)", "--encrypted-key=$($encryptedKey)", "--iv=$($iv)") if ( $KeyCredential ) { $ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($KeyCredential.password) $password = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($ptr) $cmdArgList += @( "--key-password=$($password)") } if ( $File ) { $cmdPath = "$($env:JAVA_HOME)/bin/java" $cmdArgList += @( "--infile=$($File)", "--outfile=$($OutFile)" ) $result=(& $cmdPath $cmdArgList) | Out-String } else { $cmdPath = "$($env:JAVA_HOME)/bin/java" $cmdArgList += @( "--in=$($encryptedSecret)" ) $result=(& $cmdPath $cmdArgList) | Out-String } # remove trailing \n\r added from Out-String $result=(($result -replace "`r`$", '') -replace "`n`$", '') $result if ( $tempPrivateKeyFile -and (Test-Path -Path $tempPrivateKeyFile -PathType leaf) ) { Remove-Item -Path $tempPrivateKeyFile -Force } } catch { if ( $tempPrivateKeyFile -and (Test-Path -Path $tempPrivateKeyFile -PathType leaf) ) { Remove-Item -Path $tempPrivateKeyFile -Force } $message = $_.Exception | Format-List -Force | Out-String throw "Exception occurred in line number $($_.InvocationInfo.ScriptLineNumber)`n$($message)" } Trace-JS7StopWatch -CommandName $MyInvocation.MyCommand.Name -StopWatch $stopWatch Update-JS7Session } } |