PS/ConvertFrom-JWTToken.ps1
|
Function ConvertFrom-JWTToken { <# .SYNOPSIS Get JWT token information. .PARAMETER JWTToken AccessToken string. .PARAMETER ValidateSignature Use additional signature validation. .PARAMETER AsJSON Return data as json. .EXAMPLE $AccessToken | ConvertFrom-JWTToken -AsJSON .EXAMPLE $AccessToken | ConvertFrom-JWTToken -ValidateSignature .NOTES Author: Michal Gajda .LINK https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens #> [CmdletBinding()] param( [Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0)] [string]$JWTToken, [Switch]$ValidateSignature, [Switch]$AsJSON ) #Check if token is ok if (!$JWTToken.Contains(".") -or !$JWTToken.StartsWith("eyJ")) { Write-Error "Invalid Access Token" -ErrorAction Stop } $DecodedToken = @{} $Header, $Payload, $Signature = $JWTToken.Split(".") #Decode Header $HeaderData = $Header.Replace('-', '+').Replace('_', '/') while($HeaderData.Length % 4 -ne 0) { $HeaderData += "=" } $DecodedHeader = [System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($HeaderData)) | ConvertFrom-Json $DecodedToken['Header'] = [PSCustomObject]$DecodedHeader #Decode Payload $PayloadData = $Payload.Replace('-', '+').Replace('_', '/') while($PayloadData.Length % 4 -ne 0) { $PayloadData += "=" } $DecodedPayload = [System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($PayloadData)) | ConvertFrom-Json $DecodedToken['Payload'] = [PSCustomObject]$DecodedPayload #Get expiration time $UnixTime = (Get-Date -Year 1970 -Month 1 -Day 1 -hour 0 -Minute 0 -Second 0 -Millisecond 0) $UtcTime = $UnixTime.AddSeconds($DecodedToken['Payload'].exp) $ExpiryDateTime = $UtcTime.AddMinutes($(Get-TimeZone).GetUtcOffset($(Get-Date)).TotalMinutes) $DecodedToken['ExpiryDateTime'] = $ExpiryDateTime #Validation if($ValidateSignature) { $Issuer = $DecodedToken['Payload'].iss $Kid = $DecodedToken['Header'].kid #Get keys pool for tenant $Url = $Issuer + ".well-known/openid-configuration" #if($null -ne $AppId) { $Url += "?appid=" + $AppId } $Configuration = (ConvertFrom-Json (Invoke-WebRequest $Url).Content) $Keys = (ConvertFrom-Json (Invoke-WebRequest $Configuration.jwks_uri).Content).Keys $KeysHT = $Keys | Group-Object -Property Kid -AsHashTable #Get right key $Key = $KeysHT[$Kid] if($null -ne $Key) { #Get key info $KeyInfo = @{} $KeyInfo['e'] = $Key.e $KeyInfo['kty'] = $Key.kty $KeyInfo['n'] = $Key.n $KeyInfo['kid'] = $Key.kid #Decode public cert if($Key.x5c) { $X5C = $Key.x5c | Select-Object -First 1 $X509Certificate = [System.Security.Cryptography.X509Certificates.X509Certificate2]([System.Convert]::FromBase64String($X5C)) $KeyInfo['X509Certificate'] = $X509Certificate } $DecodedToken['KeyInfo'] = [PSCustomObject]$KeyInfo #Validate Signature $RSA = New-Object System.Security.Cryptography.RSACryptoServiceProvider $RSAParameters = [System.Security.Cryptography.RSAParameters]::New() $KaynData = $Key.n.Replace('-', '+').Replace('_', '/') while($KaynData.Length % 4 -ne 0) { $KaynData += "=" } $RSAParameters.Modulus = [Convert]::FromBase64String($KaynData) $KayeData = $Key.e.Replace('-', '+').Replace('_', '/') while($KayeData.Length % 4 -ne 0) { $KayeData += "=" } $RSAParameters.Exponent = [System.Convert]::FromBase64String($KayeData) $RSA.ImportParameters($RSAParameters) $SignatureDeformatter = [System.Security.Cryptography.RSAPKCS1SignatureDeformatter]::new($RSA) $SignatureDeformatter.SetHashAlgorithm("SHA256") #Get hash of header and payload $SHA256 = [System.Security.Cryptography.SHA256]::Create() $Hash = $SHA256.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($Header + '.' + $Payload)) #Decode signature $SignatureData = $Signature.Replace('-', '+').Replace('_', '/') while($SignatureData.Length % 4 -ne 0) { $SignatureData += "=" } $SignatureBytes = [System.Convert]::FromBase64String($SignatureData) #Verify signature if($SignatureDeformatter.VerifySignature($Hash, $SignatureBytes)) { $DecodedToken['SignatureStatus'] = "Signature Verified" } else { if($TokenClaims.aud -eq "https://graph.microsoft.com") { $DecodedToken['SignatureStatus'] = "Cant validate MSGraph token signature" } else { $DecodedToken['SignatureStatus'] = "Invalid Signature" } } } } if($AsJSON) { $Result = [PSCustomObject]$DecodedToken | ConvertTo-Json -Depth 5 } else { $Result = [PSCustomObject]$DecodedToken } Return $Result } # SIG # Begin signature block # MIIixQYJKoZIhvcNAQcCoIIitjCCIrICAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCxsVkrh2KDqf2G # 1P2mIiVkji7dp3lEJA5wDjb1EDRVkaCCHDUwggQuMIICFqADAgECAhBTXA6VE4ZJ # kkZJJNYxZDR4MA0GCSqGSIb3DQEBCwUAMBoxGDAWBgNVBAMMD01pY2hhbCBHYWpk # YSBDQTAeFw0yNjExMDkxMDI2MTZaFw0yNzExMDkxMDM2MTZaMCMxITAfBgNVBAMM # GE1pY2hhbCBHYWpkYSBDb2RlU2lnbmluZzCCASIwDQYJKoZIhvcNAQEBBQADggEP # ADCCAQoCggEBAMbcpWN3ctQ7jeDfNLFP+cxh3Wd9vA1r6jN9iQYAS15j1wEI6V53 # yWjJoYJKmeIQtXxQYWhsfPE5cJ2CHTTxhsovsKp2zm/30MRL50maZrbwdkZ/KZyc # LLPk+dyNvfWfH5UBQV0pRCLN1ILXPQd1F3LqsBPH7cko5L5Om+b3oBl2w9CxF4G/ # UbTFh/9qgcAYXvOPNDzUFFryFepSiwAAfC6D5RHaFMWljb+gegRUkl+/B4g8Xf3R # mbFcl2lTqhRENPFhOdrtngy9ldkz/tyUO3Reaixhy+EA8/bTOtK5Mq7RtyAA2dhZ # IH5AQrN5U9jIY8SL+rizT4JvF/L6TQgqRC0CAwEAAaNnMGUwDgYDVR0PAQH/BAQD # AgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMB8GA1UdIwQYMBaAFGfJIhIP6r4+OzlU # V5fnBSoEZF3BMB0GA1UdDgQWBBRuO6w3QLbfSM2OJPzXgPrB6kf7zTANBgkqhkiG # 9w0BAQsFAAOCAgEAT752PsmY9UcAejy9a4CgH74wvHt5otpbyMGtM0qUqlyc+8q/ # E69LBVDjPt6CEXiJFMTRNXoVTKkEjZA0wO4GsyBg+T9ODbGxl/Vn+39qsqLh0HYZ # aTQyPGfsVtm/ZuvcwJYnm2gdHUjb3T9joP+vGe+2bFfzRnCIAjdM66Bgq6pxSPlt # KQLmLsWyygMqTHaam4VLe5Kaqf8DgibsJ6NWHhS4/b7XdZaajp6YpFaoIARAoGZe # hOVgZaDIIi9yEFfhxhAhX5G9+yJEVjJH/ZnRCY3vRHvFYQHtvJcxQrUmG16IeA3L # 6t2+UzT6mWKIrFUprO3XceGZeT/sKn7vUqSnKU0fJR/C9+CLjNaD2P4U5QXgIa0+ # bN+RGuB+0u4NUj0fOTFQRKAxIhgzlzUJbMUceDOhmg8aMgG9vrI6Ukhp0q4iNjvg # 7HLDM+mDzbthNy+duIAKli3DTfGMKvpy1PLfY9NlTQLi2suhppUlzMMxtBuQCajq # dZBYLEQIBZyrsnfG7dleDRzXHy6E137/EXx3MeYj2ZT0vGRwDH0qQWZkL3WLILN9 # t1hwlueP2imnQ8IyxxGRRgR61LpEoeVxpkMP/LlsXngLvxDuAZVFadHkcH4YvoZx # bu8t/sbwZWIiVhZarLyochr1eXwecXNbjXucI7tGAxanRq0SFl7mQyJ6YEMwggTv # MIIC16ADAgECAhASiMPAZpZmrkW5VhWUwZQNMA0GCSqGSIb3DQEBCwUAMBoxGDAW # BgNVBAMMD01pY2hhbCBHYWpkYSBDQTAeFw0yNjExMDkxMDI1MjNaFw0zNjExMDkx # MDM1MjFaMBoxGDAWBgNVBAMMD01pY2hhbCBHYWpkYSBDQTCCAiIwDQYJKoZIhvcN # AQEBBQADggIPADCCAgoCggIBAKoTH4NpYpZwRaNHiIVPS/34t3cwY7fAjDjtY08F # Vs0af5/C6EY7OwwmrIf6f8bMHOPI25lfZ57mOaTdFpZKK1/6y56KKc8vhYMmUYeB # 3KGZ+NYGdDsyLt+PFG32nGwpDVu8r/iKJMk5tWwAbTpyIa+DD/W+skB3jNf93aCh # A8htMXwHooHMkNZ7p5E5fx8NQjY/mlTtGB7IZ61DBwg4Zm74avD+56RgbkvTz222 # V6vKQxU30F4wu6fmrRVzLDbZw1tCMND389QRx01MuD9lCzsZcty4dj4oWh4PoJKf # HtoHuoUFtJW9UOLsNxryat6JFlbkggPb6CbWvwJfCsCXgjEFP1DEtO5KFjup3ME9 # a+Duvsk3XkbXfNWeVdDZ12LqHu89QV1z6pAi/qAf21zYO/bNfwKoaN9sqlDEVEEM # bytam3Iw1WxDgweWshAXTABOKOWHVryU9VFPhRTlazEXZZjGXup6kxk4+zpU9DAx # BqGfZvRevGlVqmr6/1qt8FtQi73+L+WQu51lVAMezQNhTukCvA3odiCOg2/LHLXb # 7Du3SVeQgM52OUAN6CP7dPHJUf5EBiWidiNqx2B1a9l+pxIeLPdn+7t64uQdY6j9 # NpOY7CNyZDcx/KwZ4IG++VQlOcMbHnDuooD2/lCFEPf8wX974KvQk5to90b1TYB1 # TVU1AgMBAAGjMTAvMA4GA1UdDwEB/wQEAwICBDAdBgNVHQ4EFgQUZ8kiEg/qvj47 # OVRXl+cFKgRkXcEwDQYJKoZIhvcNAQELBQADggIBACbBQxFIE77wc05vEf2IjBLC # plLr7Yo71AIg1JwggEze1ZWQcRrZqDqpH4i/hbihW4LlSDxJVQXCacnknJg0p2Ur # maP/0fyI8KhYkmj+VQh1VFkovErPQp+aYSMD9sDsr7BqqmSLNMoL3HV7YZM9qlX+ # sR0is+Cg+cT0bq+SHxTBmb4EUy3lD6+gzH3qvv79fqMHA6JXBbNDVDYyaOFB2y51 # U+F1yzbf1NzVGkTdFv9JzO57WneJ3qLxFAfKckVBsn0f+nUsNkTP6c42hHlc1dna # H4zgt0Ie8CIPg3mwy28hnG7C80C3T0B8bUBC2NntGMjxYm8mML2v7xZRhAwkBUx/ # GtklhGUGiHfBCKyy2YgSGWI7/OmOK4dv3+1Vi+3FKyFXwZ2FibmA12WaIXsaoz9N # vIVIu+vqm01f6C3kFj/VxVjVa3Q6vSeq/Lk7y/HKCGFoQzbwUT70VKBC/X/oSI0k # BRiMQMoHUwJhwehWszvwh6/Oul7We3618pGfjgSeaDjRhb1t7aOLs9WIt+n4HOUj # Aiq5MJ/bLbVBxVSCzoMblRwX1XU5bpJedyN2rbXhLfDuywISBT0N6nd+cQ78RjbX # QO99Vegf01cCG8vicJKWAHOK78a3sCUdgC1ZSIqpu2FhdYa5QdNn3eCAey1X8nnE # veaEYam2B60G1P0WV02OMIIFyTCCBLGgAwIBAgIQG7WPJSrfIwBJKMmuPX7tJzAN # BgkqhkiG9w0BAQwFADB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU # ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24g # QXV0aG9yaXR5MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMB4X # DTIxMDUzMTA2NDMwNloXDTI5MDkxNzA2NDMwNlowgYAxCzAJBgNVBAYTAlBMMSIw # IAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0 # dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxJDAiBgNVBAMTG0NlcnR1bSBUcnVz # dGVkIE5ldHdvcmsgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB # AL35ePjm1YAMZJ2GG5ZkZz8iOh51AX3v+1xnjMnMXGupkea5QuUgS5vam3u5mV3Z # m4BL14RAKyfT6Lowuz4JGqdJle8rQCTCl8en7psl76gKAJeFWqqd3CnJ4jUH63BN # StbBs1a4oUE4m9H7MX+P4F/hsT8PjhZJYNcGjRj5qiYQqyrT0NFnjRtGvkcw1S5y # 0cVj2udjeUR+S2MkiYYuND8pTFKLKqfA4pEoibnAW/kd2ecnrf+aApfBxlCSmwIs # vam5NFkKv4RK/9/+s5/r2Z7gmCPspmt3FirbzK07HKSH3EZzXhliaEVX5JCCQrtC # 1vBh4MGjPWajXfQY7ojJjRdFKZkydQIx7ikmyGsC5rViRX83FVojaInUPt5OJ7Dw # QAy8TRfLTaKzHtAGWt32k89XdZn1+oYaZ3izv5b+NNy951JW5bPldXvXQZEF3F1p # 45UNQ7n8g5Y5lXtsgFpPE3LG130pekS6UqQq1UFGCSD+IqC2WzCNvIkM1ddw+IdS # /drvrFEuB7NO/tAJ2nDvmPpW5m3btVdL3OUsJRXIni54TvjanJ6GLMpX8xrlyJKL # GoKWesO8UBJp2A5aRos66yb6I8m2sIG+QgCk+Nb+MC7H0kb25Y51/fLMudCHW8wG # EGC7gzW3XmfeR+yZSPGkoRX+rYxijjlVTzkWubFjnf+3AgMBAAGjggE+MIIBOjAP # BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAf # BgNVHSMEGDAWgBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw # LwYDVR0fBCgwJjAkoCKgIIYeaHR0cDovL2NybC5jZXJ0dW0ucGwvY3RuY2EuY3Js # MGsGCCsGAQUFBwEBBF8wXTAoBggrBgEFBQcwAYYcaHR0cDovL3N1YmNhLm9jc3At # Y2VydHVtLmNvbTAxBggrBgEFBQcwAoYlaHR0cDovL3JlcG9zaXRvcnkuY2VydHVt # LnBsL2N0bmNhLmNlcjA5BgNVHSAEMjAwMC4GBFUdIAAwJjAkBggrBgEFBQcCARYY # aHR0cDovL3d3dy5jZXJ0dW0ucGwvQ1BTMA0GCSqGSIb3DQEBDAUAA4IBAQBRwqFY # FiIQi/yGMdTCMtNc+EuiL2o+TfirCB7t1ej65wgN7LfGHg6ydQV6sQv613RqAAYf # pM6q8mt92BHAEQjUDk1hxTqo+rHh45jq4mP9QfWTfQ28XZI7kZplutBfTL5MjWgD # EBbV8dAEioUz+TfnWy4maUI8us281HrpTZ3a50P7Y1KAhQTEJZVV8H6nnwHFWyj4 # 4M6GcKYnOzn7OC6YU2UidS3X9t0iIpGW691o7T+jGZfTOyWI7DYSPal+zgKNBZqS # pyduRbKcYoY3DaQzjteoTtBKF0NMxfGnbNIeWGwUUX6KVKH27595el2BmhaQD+G7 # 8UoA+fndvu2q7M4KMIIGgjCCBGqgAwIBAgIQKPB3wRw2vf5fdDJHcCcuAzANBgkq # hkiG9w0BAQwFADBWMQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEg # U3lzdGVtcyBTLkEuMSQwIgYDVQQDExtDZXJ0dW0gVGltZXN0YW1waW5nIDIwMjEg # Q0EwHhcNMjYwMzExMDczNDU0WhcNMzYwMjI3MDczNDU0WjBQMQswCQYDVQQGEwJQ # TDEhMB8GA1UECgwYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMR4wHAYDVQQDDBVD # ZXJ0dW0gVGltZXN0YW1wIDIwMjYwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK # AoICAQC4vc3wcPsSNdoYthfbjUATTkk5EyItd37odw4lsmyOd/dmwXycOrTu8w7O # 1Kj/63o1X+MRU1N1zTj7LjhZD+UjxbJ1sJ91SS/jYTYbLro72LELWkJ7zaNcJOOq # 3k4MLNS/DhRHSmsYMqk+MzkMfNZi8DWUqlzVPUa2/aACViReDMnc/gtXm7tA9Pr4 # DN7agEPE1NtN36oCgj6iHR5aGhah/XskfvLZ6ZstoZ5zefWTrZrLh3kcH+YkzoZY # X9Hf6qqrizkiBj4BlS9R4+VwVKMdjhO7UEa/pf8cTWy+jrsATuAGthG7sWIN+3KV # 7+Ytv5Uy+DQEgf3bn/VuH4wN0aPhj/mwueJ9jmIjNwqvM/dno8fBeR1jtnuP++Xg # veQfbTMP3qu9dPRg8ltvtrreQZ9KPDFyUxEZMsrLVm6nJ1JKJgPe6n4gwsL6Vrjj # HX0zpLF3vUvsQ8TiWgm4sk4r4D7pcXE/rX0E0Vwa+VMLT73PiDZ2nzhIpc1RwNdb # b/qR3Mpa8sQXNPHFIoX/7bapGUtG5sd1cUGsvLqIWk6dP/xAgPb2BludUinSTCYV # 7ysiHQS8vFmDXIU7fMkSE7/QHcYPSahro4fk5z9W1t2kIxbZRJe0s4DXiPDlQPwi # QFllLkU9wLvU6DqR8v35a65J4TeIXhMO/+iCzL+B0rI9GGeKLQIDAQABo4IBUDCC # AUwwdQYIKwYBBQUHAQEEaTBnMDsGCCsGAQUFBzAChi9odHRwOi8vc3ViY2EucmVw # b3NpdG9yeS5jZXJ0dW0ucGwvY3RzY2EyMDIxLmNlcjAoBggrBgEFBQcwAYYcaHR0 # cDovL3N1YmNhLm9jc3AtY2VydHVtLmNvbTAfBgNVHSMEGDAWgBS+VAIvv0Bsc0PO # rAklTp5DRBru4DAMBgNVHRMBAf8EAjAAMDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6 # Ly9zdWJjYS5jcmwuY2VydHVtLnBsL2N0c2NhMjAyMS5jcmwwFgYDVR0lAQH/BAww # CgYIKwYBBQUHAwgwDgYDVR0PAQH/BAQDAgeAMCIGA1UdIAQbMBkwCAYGZ4EMAQQC # MA0GCyqEaAGG9ncCBQELMB0GA1UdDgQWBBQjOWooq5oSp6Sn8h/5RZq/jf6CAzAN # BgkqhkiG9w0BAQwFAAOCAgEAZv6Tm6wL3k6mBTwkrYcTVcAR01uE37gUGNihgnTJ # R+gC41T2H9lwETRjE10nEdCUNv3Ni8S6aBx4UcMRX93fd9w4RUteua2I+oj0kCpu # Na3PQDKUwozHZmotWivaPO9KTs08y0YVhVSMZvuUH/reFec9eLT6FLAFnX0Sg9Wc # 7833uQB5RPa8TmXBkTolC8bNxHX+2SfEWSNI8w/Y7o9qBF9l0uwVSrjQitVtIdZo # 2qb9NvMqqPFLWYef9SG+PGMqfPAQ2EoYeT0hlFLkubWF1X3HbiDwXtz3TU2EWHU+ # VTcZMC4IzMyHK/+kh9n3oxSQ45wsY71y7mqxKyYPyHSPoV3RiAQ1Thr9c65BeJLa # ELxWSKeQyAGIdBsMlIXPO6qp+VGmE49vosogQ0jYe2hgq5LgJ6oO0Ie364V/kITB # nifUqS6Zxu+qjfOYS8o72EeoEWIi04/BuH8Y6leNNP27j8NKwaPciWcqv/HBnQji # zzmH/aqXn03K2SnjvaYPlCR8fFAAW2k6os0cZvLFEhMnHHAghYSIrdwCP98Brkjg # A3ogOu+jXEO/nbD9OGL873Te6U2TcoOu9lqQQyXYNHiLR5eMqJrzXiDlodarOEKj # lukyPDnLIuLkg0y6K8S1A5wU8CkM86cXdWFHLRIEYd9kdCfRZBZHhK7iVPeEZYxa # 9bgwgga5MIIEoaADAgECAhEA5/9pxzs1zkuRJth0fGilhzANBgkqhkiG9w0BAQwF # ADCBgDELMAkGA1UEBhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVz # IFMuQS4xJzAlBgNVBAsTHkNlcnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEk # MCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29yayBDQSAyMB4XDTIxMDUxOTA1 # MzIwN1oXDTM2MDUxODA1MzIwN1owVjELMAkGA1UEBhMCUEwxITAfBgNVBAoTGEFz # c2VjbyBEYXRhIFN5c3RlbXMgUy5BLjEkMCIGA1UEAxMbQ2VydHVtIFRpbWVzdGFt # cGluZyAyMDIxIENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA6RIf # BDXtuV16xaaVQb6KZX9Od9FtJXXTZo7b+GEof3+3g0ChWiKnO7R4+6MfrvLyLCWZ # a6GpFHjEt4t0/GiUQvnkLOBRdBqr5DOvlmTvJJs2X8ZmWgWJjC7PBZLYBWAs8sJl # 3kNXxBMX5XntjqWx1ZOuuXl0R4x+zGGSMzZ45dpvB8vLpQfZkfMC/1tL9KYyjU+h # tLH68dZJPtzhqLBVG+8ljZ1ZFilOKksS79epCeqFSeAUm2eMTGpOiS3gfLM6yvb8 # Bg6bxg5yglDGC9zbr4sB9ceIGRtCQF1N8dqTgM/dSViiUgJkcv5dLNJeWxGCqJYP # gzKlYZTgDXfGIeZpEFmjBLwURP5ABsyKoFocMzdjrCiFbTvJn+bD1kq78qZUgAQG # Gtd6zGJ88H4NPJ5Y2R4IargiWAmv8RyvWnHr/VA+2PrrK9eXe5q7M88YRdSTq9TK # bqdnITUgZcjjm4ZUjteq8K331a4P0s2in0p3UubMEYa/G5w6jSWPUzchGLwWKYBf # eSu6dIOC4LkeAPvmdZxSB1lWOb9HzVWZoM8Q/blaP4LWt6JxjkI9yQsYGMdCqwl7 # uMnPUIlcExS1mzXRxUowQref/EPaS7kYVaHHQrp4XB7nTEtQhkP0Z9Puz/n8zIFn # USnxDof4Yy650PAXSYmK2TcbyDoTNmmt8xAxzcMCAwEAAaOCAVUwggFRMA8GA1Ud # EwEB/wQFMAMBAf8wHQYDVR0OBBYEFL5UAi+/QGxzQ86sCSVOnkNEGu7gMB8GA1Ud # IwQYMBaAFLahVDkCw6A/joq8+tT4HKbROg79MA4GA1UdDwEB/wQEAwIBBjATBgNV # HSUEDDAKBggrBgEFBQcDCDAwBgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vY3JsLmNl # cnR1bS5wbC9jdG5jYTIuY3JsMGwGCCsGAQUFBwEBBGAwXjAoBggrBgEFBQcwAYYc # aHR0cDovL3N1YmNhLm9jc3AtY2VydHVtLmNvbTAyBggrBgEFBQcwAoYmaHR0cDov # L3JlcG9zaXRvcnkuY2VydHVtLnBsL2N0bmNhMi5jZXIwOQYDVR0gBDIwMDAuBgRV # HSAAMCYwJAYIKwYBBQUHAgEWGGh0dHA6Ly93d3cuY2VydHVtLnBsL0NQUzANBgkq # hkiG9w0BAQwFAAOCAgEAuJNZd8lMFf2UBwigp3qgLPBBk58BFCS3Q6aJDf3TISoy # tK0eal/JyCB88aUEd0wMNiEcNVMbK9j5Yht2whaknUE1G32k6uld7wcxHmw67vUB # Y6pSp8QhdodY4SzRRaZWzyYlviUpyU4dXyhKhHSncYJfa1U75cXxCe3sTp9uTBm3 # f8Bj8LkpjMUSVTtMJ6oEu5JqCYzRfc6nnoRUgwz/GVZFoOBGdrSEtDN7mZgcka/t # S5MI47fALVvN5lZ2U8k7Dm/hTX8CWOw0uBZloZEW4HB0Xra3qE4qzzq/6M8gyoU/ # DE0k3+i7bYOrOk/7tPJg1sOhytOGUQ30PbG++0FfJioDuOFhj99b151SqFlSaRQY # z74y/P2XJP+cF19oqozmi0rRTkfyEJIvhIZ+M5XIFZttmVQgTxfpfJwMFFEoQrSr # klOxpmSygppsUDJEoliC05vBLVQ+gMZyYaKvBJ4YxBMlKH5ZHkRdloRYlUDplk8G # Ua+OCMVhpDSQurU6K1ua5dmZftnvSSz2H96UrQDzA6DyiI1V3ejVtvn2azVAXg6N # njmuRZ+wa7Pxy0H3+V4K4rOTHlG3VYA6xfLsTunCz72T6Ot4+tkrDYOeaU1pPX1C # BfYj6EW2+ELq46GP8KCNUQDirWLU4nOmgCat7vN0SD6RlwUiSsMeCiQDmZwgwrUx # ggXmMIIF4gIBATAuMBoxGDAWBgNVBAMMD01pY2hhbCBHYWpkYSBDQQIQU1wOlROG # SZJGSSTWMWQ0eDANBglghkgBZQMEAgEFAKCBhDAYBgorBgEEAYI3AgEMMQowCKAC # gAChAoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsx # DjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEiBCCwBcWH7XE8reQYzof95tYL # HANSbam0+y1afE1wm+mVEjANBgkqhkiG9w0BAQEFAASCAQA/1alB/micQmQdPg8M # m5no9cBmfSjBlM22iiR8/kNugf5gRkCARlCK/Lu/hgsfRcrEn84u18Zguz2MsS9/ # h6Sf8PuGRPUTc1wXe6mVhoe9fnm9NfyL06oS5hlbx5atuuNwY1epnSepAlsdp1wo # ceZ0G7i2g82B+t5Ih+oS4exQqVFyRfSzR3x4V/1j83A60M60Lrut0NtQs332A3lr # d6ydepzpSJRwtCHsckU2s6xrGf1IN3lOdB6wS1yhW8Gn1D2FtDzwIpF2IKu7s8xa # yLuIsGhUyc+guIKcwBjfBENj07uylagkiBDmiVXB10GQ4ayDrQN2IHS4dMftO+l6 # kkC6oYIEAjCCA/4GCSqGSIb3DQEJBjGCA+8wggPrAgEBMGowVjELMAkGA1UEBhMC # UEwxITAfBgNVBAoTGEFzc2VjbyBEYXRhIFN5c3RlbXMgUy5BLjEkMCIGA1UEAxMb # Q2VydHVtIFRpbWVzdGFtcGluZyAyMDIxIENBAhAo8HfBHDa9/l90MkdwJy4DMA0G # CWCGSAFlAwQCAgUAoIIBVjAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJ # KoZIhvcNAQkFMQ8XDTI2MTEwOTEwNTIwNlowNwYLKoZIhvcNAQkQAi8xKDAmMCQw # IgQghb6Q4QrSQ418ySi2r0iwmrIIF3zs+LASbFjTkQUlxDwwPwYJKoZIhvcNAQkE # MTIEMHKa/4T2ENqeLFBPllhgtXvHS+/xEXMgSndm/T9W3kA65Y3Y29NTXsXZGK8K # 0RHm1DCBnwYLKoZIhvcNAQkQAgwxgY8wgYwwgYkwgYYEFFcUaEEMqFrzQk75FkpR # NhD0042YMG4wWqRYMFYxCzAJBgNVBAYTAlBMMSEwHwYDVQQKExhBc3NlY28gRGF0 # YSBTeXN0ZW1zIFMuQS4xJDAiBgNVBAMTG0NlcnR1bSBUaW1lc3RhbXBpbmcgMjAy # MSBDQQIQKPB3wRw2vf5fdDJHcCcuAzANBgkqhkiG9w0BAQEFAASCAgCC+WUYyqsw # CrsNMbu4gTqTDzKs28To/k6GmQ9li7qjtoECLl3sj1chd31+2QQLJ/g24fZgMbUP # crmfXAjnTOHJcY9Y1waHobjMGuirFMlVNaRdT9toBkGt1RoOo7ecF0THzoWY0Ax+ # nInaBBC/XOwonwe99VC1gAtu8SnsO1Ixv8UtrIoumtlH7RW03doNC7BAeVf2CN2I # 6WJEBxjfMIIiyJ5msfV4y98POXMO3plVf9kvaWQH7AyQN4v1HuDtdnowDHoFkXSk # hpDjITzYiX5rCWm7WTo/vOiLx0boAqpx3/cmJZAp+SJX1OE3Em+98JFhtxjuIAdh # snoBfkvWrZuIeQVPNhQ6sIZhGqk6YpOJFhJeoaACdjCxx0Gv/KSBy2C+3ZSW2cJP # abKXcwddXcSIQoSFA2X1MXd1xybTx43xBMgRmgyXyWYquqCHctwNwIvvBt0lwpbT # +YcDXivx/H9ZUHrUgZ9Kjzf4CO+16SHxkfsXaoYhVxoR7IEaes1BzlBBRox5c4L0 # pbPGASvQkuwWhaMy4gTeKyf2DwEBpwxYDVkPRCRhHUaccAZd1l5Qc9ZaR0jsdLyO # SXY9pLGe5ZJ3omKBQdsg8bLUujL8xshnICR0tZ+vkAGTvCtYcuDQKHxeUYbVjnQq # b5x7wMSyhsqf9c8VOtKOmruJvbfISjxoXg== # SIG # End signature block |