function New-CodeSigningCertificate { [CmdletBinding()] param( [Security.Cryptography.X509Certificates.X500DistinguishedName]$Subject = "CN=PowerGUI User", [ValidateSet(1024,2048)] [int]$KeyLength = 2048, [DateTime]$ValidFrom = [datetime]::Now, [DateTime]$ValidTo = [datetime]::Now.AddYears(1) ) $signature = @" [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] public static extern bool CryptAcquireContext( ref IntPtr phProv, string pszContainer, string pszProvider, uint dwProvType, Int64 dwFlags ); [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] public static extern bool CryptReleaseContext( IntPtr phProv, int flags ); [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] public static extern bool CryptGenKey( IntPtr phProv, int Algid, int dwFlags, ref IntPtr phKey ); [DllImport("Crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)] public static extern bool CryptExportPublicKeyInfo( IntPtr phProv, int dwKeySpec, int dwCertEncodingType, IntPtr pbInfo, ref int pcbInfo ); [DllImport("Crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)] public static extern bool CryptHashPublicKeyInfo( IntPtr phProv, int Algid, int dwFlags, int dwCertEncodingType, IntPtr pInfo, IntPtr pbComputedHash, ref int pcbComputedHash ); [DllImport("Crypt32.dll", SetLastError=true)] public static extern bool CryptEncodeObject( int dwCertEncodingType, [MarshalAs(UnmanagedType.LPStr)]string lpszStructType, ref CRYPTOAPI_BLOB pvStructInfo, byte[] pbEncoded, ref int pcbEncoded ); [DllImport("Crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)] public static extern IntPtr CertCreateSelfSignCertificate( IntPtr phProv, CRYPTOAPI_BLOB pSubjectIssuerBlob, int flags, CRYPT_KEY_PROV_INFO pKeyProvInfo, IntPtr pSignatureAlgorithm, SystemTime pStartTime, SystemTime pEndTime, CERT_EXTENSIONS pExtensions ); [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] public static extern bool CryptDestroyKey( IntPtr cryptKeyHandle ); [DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)] public static extern bool FileTimeToSystemTime( [In] ref long fileTime, out SystemTime SystemTime ); [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct CRYPT_KEY_PROV_INFO { public string pwszContainerName; public string pwszProvName; public int dwProvType; public int dwFlags; public int cProvParam; public IntPtr rgProvParam; public int dwKeySpec; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct CERT_EXTENSIONS { public int cExtension; public IntPtr rgExtension; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct CERT_EXTENSION { [MarshalAs(UnmanagedType.LPStr)]public String pszObjId; public Boolean fCritical; public CRYPTOAPI_BLOB Value; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct CRYPTOAPI_BLOB { public int cbData; public IntPtr pbData; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct CRYPT_BIT_BLOB { public uint cbData; public IntPtr pbData; public uint cUnusedBits; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct CERT_PUBLIC_KEY_INFO { public CRYPT_ALGORITHM_IDENTIFIER Algorithm; public CRYPT_BIT_BLOB PublicKey; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct CRYPT_ALGORITHM_IDENTIFIER { [MarshalAs(UnmanagedType.LPStr)]public String pszObjId; public CRYPTOAPI_BLOB Parameters; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct SystemTime { public short Year; public short Month; public short DayOfWeek; public short Day; public short Hour; public short Minute; public short Second; public short Milliseconds; } "@ Add-Type -MemberDefinition $signature -Namespace Quest -Name PowerGUI $pszContainer = [Guid]::NewGuid().ToString() [IntPtr]$phProv = [IntPtr]::Zero $Provider = "Microsoft Base Cryptographic Provider v1.0" $Result = [Quest.PowerGUI]::CryptAcquireContext([ref]$phProv,$pszContainer,$Provider,0x1,0x8) if (!$Result) {Write-Warning "Unable to create provider context!"; return} [IntPtr]$phKey = [IntPtr]::Zero if ($KeyLength -eq 2048) { $Result = [Quest.PowerGUI]::CryptGenKey($phProv,2,0x08000001,[ref]$phKey) } else { $Result = [Quest.PowerGUI]::CryptGenKey($phProv,2,0x04000001,[ref]$phKey) } if (!$Result) {Write-Warning "Unable to create key context!"; return} $ptrSubject = [Runtime.InteropServices.Marshal]::AllocHGlobal($Subject.RawData.Count) [Runtime.InteropServices.Marshal]::Copy($Subject.RawData,0,$ptrSubject,$Subject.RawData.Length) $ptrName = New-Object Quest.PowerGUI+CRYPTOAPI_BLOB -Property @{ cbData = $Subject.RawData.Length; pbData = $ptrSubject } $PrivateKey = New-Object Quest.PowerGUI+CRYPT_KEY_PROV_INFO -Property @{ pwszContainerName = $pszContainer; pwszProvName = $Provider; dwProvType = 1; dwKeySpec = 2 } $Extensions = New-Object Security.Cryptography.X509Certificates.X509ExtensionCollection # add Basic Constraints extension [void]$Extensions.Add((New-Object Security.Cryptography.X509Certificates.X509BasicConstraintsExtension $false,$false,0,$false)) # add Code Signing EKU $OIDs = New-Object Security.Cryptography.OidCollection [void]$OIDs.Add("code signing") [void]$Extensions.Add((New-Object Security.Cryptography.X509Certificates.X509EnhancedKeyUsageExtension -ArgumentList $OIDs, $false)) # add SKI extension $pcbInfo = 0 if (([Quest.PowerGUI]::CryptExportPublicKeyInfo($phProv,2,1,[IntPtr]::Zero,[ref]$pcbInfo))) { $pbInfo = [Runtime.InteropServices.Marshal]::AllocHGlobal($pcbInfo) $Return = [Quest.PowerGUI]::CryptExportPublicKeyInfo($phProv,2,1,$pbInfo,[ref]$pcbInfo) $pcbComputedHash = 0 if (([Quest.PowerGUI]::CryptHashPublicKeyInfo([IntPtr]::Zero,0,0,1,$pbInfo,[IntPtr]::Zero,[ref]$pcbComputedHash))) { $pbComputedHash = [Runtime.InteropServices.Marshal]::AllocHGlobal($pcbComputedHash) [void][Quest.PowerGUI]::CryptHashPublicKeyInfo([IntPtr]::Zero,0,0,1,$pbInfo,$pbComputedHash,[ref]$pcbComputedHash) $pcbEncoded = 0 $uSKI = New-Object Quest.PowerGUI+CRYPTOAPI_BLOB -Property @{ cbData = $pcbComputedHash; pbData = $pbComputedHash } $pcbEncoded = 0 if (([Quest.PowerGUI]::CryptEncodeObject(1,"2.5.29.14",[ref]$uSKI,$null,[ref]$pcbEncoded))) { $pbEncoded = New-Object byte[] -ArgumentList $pcbEncoded $Return = [Quest.PowerGUI]::CryptEncodeObject(1,"2.5.29.14",[ref]$uSKI,$pbEncoded,[ref]$pcbEncoded) $AsnEncodedData = New-Object Security.Cryptography.AsnEncodedData -ArgumentList "2.5.29.14", $pbEncoded [void]$Extensions.Add((New-Object Security.Cryptography.X509Certificates.X509SubjectKeyIdentifierExtension -ArgumentList $AsnEncodedData, $false)) } } } # add KeyUsages extension [void]$Extensions.Add((New-Object Security.Cryptography.X509Certificates.X509KeyUsageExtension -ArgumentList "DigitalSignature", $true)) # transform managed extensions to unmanaged structures $uExtensionCollection = @() foreach ($mExt in $Extensions) { $uExtension = New-Object Quest.PowerGUI+CERT_EXTENSION $uExtension.pszObjId = $mExt.Oid.Value $uExtension.fCritical = $mExt.Critical $value = New-Object Quest.PowerGUI+CRYPTOAPI_BLOB $value.cbData = $mExt.RawData.Length $value.pbData = [Runtime.InteropServices.Marshal]::AllocHGlobal($value.cbData) [Runtime.InteropServices.Marshal]::Copy($mExt.RawData,0,$Value.pbData,$Value.cbData) $uExtension.Value = $value $uExtensionCollection += $uExtension } $uExtensions = New-Object Quest.PowerGUI+CERT_EXTENSIONS $ExtensionSize = [Runtime.InteropServices.Marshal]::SizeOf([Quest.PowerGUI+CERT_EXTENSION]) * $Extensions.Count $uExtensions.cExtension = $Extensions.Count $uExtensions.rgExtension = [Runtime.InteropServices.Marshal]::AllocHGlobal($ExtensionSize) for ($n = 0; $n -lt $Extensions.Count; ++$n) { $offset = $n * [Runtime.InteropServices.Marshal]::SizeOf([Quest.PowerGUI+CERT_EXTENSION]) $next = $offset + $uExtensions.rgExtension.ToInt64() [IntPtr]$NextAddress = New-Object IntPtr $next [Runtime.InteropServices.Marshal]::StructureToPtr($uExtensionCollection[$n],$NextAddress,$false) } $pStartTime = New-Object Quest.PowerGUI+SystemTime [void][Quest.PowerGUI]::FileTimeToSystemTime([ref]$ValidFrom.ToFileTime(),[ref]$pStartTime) $pEndTime = New-Object Quest.PowerGUI+SystemTime [void][Quest.PowerGUI]::FileTimeToSystemTime([ref]$ValidTo.ToFileTime(),[ref]$pEndTime) $pvContext = [Quest.PowerGUI]::CertCreateSelfSignCertificate($phProv,$ptrName,0,$PrivateKey,[IntPtr]::Zero,$pStartTime,$pEndTime,$uExtensions) if (!$pvContext.Equals([IntPtr]::Zero)) { New-Object Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList $pvContext } # release memory foreach ($uExt in $uExtensionCollection) {[void][Runtime.InteropServices.Marshal]::FreeHGlobal($uExt.Value.pbData)} [void][Runtime.InteropServices.Marshal]::FreeHGlobal($ptrSubject) [void][Runtime.InteropServices.Marshal]::FreeHGlobal($uExtensions.rgExtension) [void][Runtime.InteropServices.Marshal]::FreeHGlobal($pbInfo) [void][Runtime.InteropServices.Marshal]::FreeHGlobal($pbComputedHash) [void][Quest.PowerGUI]::CryptDestroyKey($phKey) [void][Quest.PowerGUI]::CryptReleaseContext($phProv,0) } # SIG # Begin signature block # MIIQWAYJKoZIhvcNAQcCoIIQSTCCEEUCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUge7cFVYzIfHNv8tAGkce54mu # Nd+gggwdMIIDejCCAmKgAwIBAgIQOCXX+vhhr570kOcmtdZa1TANBgkqhkiG9w0B # AQUFADBTMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xKzAp # BgNVBAMTIlZlcmlTaWduIFRpbWUgU3RhbXBpbmcgU2VydmljZXMgQ0EwHhcNMDcw # NjE1MDAwMDAwWhcNMTIwNjE0MjM1OTU5WjBcMQswCQYDVQQGEwJVUzEXMBUGA1UE # ChMOVmVyaVNpZ24sIEluYy4xNDAyBgNVBAMTK1ZlcmlTaWduIFRpbWUgU3RhbXBp # bmcgU2VydmljZXMgU2lnbmVyIC0gRzIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ # AoGBAMS18lIVvIiGYCkWSlsvS5Frh5HzNVRYNerRNl5iTVJRNHHCe2YdicjdKsRq # CvY32Zh0kfaSrrC1dpbxqUpjRUcuawuSTksrjO5YSovUB+QaLPiCqljZzULzLcB1 # 3o2rx44dmmxMCJUe3tvvZ+FywknCnmA84eK+FqNjeGkUe60tAgMBAAGjgcQwgcEw # NAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC52ZXJpc2ln # bi5jb20wDAYDVR0TAQH/BAIwADAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3Js # LnZlcmlzaWduLmNvbS90c3MtY2EuY3JsMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMI # MA4GA1UdDwEB/wQEAwIGwDAeBgNVHREEFzAVpBMwETEPMA0GA1UEAxMGVFNBMS0y # MA0GCSqGSIb3DQEBBQUAA4IBAQBQxUvIJIDf5A0kwt4asaECoaaCLQyDFYE3CoIO # LLBaF2G12AX+iNvxkZGzVhpApuuSvjg5sHU2dDqYT+Q3upmJypVCHbC5x6CNV+D6 # 1WQEQjVOAdEzohfITaonx/LhhkwCOE2DeMb8U+Dr4AaH3aSWnl4MmOKlvr+ChcNg # 4d+tKNjHpUtk2scbW72sOQjVOCKhM4sviprrvAchP0RBCQe1ZRwkvEjTRIDroc/J # ArQUz1THFqOAXPl5Pl1yfYgXnixDospTzn099io6uE+UAKVtCoNd+V5T9BizVw9w # w/v1rZWgDhfexBaAYMkPK26GBPHr9Hgn0QXF7jRbXrlJMvIzMIIDxDCCAy2gAwIB # AgIQR78Zld+NUkZD99ttSA0xpDANBgkqhkiG9w0BAQUFADCBizELMAkGA1UEBhMC # WkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTEUMBIGA1UEBxMLRHVyYmFudmlsbGUx # DzANBgNVBAoTBlRoYXd0ZTEdMBsGA1UECxMUVGhhd3RlIENlcnRpZmljYXRpb24x # HzAdBgNVBAMTFlRoYXd0ZSBUaW1lc3RhbXBpbmcgQ0EwHhcNMDMxMjA0MDAwMDAw # WhcNMTMxMjAzMjM1OTU5WjBTMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNp # Z24sIEluYy4xKzApBgNVBAMTIlZlcmlTaWduIFRpbWUgU3RhbXBpbmcgU2Vydmlj # ZXMgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpyrKkzM0grwp9 # iayHdfC0TvHfwQ+/Z2G9o2Qc2rv5yjOrhDCJWH6M22vdNp4Pv9HsePJ3pn5vPL+T # rw26aPRslMq9Ui2rSD31ttVdXxsCn/ovax6k96OaphrIAuF/TFLjDmDsQBx+uQ3e # P8e034e9X3pqMS4DmYETqEcgzjFzDVctzXg0M5USmRK53mgvqubjwoqMKsOLIYdm # vYNYV291vzyqJoddyhAVPJ+E6lTBCm7E/sVK3bkHEZcifNs+J9EeeOyfMcnx5iIZ # 28SzR0OaGl+gHpDkXvXufPF9q2IBj/VNC97QIlaolc2uiHau7roN8+RN2aD7aKCu # FDuzh8G7AgMBAAGjgdswgdgwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhho # dHRwOi8vb2NzcC52ZXJpc2lnbi5jb20wEgYDVR0TAQH/BAgwBgEB/wIBADBBBgNV # HR8EOjA4MDagNKAyhjBodHRwOi8vY3JsLnZlcmlzaWduLmNvbS9UaGF3dGVUaW1l # c3RhbXBpbmdDQS5jcmwwEwYDVR0lBAwwCgYIKwYBBQUHAwgwDgYDVR0PAQH/BAQD # AgEGMCQGA1UdEQQdMBukGTAXMRUwEwYDVQQDEwxUU0EyMDQ4LTEtNTMwDQYJKoZI # hvcNAQEFBQADgYEASmv56ljCRBwxiXmZK5a/gqwB1hxMzbCKWG7fCCmjXsjKkxPn # BFIN70cnLwA4sOTJk06a1CJiFfc/NyFPcDGA8Ys4h7Po6JcA/s9Vlk4k0qknTnqu # t2FB8yrO58nZXt27K4U+tZ212eFX/760xX71zwye8Jf+K9M7UhsbOCf3P0owggTT # MIIDu6ADAgECAgphPJ1VAAAAAAATMA0GCSqGSIb3DQEBBQUAMHIxCzAJBgNVBAYT # AkxWMRUwEwYDVQQKEwxTeXNhZG1pbnMgTFYxHDAaBgNVBAsTE0luZm9ybWF0aW9u # IFN5c3RlbXMxLjAsBgNVBAMTJVN5c2FkbWlucyBMViBJbnRlcm5hbCBDbGFzcyAx # IFN1YkNBLTEwHhcNMTAwNDE1MTc0MDU2WhcNMTUwNDE0MTc0MDU2WjBaMQswCQYD # VQQHEwJMVjEVMBMGA1UEChMMU3lzYWRtaW5zIExWMRwwGgYDVQQLExNJbmZvcm1h # dGlvbiBTeXN0ZW1zMRYwFAYDVQQDEw1WYWRpbXMgUG9kYW5zMIIBIjANBgkqhkiG # 9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhzDxXkGOfXVksAb8aGJD7LsISli39npqUVB2 # QE09Ie5YwL55s9RCASTLnsk56j0N5dS/z6s7E63W2Gm0QMQhnm0lAeFLEsR+jEtI # dAKSfg6ZBeTqr9RlZ++S2/veTZGr7F22+YwVMfjGq+F11WZrox4oQFY+7lRGFPvC # +cj5waHlN4TySYSur8TaFUg55nWvzkgLWdoGJXhXEkwxCR4+zAFNgIByNgJPVRTw # aKER2Crx0KU2awTZr91g2hOS3EgZSTbAWc/+m1IS2uXOFzMprlYOUZ64zHraV9G5 # N/Or6A7OTgkOV653o0+qoiKOH+JgFL6on7gZ7Fg8vTBkJ1M9VQIDAQABo4IBgTCC # AX0wOwYJKwYBBAGCNxUHBC4wLAYkKwYBBAGCNxUIlp1NhZKyeL2fPIXo7HSCzthE # eoKq90KH58Q2AgFkAgEDMB8GA1UdJQQYMBYGCisGAQQBgjcKAwwGCCsGAQUFBwMD # MA4GA1UdDwEB/wQEAwIHgDApBgkrBgEEAYI3FQoEHDAaMAwGCisGAQQBgjcKAwww # CgYIKwYBBQUHAwMwHQYDVR0OBBYEFCx12lrTtrk1gAKUsuYvMaIr11eZMB8GA1Ud # IwQYMBaAFBv6XnMtZxNcztMO5uh6qWCMC2P8MDcGA1UdHwQwMC4wLKAqoCiGJmh0 # dHA6Ly93d3cuc3lzYWRtaW5zLmx2L3BraS9waWNhLTEuY3JsMGkGCCsGAQUFBwEB # BF0wWzAyBggrBgEFBQcwAoYmaHR0cDovL3d3dy5zeXNhZG1pbnMubHYvcGtpL3Bp # Y2EtMS5jcnQwJQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwLnN5c2FkbWlucy5sdi8w # DQYJKoZIhvcNAQEFBQADggEBAEnZsZtm77dP7Rklc5NKNB9d8BwHPOocz5HXpSnq # peSNSdCCC4g1P/Uq2qvfLtJ08aTIdnK2rPQAHCv+GBnVt2XhZpX3GnLigmeLvBTg # aroyHxDO+EbCtCZCJ9tHK6Yz8QozPJhlT4qQPtMAeg3UKIQaGITIr705VpA3EDHA # 7eOZZY1yPZDzpitXuv5fOQBT83qBJ5VReKLl4YDfTBA2cJZB3ZxPMv20d00fy3io # o30uGKO3QSjEYRlgYOeJE6YhiUjBlSPqdT9eyZ4fInm+ly8HG7XYBVAw0hRj4fMI # tK0qcLJJ3WG2YkF6aVpqbQ495intBJQqDDObX6ArzXcZTMoxggOlMIIDoQIBATCB # gDByMQswCQYDVQQGEwJMVjEVMBMGA1UEChMMU3lzYWRtaW5zIExWMRwwGgYDVQQL # ExNJbmZvcm1hdGlvbiBTeXN0ZW1zMS4wLAYDVQQDEyVTeXNhZG1pbnMgTFYgSW50 # ZXJuYWwgQ2xhc3MgMSBTdWJDQS0xAgphPJ1VAAAAAAATMAkGBSsOAwIaBQCgeDAY # BgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3 # AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMCMGCSqGSIb3DQEJBDEW # BBRue0bqapIj7BEg3nnfRe+5cK+NaTANBgkqhkiG9w0BAQEFAASCAQAIm6lmx1Pb # /oH1lADOb1eZPIkd9YknoeGn4X6LqHLHnYCxA3w4rQ1XSdSSqn2kpHIKwM9GdS/y # Y1i6wrMGG/aMGkn2qaMaKnU+NfzDztG8c3UCXCfX4Du/eEyvAC/Ip0RpkKNajqjc # S+NPAU+Vx1TMGEMlXdmW3Lb0ROQ7vOIOzSnSPvbWnXfOoRyMtFTq/rRIVUEK2+as # FCIkr3ctT82ZK10+2gBfW68KqUZ4oQSpAaRZbyFVPWvS1LVXHOq2pIDwlM8ZEGqR # 3kCjboronWmT9OdCoLhvGfRjJ0MFgL2rrxLzQhhRJ+Oz7uOGpd5bfkkAFzwCaHG1 # GkNh/sG2KHUfoYIBfzCCAXsGCSqGSIb3DQEJBjGCAWwwggFoAgEBMGcwUzELMAkG # A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMSswKQYDVQQDEyJWZXJp # U2lnbiBUaW1lIFN0YW1waW5nIFNlcnZpY2VzIENBAhA4Jdf6+GGvnvSQ5ya11lrV # MAkGBSsOAwIaBQCgXTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3 # DQEJBTEPFw0xMTA2MTMxNzM3NDRaMCMGCSqGSIb3DQEJBDEWBBTG9KeiPlICeucD # aT4fmG6E6t9uXjANBgkqhkiG9w0BAQEFAASBgFxs6HDpZyIx/VXgF9DWDtP4D4sY # AIAiSrYqKkd/McuwwOAWJNdLIyeRz3IAYd4SQXykWmvGb4WgghyfXnMRow8fUNje # U+xmHghKJ+jkQMD/G4SXMZfyfdNNJESfqmLc/hMPUy401i1KWSSiQ140Wf7eoVjR # VV1163n9WbMkAFk3 # SIG # End signature block