PowerShell - Read Certificate Issuer using public key - powershell

Could someone guide me to read the issuer from public key?
I used to do this earlier using the below piece of code.
$Cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$cert.Import([Convert]::FromBase64String($KeyCred.key))
But its no more working.
Getting the below error.
MethodInvocationException: Exception calling "Import" with "1" argument(s):
"X509Certificate is immutable on this platform. Use the equivalent constructor instead."
I am using PowerShell 7. Appreciate any help on this.
Thanks in advance.

If your $KeyCred.key stores a base64-encoded string that represents the certificate (not public key), then you can use appropriate constructor like this:
$cert = [Security.Cryptography.X509Certificates.X509Certificate2]::new([Convert]::FromBase64String($KeyCred.key))

Related

How do you set permissions on a certificate in the Windows Certificate Store through PowerShell 7?

Every resource I've found so far, such as this question, boils down to:
Get the certificate as an X509Certificate2
Cast the PrivateKey property to RSACryptoServiceProvider
Do stuff involving CspKeyContainerInfo property on the private key
This works in PowerShell 5, but in PowerShell 7, the PrivateKey property is an RSACng, not an RSACryptoServiceProvider, and so step 2 doesn't work.
FYI, PrivateKey was deprecated. You are now required to use the GetRSAPrivateKey extension method.
I cannot find any documentation, but it appears that .Net Framework used to return an RSA that also implemented RSACryptoServiceProvider which is where we could get the CspKeyContainerInfo, but now we are required to grab the key RSA derived type RSACng which is returned by the extension method. From here you can grab properties like the $cert.Key.UniqueName

Unable to access ssl certificate from octopus library as X509Certificate2 object using powershell

I am trying to create a jwt token using a pfx which,I have stored in Octopus library. For this I have to create an object of X509Certificate2, which takes certificate path and password as input. Can someone please suggest a way to do this using powershell?
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($certpath,'password')
I have been through some documents as per how to access certificate variables in octopus but how can I use them to create an object of X509Certificate2.
https://octopus.com/docs/deployment-process/variables/certificate-variables
After going through Microsoft and Octopus documentation I have managed to get it to work. Octopus store the certificate as a base64 encoded string in a variable named as Cert.Pfx and constructor of X509Certificate2 takes a byte array as a first parameter. So as a first step I just needed to convert the base64 encoded string to byte array.
$certbytearray=[System.Convert]::FromBase64String($OctopusParameters["Cert.Pfx"])
$CertPassKey="password"
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($certbytearray,$CertPassKey)
#Biplab Thanks for posting your solution; it saved me a lot of headache! I had a slightly different situation without a password and I found that the X509Certificate2 constructor interpreted the byte array as a file name when I tried to call without the password even though the documentation indicates it should accept just a byte array.
I got it to work without the password by doing an import instead.
$certbytearray=[System.Convert]::FromBase64String($OctopusParameters["mycert.Pfx"])
$mycert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$mycert.import($certbytearray)
write-host $mycert.ThumbPrint
if ($mycert.HasPrivateKey)
{ write-host "has private key"}

How can I use RSA signatures in powershell?

I'm writing a powershell script where I need to verify the signature of a string using public / private key cryptography. I looked around and only found a "untested" demo of RSA implemented directly in powershell.
Is it possible to use a secure RSA implementation in powershell and if not, are there any other private / public key signature algorithms available?
Can you use .Net objects in your script? Just instantiate a .Net RSACryptoServiceProvider object and load your public and/or private key information. Then you can call any of the Encrypt, Decrypt, SignData or VerifyData functions, as you would in, say, C# code.
$rsa = New-Object -TypeName System.Security.Cryptography.RSACryptoServiceProvider
$rsa.FromXmlString("<RSAKeyValue>your public / private key info here</RSAKeyValue>")
$bytes = GetYourDataAsByteArray()
$decryptedBytes = $rsa.Decrypt($bytes, $true)
// don't forget to dispose when you're done!
$rsa.Dispose()

CryptoAPI - how to extract RSA public key from private

Using windows CryptoAPI, is it possible to get public RSA key from a private key which was imported (not generated)?
If I use CryptGenKey, I can call CryptExportPublicKeyInfo and CryptImportPublicKeyInfo to obtain the public key handle. However, when I try to do the same thing with private key decoded from PEM and imported using:
CryptImportKey(hCSP, pKeyBuf, cbKeyBuf, 0, CRYPT_EXPORTABLE, &hPrivKey)
import of the private key succeeds and I have a valid handle but the subsequent call to CryptExportPublicKeyInfo fails with "Key does not exist" error. It looks like there's another call missing between CryptImportKey and CryptExportPublicKeyInfo, but I can not find that API call.
The problem with exporting/importing the public key was because private key was generated using AT_SIGNATURE, instead of AT_EXCHANGE. See the explanation and the example code

How to do LDAP query using Powershell and PKI

I'm new to Powershell, and I'm trying to do a secure LDAP query using PKI authentication. I'm getting stuck on how to set the certificate and key. Based on Googling/research, I have some of the basics, e.g.:
$connection = new-object System.DirectoryServices.Protocols.LDAPConnection('$domainName:$portNum')
[string[] $get] = "$attribute1", "$attribute2", "attribute3"
$request = new-object System.DirectoryServices.Protocol.SearchRequest("$targetOu", "$filter", "subtree", $get)
$response = new-object $connection.SendRequest($request)
Like I said, I'm getting stuck on how to set/send the certificate and key. I thought I could do $connection.ClientCertificates = $path, but that property is read-only. I also thought I had to do something with $System.Net.NetworkCredential, but I'm not sure if the cert and key actually correspond to username and password. I referred to a Perl script that did an LDAP query and used PKI, and you could do:
clientcert => '/path/to/cert.pem'
clientkey => '/path/to/key.pem'
What's the equivalent for Powershell? Do I have to do something with System.Security.Cryptography.X509Certificates.X509Certificate?
Any help would be appreciated!
$connection.ClientCertificates.Add($cert)
the $cert must be X509Certificate class
and get certificates from store using
$allPersonalCerts = #( Get-ChildItem -Path 'Cert:\CurrentUser\my' )
It returns array of X509Certificate objects (or X509Certificate2 which is child class for X509Certificate )
NB: When doing PowerShell programming, you can always search for help by googling C# or VB.net solutions. This is .Net and examples on .net-oriented languages just differ on syntax