How to read pfx file's thumbprint without prompt for password - powershell

I have a need to obtain a thumbprint from a pfx file on the filesystem without being prompted for a password that requires manual input.
I'm running this as part of an installer where the user specifies the path to the certificate on the filesystem (Not in the store). And the user specifies the password for the certificate. From that point, i need the thumbprint.
So this is simply a matter of discovering a tool which i can pass a path and password to a pfx file and return the thumbprint. I've tried several tools, but even OpenSSL compiled for windows, and it still prompts for the password and gives back a lot more info than just the thumbprint. It needs to be 100% programmatic and without further user intervention.
I'd love to hear any ideas on how to do this. This will be on Windows Server machines only. Thanks!

I found a way to do this - it involves downloading OpenSSL for windows and using that tool to convert and using powershell to read it out.
Conversion
& openssl pkcs12 -in C:\LocalHost.pfx -out C:\mycertificates.crt -nokeys -clcerts -passin pass:ActualPassword
Read In
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("C:\mycertificates.crt")
$thumbprint = $cert.Thumbprint
write-host $thumbprint
So i had to convert to crt/cer first and then read using X509Certificate2.

When creating .pfx (pkcs#12) file, the internal storage containers, called "SafeBags", may also be encrypted and signed.
By default, OpenSSL encrypts the certificate along with its private key, which means it is not possible to get its thumbprint without knowing password.
When creating a new pfx, you can explicitly add -certpbe NONE to avoid encrypting the certificate.
For more details check -certpbe OpenSSL's man page

Related

Convert cert to pfx or p12 file format

Convert .crt, .csr, and .key files to .pfx or .p12 using powershell on Windows server 2016.
I have .cert, .csr, and .key files. But in order to execute the "netsh http add sslcert ..." command, I need the .pfx or .p12 file. And I need this to be done in powershell. Openssl is not an option.
I have accomplished the above using openssl. But Im restricted from downloading software now, so thats not an option any more. Im looking for equivalent of openssl pkcs12 -export -out domain.name.pfx -inkey key.key -in cert.crt command in powershell.
This is an old thread but since I was stuck on the exact same problem and finally found the correct answer that wasn't just everyone shouting to use openssl which sometimes isn't available I thought I'd share here for the next lucky soul.
There is a built-in windows utility call CertUtil which can be called from PS and will do exactly this. It's available out of the box at least as far back as server 2012, cant' speak to older versions.
certutil –MergePFX certfile.cer certfile.pfx
A couple things to keep in mind, the -MergePFX only prompts for the certfile not the key so:
Private key file must have .KEY extension.
Cert and key files must have the same base file name.
Cert and key file must be in the same directory.
If you can use .NET Core 3.0:
Load the certificate via cert = new X509Certificate2(certFile)
If the keyfile is PEM encoded (e.g. starts with "----- BEGIN ") then load it, remember what type it is (human or software), find the base64 contents between the header and footer, and run that through Convert.FromBase64String to get the BER/DER encoded format of the key.
key = RSA.Create()
key.ImportPkcs8PrivateKey(bytes, out _), key.ImportEncryptedPkcs8PrivateKey(password, bytes, out _), or key.ImportRSAPrivateKey(bytes, out _); depending on what format the private key file is in.
certWithKey = cert.CopyWithPrivateKey(key)
File.WriteAllBytes("new.pfx", certWithKey.Export(X509ContentType.Pkcs12, password))
If you can use .NET Core 2.1 / .NET Framework 4.7.2:
Load the cert, as above.
Load the key manually:
RSAPrivateKey
How to get RSACryptoServiceProvider public and private key only in c#
How to parse(Convert to RSAParameters) X.509 private key in C#?
PKCS#8 PrivateKeyInfo
Digital signature in c# without using BouncyCastle
PKCS#8 EncryptedPrivateKeyInfo
X509Certificate2.Import with NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG (ImportEncryptedPkcs8Overwrite method)
Use CopyWithPrivateKey/Export/WriteAllBytes as above
If you're stuck on something older:
You could try loading the cert, manually loading the key into an RSACryptoServiceProvider, using cert.set_PrivateKey, and exporting that. Only works on .NET Framework (eliminated from .NET Core because it has too many side effects, especially when done to a cert already in a persisted certificate store).

How to export base64 encoded x.509 certificate with private key without using OpenSSL

I have a Root CA certificate with .cer extension with private key.
I have to Export that certificate as .pem extension with private key in base64 encoded format without using OpenSSl.
I am not able to do this with mmc.
Is there any tool or script available for converting certificate from pfx to pem format without using openssl in windows.
Please help me by sharing code or any scripts or commands etc...
Thanks...
You could use the window's certutil tool to encode a file to Base64. Try this command:
certutil -encode {YOUR_PFX_FILE} {CONVERTED_FILE_NAME}
This command should put the appropriate certificate header too.

Why my certificate can't be used for PowerShell code signing?

Windows 7 x64, PowerShell 4.0.
I am beginner in the working with the digital signatures, therefore I read these articles before:
https://technet.microsoft.com/en-us/magazine/2008.04.powershell.aspx
https://msdn.microsoft.com/en-us/library/bfsktky3%28v=vs.100%29.aspx
https://msdn.microsoft.com/en-us/library/f5cs0acs%28v=vs.100%29.aspx
I need to sign my PowerShell scripts. These scripts are to be accessible by all users of our Windows domain. But at first I want to learn to do it on my computer.
I set execution policy to the AllSigned value (with admin rights):
Set-ExecutionPolicy -Scope LocalMachine -ExecutionPolicy AllSigned
According Don Jones article I created my own certificate (through the Developer Command Prompt for VS2015 [i.e. through the cmd.exe], with admin rights):
cd c:\temp
makecert -n "CN=Andrey Bushman" -a md5 -r -sv Andrey.Bushman.pvk -ss Root -sr localMachine Andrey.Bushman.cer
I got the Andrey.Bushman.cer and Andrey.Bushman.pvk files in my current directory. The first of them has 1 kb size, and the second of them has 2 kb size. So, I see the private key size is more than size of certificate.
Question #1
Does it mean that my certificate don't include the copy of my private key?
Now I see new item in the certificate store:
PS Cert:\LocalMachine\Root> Get-ChildItem | where -Property Issuer -EQ "CN=Andrey Bushman"
Directory: Microsoft.PowerShell.Security\Certificate::LocalMachine\Root
Thumbprint Subject
---------- -------
CF26A00BB7C8EB2B1EA66CA307C4B5025F636F9A CN=Andrey Bushman
Then Don Jones did it:
makecert -pe -n "CN=MyCertificate" -ss MY
–a sh1 -eku 1.3.6.1.5.5.7.3.3 -iv root.pvk
–c root.cer
Question #2
Why he did it? Before he did it we already have our certificate in the cert:LocalMachine\Root storage.
By analogy I did it for my case:
makecert -pe -n "CN=Andrey Bushman" -ss MY -a md5 -iv Andrey.Bushman.pvk -ic Andrey.Bushman.cer
But I get nothing when I launch this:
gci cert:\CurrentUser\My -codesigning
Without the -codesigning flag I get this:
PS C:\temp> gci cert:\CurrentUser\My
Directory: Microsoft.PowerShell.Security\Certificate::CurrentUser\My
Thumbprint Subject
---------- -------
8F0D753ACA7F6631C3D967921BD06E158E1AB1AF CN=Andrey Bushman
Question #3
Why I get nothing when I use the -codesigning flag?
Ok I try to sign some file and get the problem:
PS C:\temp> $cert = #(gci cert:\CurrentUser\My)[0]
PS C:\temp> Set-AuthenticodeSignature -FilePath .\123.ps1 -Certificate $cert
Set-AuthenticodeSignature : It isn't possible to sign the code. The specified certificate isn't suitable for the code signing
а.
line:1 char:1
+ Set-AuthenticodeSignature -FilePath .\123.ps1 -Certificate $cert
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Set-AuthenticodeSignature], PSArgumentException
+ FullyQualifiedErrorId : Argument,Microsoft.PowerShell.Commands.SetAuthenticodeSignatureCommand
Question #4
How can I make my certificate suitable for the code signing?
UPD
I can't ask my question here, because I can't register on that site (I have nothing to my email). I wrote the letters to email of support team but they answer never. I tried to do it some years ago and I tried to do it some days ago again, but I get the same result.
Q1: Does it mean that my certificate don't include the copy of my private key?
A1: Yes. Certificates can be swapped around because they don't include the private key. The private key typically only exists on one computer, with a backup copy archived in a secure location. Anyone that gets access to the private key can sign anything they want and it looks just like you did it. (A more complete answer to this question is outside the typical scope of Stack Overflow, but there are many good resources available on PKI.)
Q2: Why he did it?
Q3: Why I get nothing when I use the -codesigning flag?
A2/A3: The first time he ran makecert, he created the root certificate. A root certificate is specifically for issuing other certificates, which is why it does not show up as a code signing certificate. This second time, he is making the actual certificate. The -eku option specifies the certificate options to use, which can be anything from a root certificate, code signing certificate, or digital signature, to more advanced things like data encryption or client authentication.
Q4: How can I make my certificate suitable for the code signing?
A4: I don't have a lot of experience with makecert.exe, as my company has a contract with Cybertrust such that I can generate as many certificates as I need without worrying about the cost for each one. (Yes, it's a nice luxury.) This means I can't answer questions on makecert.exe, its syntax, or the -eku options to use.
In many ways, makecert is doing a lot of things for you behind the scenes, but the basic things you need are the same:
You have to generate a public / private key pair.
You have to create a certificate request that specifies "code signing".
You have to use the private key to sign your certificate request.
The certificate authority uses that request to generate the certificate.
The generated certificate can only be installed using the private key that signed the request.
Once you have the certificate installed, it will show up using the -codesigning option and will be usable by Set-AuthenticodeSignature.
I would suggest using the makecert documentation and other digital certificate resources to find the right options, but based on my quick glance at the links you posted, it appears you have the majority of the information you need. Having done digital certificates for many years now, it appears to me that the biggest thing that will help you is to get more familiar with how Public Key Infrastructure (PKI) works, especially with regards to how a certificate chain works and is verified. It takes time to get it all down, and code signing in Powershell is not the easiest place to start, but if you're going to do a lot of it, it's worth the time investment.

