<# .SYNOPSIS Digitally signs JS7 workflows and related files for secure deployment in a JS7 environment operated for security level "high" .DESCRIPTION JS7 can be operated in environments for security level "high". This includes to have workflows digitally signed outside of JOC Cockpit in order not to have the private key within reach of JOC Cockpit. Digital signing includes * to export scheduling objects with the option "for signing". This will create a .tar.gz/.zip archive file holding related scheduling objects which is available with the user's computer that connected to JOC Cockpit ** to optionally transfer the export .tar.gz/.zip archive file to a secure machine * to digitally sign exported workflow files and job resouce filess ** to extract the .tar.gz/.zip archive file ** to create signature files, for example *.workflow.json.sig for workflow files *.workflow.json * to create or update a .tar.gz/.zip archive file that includes both the original workflow files and newly created signature files * to import and to deploy the .tar.gz/.zip archive file that holds the original workflows and the signature files ** JOC Cockpit offers the operation to "Import and Deploy" .tar.gz/.zip archives from a single step The Sign-JS7Workflow.ps1 script can be used with PowerShell 5.1, 7.x on Liux and Windows. .PARAMETER File Specifies the path to a *.workflow.json or *.jobresource.json file to be signed. If this argument is omitted then the -Dir argument will be used to look up workflow files. .PARAMETER Dir Specifies the path to a directory holding *.workflow.json or *.jobresource.json files to be signed. Any sub-directories will be traversed recursively. By default the current directory is used. .PARAMETER Keystore Specifies the path to a keystore file that holds the private key and certificate used for signing. The argument can be populated from the JS7_SIGN_KEYSTORE environment variable. Only one of the -Keystore and -Key arguments can be used. If both arguments are omitted then the Windows Certificate Store will be used. .PARAMETER Key Specifies the path to the key file that holds the private key used for signing. The argument can be populated from the JS7_SIGN_KEY environment variable. Only one of the -Key and -Keystore arguments can be used. If both arguments are omitted then the Windows Certificate Store will be used. .PARAMETER Cert Specifies the path to the certificate file used for signing. The argument can be populated from the JS7_SIGN_CERT environment variable. Only one of the -Cert and -Keystore arguments can be used. If both arguments are omitted then the Windows Certificate Store will be used. .PARAMETER Credentials Optionally specifies a PowerShell credentials object that holds the password used for access to the key file or keystore. .PARAMETER AskForCredentials Optionally prompts for user input of the password used to acess the key file or keystore. The alias argument -P is available. .PARAMETER Thumbprint Optionally specifies the thumbprint of the code signing certificate to be used. A thumbprint identifies a certificate. It is required to specify the thumbprint if more than one code signing certificate is available from the indicated keystore or Windows Certificate Store. .EXAMPLE ./Sign-JS7Workflow.ps1 -Keystore /mnt/releases/certificates/release-signing/release-signing.p12 -P Signs all *.workflow.json and *.jobresource.json files in the current directory and sub-directories using the code signing certificate from the indicated keystore asking for its password .EXAMPLE ./Sign-JS7Workflow.ps1 -Key ./js7.key -Cert ./js7.crt Signs all *.workflow.json and *.jobresource.json files in the current directory and sub-directories using the code signing certificate from the indicated keystore .EXAMPLE ./Sign-JS7Workflow.ps1 Signs all *.workflow.json and *.jobresource.json files in the current directory and sub-directories using the code signing certificate available with the Windows Certificate Store .EXAMPLE ./Sign-JS7Workflow.ps1 -Dir C:\some\folder Signs the all *.workflow.json and *.jobresource.json files in the indicated directory and sub-directories using the code signing certificate available with the Windows Certificate Store .EXAMPLE ./Sign-JS7Workflow.ps1 -File ./test.workflow.json Signs the indicated file using the code signing certificate available with the Windows Certificate Store .EXAMPLE ./Sign-JS7Workflow.ps1 -File ./test.workflow.json -Thumbprint 'EF64BFA6BC3EF6585F64E3DEC1CD67334DDBDF3F' Signs the indicated workflow file using the code signing certificate available with the Windows Certificate Store that is identified by the thumbprint .EXAMPLE ./Sign-JS7Workflow.ps1 -File ./test.workflow.json -Thumbprint '2B03EA68F103E80D83228ABCF88A3B448CC8B257' Signs the indicated workflow file using the code signing certificate available with the Windows Certificate store that is identified by the thumbprint .EXAMPLE ./Sign-JS7Workflow.ps1 -File ./test.workflow.json -Keystore P:\releases\certificates\release-signing\release-signing.p12 -AskForCredentials Signs the indicated workflow file using the code signing certificate available from the indicated keystore #> [cmdletbinding(SupportsShouldProcess)] param ( [Parameter(Mandatory=$False,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] [string] $File, [Parameter(Mandatory=$False,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] [string] $Dir = '.', [Parameter(Mandatory=$False,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] [string] $Keystore=$env:JS7_SIGN_KEYSTORE, [Parameter(Mandatory=$False,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] [string] $Key=$env:JS7_SIGN_KEY, [Parameter(Mandatory=$False,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] [string] $Cert=$env:JS7_SIGN_CERT, [Parameter(Mandatory=$False,ValueFromPipeline=$False,ValueFromPipelinebyPropertyName=$True)] [System.Management.Automation.PSCredential] $Credentials, [Parameter(Mandatory=$False,ValueFromPipeline=$False,ValueFromPipelinebyPropertyName=$True)] [Alias('P')] [switch] $AskForCredentials, [Parameter(Mandatory=$False,ValueFromPipeline=$False,ValueFromPipelinebyPropertyName=$True)] [string] $Thumbprint, [Parameter(Mandatory=$False,ValueFromPipeline=$False,ValueFromPipelinebyPropertyName=$True)] [string] $LogDir, [Parameter(Mandatory=$False,ValueFromPipeline=$False,ValueFromPipelinebyPropertyName=$True)] [switch] $ShowLogs ) Begin { switch ([System.Environment]::OSVersion.Platform) { 'Win32NT' { New-Variable -Option Constant -Name IsWindows -Value $True -ErrorAction SilentlyContinue New-Variable -Option Constant -Name IsLinux -Value $false -ErrorAction SilentlyContinue New-Variable -Option Constant -Name IsMacOs -Value $false -ErrorAction SilentlyContinue } } # default variables $script:ShowLogs = $ShowLogs $script:hostname = if ( $env:COMPUTERNAME ) { $env:COMPUTERNAME } else { $env:HOSTNAME } $script:startTime = Get-Date $script:logFile = $null $script:tempKeystore = $null $script:tempCert = $null } Process { # inline functions function Out-LogInfo( [string] $Message ) { if ( $logFile ) { $Message | Out-File $logFile -Append } if ( !$ShowLogs ) { Write-Output $Message } } function Out-LogError( [string] $Message ) { if ( $logFile ) { "[ERROR] $($Message)" | Out-File $logFile -Append } if ( !$ShowLogs ) { Write-Error $Message } } function Out-LogVerbose( [string] $Message ) { if ( $logFile ) { "[VERBOSE] $($Message)" | Out-File $logFile -Append } if ( !$ShowLogs ) { Write-Verbose $Message } } function Out-LogDebug( [string] $Message ) { if ( $logFile ) { "[DEBUG] $($Message)" | Out-File $logFile -Append } if ( !$ShowLogs ) { Write-Debug $Message } } function Test-Arguments() { if ( !$Dir -and !$File ) { Out-LogError "Use -Dir for a directory holding files or use -File for a single file to be signed" return 1 } if ( $Dir -and $File ) { if ( $Dir -eq '.' ) { $script:Dir = $null } else { Out-LogError "Only one of -Dir for a directory holding files or -File for a single file to be signed can be used" return 1 } } if ( $Keystore -and !(Test-Path -Path $Keystore -PathType leaf) ) { Out-LogError "Keystore not found: -Keystore $($Keystore)" return 1 } if ( $Key -and !(Test-Path -Path $Key -PathType leaf) ) { Out-LogError "Key file not found: -Key $($Key)" return 1 } if ( $Cert -and !(Test-Path -Path $Cert -PathType leaf) ) { Out-LogError "Certificate file not found: -Cert $($Cert)" return 1 } if ( $LogDir -and !(Test-Path -Path $LogDir -PathType container) ) { Out-LogError "Log directory not found: -LogDir $($LogDir)" return 1 } return 0 } function Cleanup() { if ( $File -and (Test-Path -Path "$($File).pub" -PathType leaf) ) { Remove-Item -Path "$($File).pub" -Force } if ( $File -and (Test-Path -Path "$($File).sig.bin" -PathType leaf) ) { Remove-Item -Path "$($File).sig.bin" -Force } } function Final() { if ( $TempKeystore -and (Test-Path -Path $TempKeystore -PathType leaf) ) { Remove-Item -Path $TempKeystore -Force } if ( $TempCert -and (Test-Path -Path $TempCert -PathType leaf) ) { Remove-Item -Path $TempCert -Force } } function Get-SigningCertificate( [string] $Thumbprint ) { if ( $Thumbprint ) { $cert = Get-ChildItem cert:\CurrentUser\my -CodeSigningCert | Where-Object { $_.Thumbprint -eq $Thumbprint } } else { $cert = Get-ChildItem cert:\CurrentUser\my -CodeSigningCert if ( $cert.count -gt 1 ) { throw "More than one code signing certificate found, use: -Thumbprint $($Thumbprint)" } } $cert } function Add-WorkflowSignature( [string] $File, [string] $KeyStore, [string] $Key, [string] $Cert, [System.Management.Automation.PSCredential] $Credentials ) { Out-LogInfo ".... signing file: $($File)" try { if ( ($Key -or $Keystore) -and $Credentials ) { $ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode( $Credentials.Password ) $result = [System.Runtime.InteropServices.Marshal]::PtrToStringUni( $ptr ) } # step 1: create signature from file if ( $Key ) { Out-LogVerbose ".... running: openssl dgst -sha256 -sign `"$($Key)`" -passin pass:`"********`" -out `"$($File).sig.bin`" `"$($File)`"" if ( $isWindows ) { cmd.exe /C "openssl dgst -sha256 -sign `"$($Key)`" -passin pass:`"$($result)`" -out `"$($File).sig.bin`" `"$($File)`"" } else { sh -c "openssl dgst -sha256 -sign '$($Key)' -passin pass:'$($result)' -out '$($File).sig.bin' '$($File)'" } } elseif ( $Keystore ) { Out-LogVerbose ".... running: openssl dgst -sha256 -sign `"$($Keystore)`" -keyform P12 -passin pass:`"********`" -out `"$($File).sig.bin`" `"$($File)`"" if ( $isWindows ) { cmd.exe /C "openssl dgst -sha256 -sign `"$($Keystore)`" -keyform P12 -passin pass:`"$($result)`" -out `"$($File).sig.bin`" `"$($File)`"" } else { sh -c "openssl dgst -sha256 -sign '$($Keystore)' -keyform P12 -passin pass:'$($result)' -out '$($File).sig.bin' '$($File)'" } } else { # works for exportable private keys only $script:tempKeystore = New-TemporaryFile Export-PfxCertificate -Cert cert:\CurrentUser\my -Force -FilePath $tempKeystore -Password $Credentials.Password Out-LogVerbose ".... running: openssl dgst -sha256 -sign `"$($tempKeystore)`" -keyform P12 -passin pass:`"********`" -out `"$($File).sig.bin`" `"$($File)`"" if ( $isWindows ) { cmd.exe /C "openssl dgst -sha256 -sign `"$($tempKeystore)`" -keyform P12 -passin pass:`"$($result)`" -out `"$($File).sig.bin`" `"$($File)`"" } else { sh -c "openssl dgst -sha256 -sign '$($tempKeystore)' -keyform P12 -passin pass:'$($result)' -out '$($File).sig.bin' '$($File)'" } } if ( $LASTEXITCODE ) { throw "Error running openssl to create signature file" } # step 2: convert signature to base64 Out-LogVerbose ".... running: openssl base64 -in `"$($File).sig.bin`" -out `"$($File).sig`"" if ( $isWindows ) { cmd.exe /C "openssl base64 -in `"$($File).sig.bin`" -out `"$($File).sig`"" } else { sh -c "openssl base64 -in '$($File).sig.bin' -out '$($File).sig'" } # step 3: prepare certificate file if ( !$Cert ) { $tempCert = New-TemporaryFile if ( $Keystore ) { Out-LogVerbose ".... running: openssl pkcs12 -in `"$($Keystore)`" -passin pass:`"********`" -passout pass:`"********`" -nokeys -out `"$($tempCert)`"" if ( $isWindows ) { cmd.exe /C "openssl pkcs12 -in `"$($Keystore)`" -passin pass:`"$($result)`" -passout pass:`"$($result)`" -nokeys -out `"$($tempCert)`"" | Out-Null } else { sh -c "openssl pkcs12 -in '$($Keystore)' -passin pass:'$($result)' -passout pass:'$($result)' -nokeys -out '$($tempCert)'" | Out-Null } } elseif ( $Key ) { Out-LogVerbose ".... running: openssl pkcs12 -in `"$($Key)`" -passin pass:`"********`" -passout pass:`"********`" -nokeys -out `"$($tempCert)`"" if ( $isWindows ) { cmd.exe /C "openssl pkcs12 -in `"$($Key)`" -passin pass:`"$($result)`" -passout pass:`"$($result)`" -nokeys -out `"$($tempCert)`"" | Out-Null } else { sh -c "openssl pkcs12 -in '$($Key)' -passin pass:'$($result)' -passout pass:'$($result)' -nokeys -out '$($tempCert)'" | Out-Null } } if ( $LASTEXITCODE ) { throw "Error running openssl to create certificate file" } } else { $tempCert = $Cert } # step 4: verify signature from public key Out-LogVerbose ".... running: openssl x509 -in `"$($tempCert)`" -pubkey -noout > `"$($File).pub`"" if ( $isWindows ) { cmd.exe /C "openssl x509 -in `"$($tempCert)`" -pubkey -noout > `"$($File).pub`"" } else { sh -c "openssl x509 -in '$($tempCert)' -pubkey -noout > '$($File).pub'" } if ( $LASTEXITCODE ) { throw "Error running openssl to create public key file" } Out-LogVerbose ".... running openssl dgst -sha256 -verify `"$($File).pub`" -signature `"$($File).sig.bin`" `"$($File)`"" if ( $isWindows ) { cmd.exe /C "openssl dgst -sha256 -verify `"$($File).pub`" -signature `"$($File).sig.bin`" `"$($File)`"" } else { sh -c "openssl dgst -sha256 -verify '$($File).pub' -signature '$($File).sig.bin' '$($File)'" } if ( $LASTEXITCODE ) { throw "Error running openssl to verify signatue file" } Cleanup } catch { Cleanup $message = $_.Exception | Format-List -Force | Out-String Out-LogError "Exception occurred in line number $($_.InvocationInfo.ScriptLineNumber)`n$($message)" } } # ------------------------------ # Main # ------------------------------ if ( Test-Arguments -ne 0 ) { return 1 } if ( $AskForCredentials ) { Write-Output '* ***************************************************** *' Write-Output '* JS7 Workflow Signing *' Write-Output '* enter password for access to key file / keystore *' Write-Output '* ***************************************************** *' [SecureString] $password = Read-Host -Prompt 'Enter password ' -AsSecureString if ( $password ) { $script:Credentials = ( New-Object -typename System.Management.Automation.PSCredential -ArgumentList 'password', $password ) $password = $null } } if ( $LogDir ) { $logFile = "$($LogDir)/js7_sign_workflow.$($hostname).$(Get-Date $startTime -Format 'yyyy-MM-ddTHH-mm-ss').log" while ( Test-Path -Path $logFile -PathType leaf ) { Start-Sleep -Seconds 1 $script:startTime = Get-Date $script:logFile = "$($LogDir)/js7_sign_workflow.$($hostname).$(Get-Date $startTime -Format 'yyyy-MM-ddTHH-mm-ss').log" } New-Item $logFile -ItemType file | Out-Null } Out-LogInfo "-- begin of log --------------" # Get the command name $commandName = $PSCmdlet.MyInvocation.InvocationName # Get the list of parameters for the command $parameterList = (Get-Command -Name $commandName).Parameters # Grab each parameter value, using Get-Variable foreach ($parameter in $parameterList.Keys) { $variable = Get-Variable -Name $parameter -ErrorAction SilentlyContinue if ( $variable.value ) { Out-LogInfo ".. Argument: $($variable.name) = $($variable.value)" } } Out-LogInfo "-- begin of output -----------" try { # works for exportable private keys only if ( !$Key -and !$Keystore ) { $script:tempKeystore = New-TemporaryFile $script:Keystore = $tempKeystore Get-SigningCertificate -Thumbprint $Thumbprint | Export-PfxCertificate -FilePath $tempKeystore -Password $Credentials.Password -ChainOption BuildChain } if ( $File ) { Add-WorkflowSignature -File $File -Keystore $Keystore -Key $Key -Cert $Cert -Credentials $Credentials } else { Get-ChildItem -Path $Dir\ -File -Recurse -Include ('*.workflow.json','*.jobresource.json') | ForEach-Object { Add-WorkflowSignature -File $_.FullName $Keystore -Key $Key -Cert $Cert -Credentials $Credentials } } Final } catch { Final $message = $_.Exception | Format-List -Force | Out-String Out-LogError "Exception occurred in line number $($_.InvocationInfo.ScriptLineNumber)`n$($message)" } } End { Out-LogInfo ".. signing completed" } # SIG # Begin signature block # MIInfwYJKoZIhvcNAQcCoIIncDCCJ2wCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUM2xeYKMV8BEL6zjwcSNiTO+m # OnGggiCOMIIFbzCCBFegAwIBAgIQSPyTtGBVlI02p8mKidaUFjANBgkqhkiG9w0B # AQwFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVy # MRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEh # MB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTIxMDUyNTAwMDAw # MFoXDTI4MTIzMTIzNTk1OVowVjELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1NlY3Rp # Z28gTGltaXRlZDEtMCsGA1UEAxMkU2VjdGlnbyBQdWJsaWMgQ29kZSBTaWduaW5n # IFJvb3QgUjQ2MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjeeUEiIE # JHQu/xYjApKKtq42haxH1CORKz7cfeIxoFFvrISR41KKteKW3tCHYySJiv/vEpM7 # fbu2ir29BX8nm2tl06UMabG8STma8W1uquSggyfamg0rUOlLW7O4ZDakfko9qXGr # YbNzszwLDO/bM1flvjQ345cbXf0fEj2CA3bm+z9m0pQxafptszSswXp43JJQ8mTH # qi0Eq8Nq6uAvp6fcbtfo/9ohq0C/ue4NnsbZnpnvxt4fqQx2sycgoda6/YDnAdLv # 64IplXCN/7sVz/7RDzaiLk8ykHRGa0c1E3cFM09jLrgt4b9lpwRrGNhx+swI8m2J # mRCxrds+LOSqGLDGBwF1Z95t6WNjHjZ/aYm+qkU+blpfj6Fby50whjDoA7NAxg0P # OM1nqFOI+rgwZfpvx+cdsYN0aT6sxGg7seZnM5q2COCABUhA7vaCZEao9XOwBpXy # bGWfv1VbHJxXGsd4RnxwqpQbghesh+m2yQ6BHEDWFhcp/FycGCvqRfXvvdVnTyhe # Be6QTHrnxvTQ/PrNPjJGEyA2igTqt6oHRpwNkzoJZplYXCmjuQymMDg80EY2NXyc # uu7D1fkKdvp+BRtAypI16dV60bV/AK6pkKrFfwGcELEW/MxuGNxvYv6mUKe4e7id # FT/+IAx1yCJaE5UZkADpGtXChvHjjuxf9OUCAwEAAaOCARIwggEOMB8GA1UdIwQY # MBaAFKARCiM+lvEH7OKvKe+CpX/QMKS0MB0GA1UdDgQWBBQy65Ka/zWWSC8oQEJw # IDaRXBeF5jAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zATBgNVHSUE # DDAKBggrBgEFBQcDAzAbBgNVHSAEFDASMAYGBFUdIAAwCAYGZ4EMAQQBMEMGA1Ud # HwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0FBQUNlcnRpZmlj # YXRlU2VydmljZXMuY3JsMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYYaHR0 # cDovL29jc3AuY29tb2RvY2EuY29tMA0GCSqGSIb3DQEBDAUAA4IBAQASv6Hvi3Sa # mES4aUa1qyQKDKSKZ7g6gb9Fin1SB6iNH04hhTmja14tIIa/ELiueTtTzbT72ES+ # BtlcY2fUQBaHRIZyKtYyFfUSg8L54V0RQGf2QidyxSPiAjgaTCDi2wH3zUZPJqJ8 # ZsBRNraJAlTH/Fj7bADu/pimLpWhDFMpH2/YGaZPnvesCepdgsaLr4CnvYFIUoQx # 2jLsFeSmTD1sOXPUC4U5IOCFGmjhp0g4qdE2JXfBjRkWxYhMZn0vY86Y6GnfrDyo # XZ3JHFuu2PMvdM+4fvbXg50RlmKarkUT2n/cR/vfw1Kf5gZV6Z2M8jpiUbzsJA8p # 1FiAhORFe1rYMIIGHDCCBASgAwIBAgIQM9cIqJFAUxnipbvTObmtbjANBgkqhkiG # 9w0BAQwFADBWMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVk # MS0wKwYDVQQDEyRTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBSNDYw # HhcNMjEwMzIyMDAwMDAwWhcNMzYwMzIxMjM1OTU5WjBXMQswCQYDVQQGEwJHQjEY # MBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS4wLAYDVQQDEyVTZWN0aWdvIFB1Ymxp # YyBDb2RlIFNpZ25pbmcgQ0EgRVYgUjM2MIIBojANBgkqhkiG9w0BAQEFAAOCAY8A # MIIBigKCAYEAu9H+HrdCW3j1kKeuLIPxjSHTMIaFe9/TzdkWS6yFxbsBz+KMKBFy # BHYsgcWrEnpASsUQ6IEUORtfTwf2MDAwfzUl5cBzPUAJlOio+Os5C1XVtgyLHif4 # 3j4iwb/vZe5z7mXdKN27H32bMn+3mVUXqrJJqDwQajrDIbKZqEPXO4KoGWG1Pmpa # Xbi8nhPQCp71W49pOGjqpR9byiPuC+280B5DQ26wU4zCcypEMW6+j7jGAva7ggQV # eQxSIOiYJ3Fh7y/k+AL7M1m19MNV59/2CCKuttEJWewBn3OJt0NP1fLZvVZZCd23 # F/bEdIC6h0asBtvbBA3VTrrujAk0GZUb5nATBCXfj7jXhDOMbKYM62i6lU98ROjU # aY0lecMh8TV3+E+2ElWV0FboGALV7nnIhqFp8RtOlBNqB2Lw0GuZpZdQnhwzoR7u # YYsFaByO9e4mkIPW/nGFp5ryDRQ+NrUSrXd1esznRjZqkFPLxpRx3gc6IfnWMmfg # nG5UhqBkoIPLAgMBAAGjggFjMIIBXzAfBgNVHSMEGDAWgBQy65Ka/zWWSC8oQEJw # IDaRXBeF5jAdBgNVHQ4EFgQUgTKSQSsozUbIxKLGKjkS7EipPxQwDgYDVR0PAQH/ # BAQDAgGGMBIGA1UdEwEB/wQIMAYBAf8CAQAwEwYDVR0lBAwwCgYIKwYBBQUHAwMw # GgYDVR0gBBMwETAGBgRVHSAAMAcGBWeBDAEDMEsGA1UdHwREMEIwQKA+oDyGOmh0 # dHA6Ly9jcmwuc2VjdGlnby5jb20vU2VjdGlnb1B1YmxpY0NvZGVTaWduaW5nUm9v # dFI0Ni5jcmwwewYIKwYBBQUHAQEEbzBtMEYGCCsGAQUFBzAChjpodHRwOi8vY3J0 # LnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2RlU2lnbmluZ1Jvb3RSNDYucDdj # MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0aWdvLmNvbTANBgkqhkiG9w0B # AQwFAAOCAgEAXzas+/n2cloUt/ALHd7Y/ZcB0v0B7pkthuj2t/A5/9aBSlqnQkoK # LRWd5pT9xWlKstdL8RYSTPa+kGZliy101KsI92oRAwh3fL5p4bDbnySJA9beXKTg # sta0z+M41bltzCfWzmQR6BBydtP54OksielJ07OXlgYK4fYKyEGakV2B2DZ3mMqA # QZeo+JE/Y5+qzVRUS4Dq9Rdm05Rx/Z79RzHj6RqGHdO+INI/sVJfspO9jJUJmHKP # lQH0mEOlSvsUJqqdNr9ysPzcvYQN7O00qF6VKzgWYwV12fYxLhVr4pSyKtJ0NbWY # mqP++CsvthdLJ2xa5rl2XtqG3atk1mrqgxiIGzGC9YizlCXAIS8IaQLjTLtMKhEw # 64F5BuFBlSrUIPYLk+R8dgydHSZrX4QB9iqZza/ex/DkGKJOmy8qDGamknUmvtlA # NRNvrqY3GnrorRxRYwcqVgZs7X4Y9uPsZHOmbQg2i68Pma51axcrwk1qw1FGQVbp # j8KN/xNxm9rtntOfq+VFphLFFFpSQZejBgAIxeYc6ieCPDvb5kbE7y0ANRPNNn2d # 5aonCAXMzsA2DksZT9Bjmm2/xSlTMSLbdVB3htDy+GruawYbPoUjK5fIfnqZQQzd # WH8OqMMSPTo1m+CdLIwXgVREqHodmJ2Wf1lYplRl/1FCC/hH68/45b8wggbsMIIE # 1KADAgECAhAwD2+s3WaYdHypRjaneC25MA0GCSqGSIb3DQEBDAUAMIGIMQswCQYD # VQQGEwJVUzETMBEGA1UECBMKTmV3IEplcnNleTEUMBIGA1UEBxMLSmVyc2V5IENp # dHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEuMCwGA1UEAxMlVVNF # UlRydXN0IFJTQSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xOTA1MDIwMDAw # MDBaFw0zODAxMTgyMzU5NTlaMH0xCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVh # dGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGDAWBgNVBAoTD1NlY3Rp # Z28gTGltaXRlZDElMCMGA1UEAxMcU2VjdGlnbyBSU0EgVGltZSBTdGFtcGluZyBD # QTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMgbAa/ZLH6ImX0BmD8g # kL2cgCFUk7nPoD5T77NawHbWGgSlzkeDtevEzEk0y/NFZbn5p2QWJgn71TJSeS7J # Y8ITm7aGPwEFkmZvIavVcRB5h/RGKs3EWsnb111JTXJWD9zJ41OYOioe/M5YSdO/ # 8zm7uaQjQqzQFcN/nqJc1zjxFrJw06PE37PFcqwuCnf8DZRSt/wflXMkPQEovA8N # T7ORAY5unSd1VdEXOzQhe5cBlK9/gM/REQpXhMl/VuC9RpyCvpSdv7QgsGB+uE31 # DT/b0OqFjIpWcdEtlEzIjDzTFKKcvSb/01Mgx2Bpm1gKVPQF5/0xrPnIhRfHuCkZ # pCkvRuPd25Ffnz82Pg4wZytGtzWvlr7aTGDMqLufDRTUGMQwmHSCIc9iVrUhcxIe # /arKCFiHd6QV6xlV/9A5VC0m7kUaOm/N14Tw1/AoxU9kgwLU++Le8bwCKPRt2ieK # BtKWh97oaw7wW33pdmmTIBxKlyx3GSuTlZicl57rjsF4VsZEJd8GEpoGLZ8DXv2D # olNnyrH6jaFkyYiSWcuoRsDJ8qb/fVfbEnb6ikEk1Bv8cqUUotStQxykSYtBORQD # Hin6G6UirqXDTYLQjdprt9v3GEBXc/Bxo/tKfUU2wfeNgvq5yQ1TgH36tjlYMu9v # GFCJ10+dM70atZ2h3pVBeqeDAgMBAAGjggFaMIIBVjAfBgNVHSMEGDAWgBRTeb9a # qitKz1SA4dibwJ3ysgNmyzAdBgNVHQ4EFgQUGqH4YRkgD8NBd0UojtE1XwYSBFUw # DgYDVR0PAQH/BAQDAgGGMBIGA1UdEwEB/wQIMAYBAf8CAQAwEwYDVR0lBAwwCgYI # KwYBBQUHAwgwEQYDVR0gBAowCDAGBgRVHSAAMFAGA1UdHwRJMEcwRaBDoEGGP2h0 # dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VU0VSVHJ1c3RSU0FDZXJ0aWZpY2F0aW9u # QXV0aG9yaXR5LmNybDB2BggrBgEFBQcBAQRqMGgwPwYIKwYBBQUHMAKGM2h0dHA6 # Ly9jcnQudXNlcnRydXN0LmNvbS9VU0VSVHJ1c3RSU0FBZGRUcnVzdENBLmNydDAl # BggrBgEFBQcwAYYZaHR0cDovL29jc3AudXNlcnRydXN0LmNvbTANBgkqhkiG9w0B # AQwFAAOCAgEAbVSBpTNdFuG1U4GRdd8DejILLSWEEbKw2yp9KgX1vDsn9FqguUlZ # kClsYcu1UNviffmfAO9Aw63T4uRW+VhBz/FC5RB9/7B0H4/GXAn5M17qoBwmWFzz # tBEP1dXD4rzVWHi/SHbhRGdtj7BDEA+N5Pk4Yr8TAcWFo0zFzLJTMJWk1vSWVgi4 # zVx/AZa+clJqO0I3fBZ4OZOTlJux3LJtQW1nzclvkD1/RXLBGyPWwlWEZuSzxWYG # 9vPWS16toytCiiGS/qhvWiVwYoFzY16gu9jc10rTPa+DBjgSHSSHLeT8AtY+dwS8 # BDa153fLnC6NIxi5o8JHHfBd1qFzVwVomqfJN2Udvuq82EKDQwWli6YJ/9GhlKZO # qj0J9QVst9JkWtgqIsJLnfE5XkzeSD2bNJaaCV+O/fexUpHOP4n2HKG1qXUfcb9b # Q11lPVCBbqvw0NP8srMftpmWJvQ8eYtcZMzN7iea5aDADHKHwW5NWtMe6vBE5jJv # HOsXTpTDeGUgOw9Bqh/poUGd/rG4oGUqNODeqPk85sEwu8CgYyz8XBYAqNDEf+oR # nR4GxqZtMl20OAkrSQeq/eww2vGnL8+3/frQo4TZJ577AWZ3uVYQ4SBuxq6x+ba6 # yDVdM3aO8XwgDCp3rrWiAoa6Ke60WgCxjKvj+QrJVF3UuWp0nr1Irpgwggb1MIIE # 3aADAgECAhA5TCXhfKBtJ6hl4jvZHSLUMA0GCSqGSIb3DQEBDAUAMH0xCzAJBgNV # BAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1Nh # bGZvcmQxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDElMCMGA1UEAxMcU2VjdGln # byBSU0EgVGltZSBTdGFtcGluZyBDQTAeFw0yMzA1MDMwMDAwMDBaFw0zNDA4MDIy # MzU5NTlaMGoxCzAJBgNVBAYTAkdCMRMwEQYDVQQIEwpNYW5jaGVzdGVyMRgwFgYD # VQQKEw9TZWN0aWdvIExpbWl0ZWQxLDAqBgNVBAMMI1NlY3RpZ28gUlNBIFRpbWUg # U3RhbXBpbmcgU2lnbmVyICM0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC # AgEApJMoUkvPJ4d2pCkcmTjA5w7U0RzsaMsBZOSKzXewcWWCvJ/8i7u7lZj7JRGO # WogJZhEUWLK6Ilvm9jLxXS3AeqIO4OBWZO2h5YEgciBkQWzHwwj6831d7yGawn7X # LMO6EZge/NMgCEKzX79/iFgyqzCz2Ix6lkoZE1ys/Oer6RwWLrCwOJVKz4VQq2cD # JaG7OOkPb6lampEoEzW5H/M94STIa7GZ6A3vu03lPYxUA5HQ/C3PVTM4egkcB9Ei # 4GOGp7790oNzEhSbmkwJRr00vOFLUHty4Fv9GbsfPGoZe267LUQqvjxMzKyKBJPG # V4agczYrgZf6G5t+iIfYUnmJ/m53N9e7UJ/6GCVPE/JefKmxIFopq6NCh3fg9EwC # SN1YpVOmo6DtGZZlFSnF7TMwJeaWg4Ga9mBmkFgHgM1Cdaz7tJHQxd0BQGq2qBDu # 9o16t551r9OlSxihDJ9XsF4lR5F0zXUS0Zxv5F4Nm+x1Ju7+0/WSL1KF6NpEUSqi # zADKh2ZDoxsA76K1lp1irScL8htKycOUQjeIIISoh67DuiNye/hU7/hrJ7CF9adD # hdgrOXTbWncC0aT69c2cPcwfrlHQe2zYHS0RQlNxdMLlNaotUhLZJc/w09CRQxLX # Mn2YbON3Qcj/HyRU726txj5Ve/Fchzpk8WBLBU/vuS/sCRMCAwEAAaOCAYIwggF+ # MB8GA1UdIwQYMBaAFBqh+GEZIA/DQXdFKI7RNV8GEgRVMB0GA1UdDgQWBBQDDzHI # kSqTvWPz0V1NpDQP0pUBGDAOBgNVHQ8BAf8EBAMCBsAwDAYDVR0TAQH/BAIwADAW # BgNVHSUBAf8EDDAKBggrBgEFBQcDCDBKBgNVHSAEQzBBMDUGDCsGAQQBsjEBAgED # CDAlMCMGCCsGAQUFBwIBFhdodHRwczovL3NlY3RpZ28uY29tL0NQUzAIBgZngQwB # BAIwRAYDVR0fBD0wOzA5oDegNYYzaHR0cDovL2NybC5zZWN0aWdvLmNvbS9TZWN0 # aWdvUlNBVGltZVN0YW1waW5nQ0EuY3JsMHQGCCsGAQUFBwEBBGgwZjA/BggrBgEF # BQcwAoYzaHR0cDovL2NydC5zZWN0aWdvLmNvbS9TZWN0aWdvUlNBVGltZVN0YW1w # aW5nQ0EuY3J0MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0aWdvLmNvbTAN # BgkqhkiG9w0BAQwFAAOCAgEATJtlWPrgec/vFcMybd4zket3WOLrvctKPHXefpRt # wyLHBJXfZWlhEwz2DJ71iSBewYfHAyTKx6XwJt/4+DFlDeDrbVFXpoyEUghGHCrC # 3vLaikXzvvf2LsR+7fjtaL96VkjpYeWaOXe8vrqRZIh1/12FFjQn0inL/+0t2v++ # kwzsbaINzMPxbr0hkRojAFKtl9RieCqEeajXPawhj3DDJHk6l/ENo6NbU9irALpY # +zWAT18ocWwZXsKDcpCu4MbY8pn76rSSZXwHfDVEHa1YGGti+95sxAqpbNMhRnDc # L411TCPCQdB6ljvDS93NkiZ0dlw3oJoknk5fTtOPD+UTT1lEZUtDZM9I+GdnuU2/ # zA2xOjDQoT1IrXpl5Ozf4AHwsypKOazBpPmpfTXQMkCgsRkqGCGyyH0FcRpLJzaq # 4Jgcg3Xnx35LhEPNQ/uQl3YqEqxAwXBbmQpA+oBtlGF7yG65yGdnJFxQjQEg3gf3 # AdT4LhHNnYPl+MolHEQ9J+WwhkcqCxuEdn17aE+Nt/cTtO2gLe5zD9kQup2ZLHzX # dR+PEMSU5n4k5ZVKiIwn1oVmHfmuZHaR6Ej+yFUK7SnDH944psAU+zI9+KmDYjbI # w74Ahxyr+kpCHIkD3PVcfHDZXXhO7p9eIOYJanwrCKNI9RX8BE/fzSEceuX1jhrU # uUAwggcOMIIFdqADAgECAhBLD42C8LN2spe26tpOptTsMA0GCSqGSIb3DQEBCwUA # MFcxCzAJBgNVBAYTAkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxLjAsBgNV # BAMTJVNlY3RpZ28gUHVibGljIENvZGUgU2lnbmluZyBDQSBFViBSMzYwHhcNMjMw # NTMwMDAwMDAwWhcNMjYwNTI5MjM1OTU5WjCB1DESMBAGA1UEBRMJSFJCIDIxMDE1 # MRMwEQYLKwYBBAGCNzwCAQMTAkRFMR0wGwYDVQQPExRQcml2YXRlIE9yZ2FuaXph # dGlvbjELMAkGA1UEBhMCREUxDzANBgNVBAgMBkJlcmxpbjE1MDMGA1UECgwsU09T # IFNvZnR3YXJlLSB1bmQgT3JnYW5pc2F0aW9ucy1TZXJ2aWNlIEdtYkgxNTAzBgNV # BAMMLFNPUyBTb2Z0d2FyZS0gdW5kIE9yZ2FuaXNhdGlvbnMtU2VydmljZSBHbWJI # MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvm3W6wNLzldzDdwiBUO9 # vjdX3L2GJGfxxaemditbwpxLnzXbSfStEJc9bywUm+bhSp/XGzWxeSbIGt13Sn9E # FopORa25JxuwA8xTEOxLM/CElgP/aN+/rl5sHzapJRF87id7yIXvlZxxiuAPZvpk # Tc/HWSz/IfbNPDtWNJhmCOliGJR3bXmFPHDDDflrfY5L9/v2wyLURELypxVBi53A # abZutiAa40LSqovVndbYQ8qQfdW9QVRJDF0hDMQ8xmu31kB6mLMCXK/9Rm7F2Yiv # 0NMvg4h3qh3kV+kLHzEcaIMeBQu+VtCPvMEn8ahRRw80blh7V2f9OX3GRyYn0DQf # jMZdGjpmj4P0xldq8Ge2PVm+rCUJeJSQUYsO1rLhMyBAoMl+z6qhwWuxh5cJaJar # DQvLWpixrisA+AJNJUniPyXTr+dZTSvnt29dG30C66KRskFKWDuBzjraAr3kUWQA # J5kS6G1KSuydbxgWk99Mjt+iaHLKDlseJEqXIerceCvsLzw+NOYsA5AOEdCz+OCL # dowQM0etNwWgcGViZBuydT3OvQ8w5QldJEXU+wh7a++/D2ul++4uhtQ3bWDWyk24 # SKX6OsqDFgcrFxWq+VJWflIhKqFA9hEZst5k8gHZkyXnD7PlbCDoeqt2sPUyiZKQ # /BY3ESONKDc+HZaLMG2ARjcCAwEAAaOCAdYwggHSMB8GA1UdIwQYMBaAFIEykkEr # KM1GyMSixio5EuxIqT8UMB0GA1UdDgQWBBREcHbV+LshFGmyiI02mnHSTFDZgjAO # BgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcD # AzBJBgNVHSAEQjBAMDUGDCsGAQQBsjEBAgEGATAlMCMGCCsGAQUFBwIBFhdodHRw # czovL3NlY3RpZ28uY29tL0NQUzAHBgVngQwBAzBLBgNVHR8ERDBCMECgPqA8hjpo # dHRwOi8vY3JsLnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2RlU2lnbmluZ0NB # RVZSMzYuY3JsMHsGCCsGAQUFBwEBBG8wbTBGBggrBgEFBQcwAoY6aHR0cDovL2Ny # dC5zZWN0aWdvLmNvbS9TZWN0aWdvUHVibGljQ29kZVNpZ25pbmdDQUVWUjM2LmNy # dDAjBggrBgEFBQcwAYYXaHR0cDovL29jc3Auc2VjdGlnby5jb20wSAYDVR0RBEEw # P6AcBggrBgEFBQcIA6AQMA4MDERFLUhSQiAyMTAxNYEfYW5kcmVhcy5wdWVzY2hl # bEBzb3MtYmVybGluLmNvbTANBgkqhkiG9w0BAQsFAAOCAYEAZBWwQK1VzdSeibzU # hNfNeTez03qcyuzLEhcFO0WlrUqr+hFmOEvdi4dmYDeRKmLw2M7RO+kjXsoT+UQH # y2byrEsA5MJDuXYKyQBtzPksgUoNvP5+br3gZp4CnzYprETjn9X56yOLfoPxUq3L # AMAFqtNkANfGkh9Dn72ws3LR3OkLBRxSvDRQCuhvo2uibwXqdL19wGgPyEvH9YjB # nKGkpgaYq0SGkXuWwrsjFTb+303nc3N8n6+ZK4xEp1m7W6gA3H09eRaiWKGZ9H8n # zYehgszuiRkZuEzNPfHoM6fS2Kv6YI4hyCTyIwDWfGS5w+JYEdhifcvE/xp+iBKT # XUfGTmb1ke92uqwdlTfSV/sRHObvMKNoTGx1P/Ua1QmU3K0OslDIrQm2I/cLHG5m # saHxsU41FOkMeSt9/VqD9cY9lH7IsJaCqY7cmCg8tECQ+UggkSRr7gwO5Gjfo7NO # tORIoBibi4YD3FpyV0aiOt7hpeBIqd1JIEWtD1GpUA7A6qqDMYIGWzCCBlcCAQEw # azBXMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS4wLAYD # VQQDEyVTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgQ0EgRVYgUjM2AhBLD42C # 8LN2spe26tpOptTsMAkGBSsOAwIaBQCgeDAYBgorBgEEAYI3AgEMMQowCKACgACh # AoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAM # BgorBgEEAYI3AgEVMCMGCSqGSIb3DQEJBDEWBBRvYcMkx6gaJFDdbf3s3twiLSIR # UTANBgkqhkiG9w0BAQEFAASCAgCpfNdiuHoarM2RRzi2vyxGLGthqY9yzulEIOqc # sMoyE9J6H6oEKVSnOc17xwPugSE3kZvSajv/t5tlYK+1jSBzhDIm2r4ePSZMPCIx # 69DqY/sjroAVTK1jf7D05t5h2TwqZ6tpcLiRluEerTw1SzVBHCNZFTcuAISXbbYp # dZvf1+4FicRlLHzpeNJ6a0zpwSM2+K3iVy9/DvjXgO2HDXAPFsV2k6RmhanFU9vR # ey4ep0VR76kQgY5KLsxchOn4Rpc3NqOapkjQeniNXgMm+0KegHYeNrSZRPFVD2Pw # 5qBNkXVRZinAMxR4UUAQ94ZCPkJiFZnIJaGxZvNGywgBgJpgBuw8FcTq3VhlVQzW # IlvwXIbh7JeT99va1yy5lmCzninwqHhsUaV0lN/UA0hRGuqrzkpmEQPPhlGpYZ2D # 02f0bDI+ys41Id8sYqDgL+P4G/5S1U7IJyeAaM+LKc6W0dMzzvXxoDL5eZyVYakd # F3ySrvwhIqtI5AnCEg3qlVAwJIsnsh2/7h5KTmkWy2T2jJbliv+2T7tsOvGXdHXq # +vXzYb5qkRylj8XoiI6Wh1Ab8u+ck/7TpQ8u6BHrOsBaUMFaHaVYopdChFzeKvOV # kLU04hweKEjJKZ6hwUc26ga5sfCEMh8SVwsVkSF1+xB5U0yh5UtIZgyazX0+1/Qm # Lpx6BqGCA0swggNHBgkqhkiG9w0BCQYxggM4MIIDNAIBATCBkTB9MQswCQYDVQQG # EwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxm # b3JkMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxJTAjBgNVBAMTHFNlY3RpZ28g # UlNBIFRpbWUgU3RhbXBpbmcgQ0ECEDlMJeF8oG0nqGXiO9kdItQwDQYJYIZIAWUD # BAICBQCgeTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEP # Fw0yMzA2MjYxNTEwMTJaMD8GCSqGSIb3DQEJBDEyBDBlW9wYgYLH6CC1pEyurQI+ # bXBGbliUBClwEoyFewHk/BHA0c4chczs9Jd4B3at6FswDQYJKoZIhvcNAQEBBQAE # ggIAAa8XJKW/4kZx/QJZwothmfOYDPaPumtz6X0UX4CDf4JRcbxcvIAGIr8YNkwh # G7BYpgZIJoS+c2R0m3bQyM3XwWsw7WYMyui6d4xNZfANyxUQWpV4RirytZepWDEn # Rpii9a6MgBfzuYCUD9dAFLc2LQL4TzdMMRAuLlU7iuQrMVe0bVfNAgRccw7NPxig # Vtd9CcYpWxNsYeqMWCvkwJJoKiYEx6kNcdrSy+Inr0bDMAZGfG6Jg7SpmF8zNaqC # C/NGPSsDqnbX2R9kV+P8+OneruYXylaipplcfbHq6x/xF9WItrhgBdMgW2kdJ8oo # U3qmfi+MOeGK+0OO8iHtiA7Onh5v9ogGERxNQUEyiP5bS8gUVO7zzPotKt8WUby3 # xPEDWXh/OgAJu4gl0gqKre7ACTpV/FWnE1dgxE6fyuxDNlbN85bqiSRYwTF3atIy # fmBvx+amvXj0qdmnKhtF3wDOJvoV4UP2YGzQNzFYTWP3IxBebHqNt0WUzfQ7/hPZ # H+yWlkE9tyGYdyyG464fqDeT2R3oUVkpkgu1jYhK7Q1J3JDBnaIQWcS2eZsSk4NO # xn/KblFgmmJx957i/F2Wl/tLWvEDuVkDp9JZ591XDoRpH6vgjSsun6F5QhXdOZZQ # WUcKbOUi8voHS4S1T5jpSkm86sQ56d9jLB+8dKAq5je1qMQ= # SIG # End signature block