Search code examples
c#powershellx509certificate2

upload X509 certificate using powershell - error 'Cannot find the requested object'


I'm currently developing a prototype C# MVC app that allows users to upload Certificates and CRLs to a repository. The app will take an uploaded .cer, for example, and parse it using X509Certificate2's Import() method. I do this to verify that what the user uploaded was indeed a cert:

    public CertModel(byte[] bytes)
    {
        this._Certificate = new X509Certificate2();
        try // Attempt to parse as a certificate to see if this is actually a cert
        { 
            this._Certificate.Import(bytes);
            this.Subject = _Certificate.Subject;
            this.Sha1Fingerprint = _Certificate.Thumbprint;
            this.RawData = Convert.ToBase64String(_Certificate.RawData);
        }
        catch (CryptographicException e)
        {
            this._Certificate = null;
        } 

    }

There is a MVC web page that presents an upload form, and ultimately the above code is called. This works fine when using the web form directly.

There is another team writing powershell scripts, and they are trying to do the upload using the Invoke-WebRequest commandlet. This is what we can't get to work.

$filePath = "%HOMEPATH%\Desktop\certs\myCert.cer"
$fileInfo = gi $filePath

# Get the raw data of the cert to upload #

$rawCertData = [System.IO.File]::ReadAllText($fileInfo)
$length = $rawCertData.Length;
Write-Host $rawCertData
## Type of file you are uploading ##
$fileType = "Certificate"


## Build the POST Body ##
$boundary = [System.Guid]::NewGuid().ToString()
$lf = "`n"

$bodyLines = (
    "--$boundary",
    'Content-Disposition: form-data; name="Type"',
    '',
    "$fileType",
    "--$boundary",
    'Content-Disposition: form-data; name="upload"; filename="myCert.cer"',
    'Content-Type: application/octet-stream',
    '',
    "$rawCertData",
    "--$boundary--"
) -join $lf


$contentType = "multipart/form-data; boundary=$boundary"
$uri = "http://localhost:58484/repo/upload_service"
$response = Invoke-WebRequest -Uri $uri  -Method POST -ContentType $contentType -Body $bodyLines -WebSession $session 
$tempStore.Clear()

For the same file, I have verified that the request payloads look exactly the same. Further, I can verify the byte array passed to Import() is the same. However, when using curl/Invoke-WebRequest method. I get the 'Cannot find the requested object' message in a CryptographicException.

I've never been exposed to powershell before now, so I'm hoping there's a C# solution I can implement to resolve this, but I will take whatever advice I can get.


Solution

  • @Eris Thanks for the solution in your comment.

    $rawCertData = [System.IO.File]::ReadAllBytes($fileInfo)
    $rawCertData = [System.Convert]::ToBase64String($rawCertData);
    

    The only thing that is strange to me is that the byte arrays are different when using the web form, but it appears that X509Certificate2.Import() knows how to parse it correctly in either case.