Importing .pfx certificate and signing binaries

In our build procedure, we are using .pfx file to sign our generated binaries, while referencing the time stamp server.
Is it possible to import/install this into the build machine (Windows Server 8.x) and sign our binaries, instead of manually referring .pfx file to SignTool.exe?
Yes it is, here is the command which signs TestLibrary.dll with "Test Certificate" from "CodeSigningCertificates" machine store:
signtool sign /v /sm /s CodeSigningCertificates /n "Test Certificate" c:\TestFiles\TestLibrary.dll
Here are some links with details on signtool and command line parameters:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa387764%28v=vs.85%29.aspx
https://msdn.microsoft.com/en-us/library/windows/desktop/aa388170%28v=vs.85%29.aspx
http://blogs.msdn.com/b/winsdk/archive/2009/11/13/steps-to-sign-a-file-using-signtool-exe.aspx
Just be aware that user who runs the build must have permission to access certain certificate location and store and have access to private key.

How to embed hash in exe file with signtool.exe

I am using signtool.exe to sign exe file.
I am trying to embed my exe file with the .pfx certificate along with the signed hash of exe(generated signed hash using openssl). I am able to sign only with certificate. But I need to embed the signed hash in the exe as well. Probably signtool.exe sign /as could help. /as option does not expect any argument so not able to pass my hash there.
Could someone please help me sign my exe with certificate and hash.
Thanks,
The version of Signtool shipped with the Windows 10 SDK includes the capability to embed a signed hash into an exe.
From the following page:
https://vcsjones.com/2017/05/07/custom-authenticode-signing/
Starting in the Windows 10 SDK, two new command line switches are available, dg and di. Recall that a signature is always performed on a hash on Authenticode. The dg option changes signtool’s behavior to output a digest that you can sign using anything you’d like. Let’s try this on a copy of notepad.exe.
signtool sign /dg "C:\scratch\dir" /fd SHA256 /f public-cert.cer notepad.exe
This takes a file to a public certificate - there is no key in
public-cert.cer. You could also use the /sha1 option to specify a
certificate in the certificate store that also has only a public key.
This will output a few files in the “C:\scratch\dir” directory. The
digest is the one with the “.dig” extension. This file will have the
Base64 encoded digest to sign. Next, using your custom tool, sign the
digest with the private key for the certificate. You should decode the
Base64 signature before signing if the signing API expects a raw
binary digest.
Next, encode your signature in base64 and place it in a file in the
“C:\scratch\dir” directory with the same name as the digest file, with
the “signed” extension. For example, “notepad.exe.dig.signed”.
The next step is to ingest the signed digest along with the rest of
the Authenticode signature to complete the signing.
signtool sign /di "C:\scratch\dir" notepad.exe
This will complete the signing process, and we now have our own signed
copy of notepad.exe. Appending a signature is done just as before,
except with the /as flag.
This provides great flexibility for signers to use non CSP / CNG
signing options, or offloading the signing process. Signtool can now
also sign just a plain digest file using the /ds option. If you have a
dedicated server for performing Authenticode signing, you can now use
the /dg, /ds, /di options so that only a very small file needs to be
moved to the signing server, instead of the entirely binary if they
are large in size.