How correctly save and import p7b certificate
Hi,
I have this information in txt format:
-----BEGIN CERTIFICATE REQUEST-----
xxxxxxxx
-----END CERTIFICATE REQUEST-----
-----BEGIN RSA PRIVATE KEY-----
yyyyyyyy
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
zzzzzzz
-----END CERTIFICATE-----
How to save all information correctly and import it to My certificate and IIS store?
I import certificate but it does not recognize the key, should I save as pfx or p7b?
If i run certutil -repairstore my "thumbprint" I get: Cannot find the certificate and private key for decryption.
thanks
July 23rd, 2012 11:22am
You can try this approach:
http://en-us.sysadmins.lv/Lists/Posts/Post.aspx?ID=46My weblog: http://en-us.sysadmins.lv
PowerShell PKI Module: http://pspki.codeplex.com
Windows PKI reference:
on TechNet wiki
Free Windows Admin Tool Kit Click here and download it now
July 23rd, 2012 2:21pm
You can try this approach:
http://en-us.sysadmins.lv/Lists/Posts/Post.aspx?ID=46My weblog: http://en-us.sysadmins.lv
PowerShell PKI Module: http://pspki.codeplex.com
Windows PKI reference:
on TechNet wiki
July 23rd, 2012 2:26pm
I wonder why it is not posible save as p7b file and import to certificate store?
Free Windows Admin Tool Kit Click here and download it now
July 23rd, 2012 3:11pm
natively, CryptoAPI do not support unencrypted private keys outside the PKCS12 container and CryptoAPI almost never (I never seen that) exports certificate and private key separately and in unencrypted state. I assume that your file was generated by OpenSSL
or something similar. Since OpenSSL uses big-endian encoding, CryptoAPI uses little-endian encodings and some manual stuff is required. Just try the script (there is example usage) and check if it works.My weblog: http://en-us.sysadmins.lv
PowerShell PKI Module: http://pspki.codeplex.com
Windows PKI reference:
on TechNet wiki
July 23rd, 2012 3:13pm
natively, CryptoAPI do not support unencrypted private keys outside the PKCS12 container and CryptoAPI almost never (I never seen that) exports certificate and private key separately and in unencrypted state. I assume that your file was generated by OpenSSL
or something similar. Since OpenSSL uses big-endian encoding, CryptoAPI uses little-endian encodings and some manual stuff is required. Just try the script (there is example usage) and check if it works.My weblog: http://en-us.sysadmins.lv
PowerShell PKI Module: http://pspki.codeplex.com
Windows PKI reference:
on TechNet wiki
Free Windows Admin Tool Kit Click here and download it now
July 23rd, 2012 3:19pm
Hi,
I create ps1 file "Convert-OpenSSLPrivateKey.ps1" and paste
function "Convert-OpenSSLPrivateKey".
I created file.pem as in your article and run the script. But I think I miss something because it did not worked.
July 26th, 2012 6:00am
you need to dot-source the file, instead of executing it:
. .\scriptfile.ps1
and then run Convert-OpenSSLPrivateKey function with required parameters.My weblog: http://en-us.sysadmins.lv
PowerShell PKI Module: http://pspki.codeplex.com
Windows PKI reference:
on TechNet wiki
Free Windows Admin Tool Kit Click here and download it now
July 26th, 2012 7:36am
thank you, I got now error but also no output file, do I have to install openssl?
July 26th, 2012 9:03am
what kind of error?My weblog: http://en-us.sysadmins.lv
PowerShell PKI Module: http://pspki.codeplex.com
Windows PKI reference:
on TechNet wiki
Free Windows Admin Tool Kit Click here and download it now
July 26th, 2012 9:19am
I am not getting any output or any error
it is strange but command just run and thats all, maybe my key is corupted?
July 26th, 2012 9:50am
my bet is that you incorrectly call the command. Can you show a screenshot from the console?My weblog: http://en-us.sysadmins.lv
PowerShell PKI Module: http://pspki.codeplex.com
Windows PKI reference:
on TechNet wiki
Free Windows Admin Tool Kit Click here and download it now
July 26th, 2012 1:54pm
July 26th, 2012 2:44pm
cert.pem looks like this:
-----BEGIN RSA PRIVATE KEY-----
o1YUZQKBgEFHtheYYGVA9iZerowzOe2TuO/NEfO8lflmtPB8m3U0ICn+a+JcJbtz
JyckwN7aRrt2eSGX2pBD5nx6u2s9Tqj/aQX0skaElyQrryVb9zjHgK11TntC42tl
UBasHW75iIILqfX1gc/b+L6b7l7dDeGTqPT4vozHF1R9Pq8cRXTt
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
Y29tL3JhcGlkc3NsLmNydDANBgkqhkiG9w0BAQUFAAOCAQEAPi9+jm1o+v6z4O3b
IwkPLPlI4EfFUw04CbajnPjLRE5Ri0C1SnzHHD9iGOHKBBZA/rSH16r36APounsB
UvhvrKBQXJ/l08nfiTtnmwNndR/9TUHMZsZPlW7efi/UwPiE4OVMWkaZXNbmLZq/
hrOJHQ==
-----BEGIN CERTIFICATE-----
Script looks like this:
function Convert-OpenSSLPrivateKey {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true, Position = 0)]
[string]$InputPath,
[Parameter(Mandatory = $true, Position = 1)]
[string]$OutputPath
)
$File = Get-Item $InputPath -Force -ErrorAction Stop
if ($PSBoundParameters.Debug) {$DebugPreference = "continue"}
function Get-ASNLength ($RawData, $offset) {
$return = "" | Select FullLength, Padding, LengthBytes, PayLoadLength
if ($RawData[$offset + 1] -lt 128) {
$return.lengthbytes = 1
$return.Padding = 0
$return.PayLoadLength = $RawData[$offset + 1]
$return.FullLength = $return.Padding + $return.lengthbytes + $return.PayLoadLength + 1
} else {
$return.lengthbytes = $RawData[$offset + 1] - 128
$return.Padding = 1
$lengthstring = -join ($RawData[($offset + 2)..($offset + 1 + $return.lengthbytes)] | %{"{0:x2}" -f $_})
$return.PayLoadLength = Invoke-Expression 0x$($lengthstring)
$return.FullLength = $return.Padding + $return.lengthbytes + $return.PayLoadLength + 1
}
$return
}
function Get-NormalizedArray ($array) {
$Powers = 1..12 | %{[Math]::Pow(2,$_)}
if ($Powers -notcontains $array.Length) {
$MatchPower = $Powers -lt $array.Length | select -Last 1
$array = $array[($array.Length - $MatchPower)..($array.Length - 1)]
}
[array]::Reverse($array)
[Byte[]]$array
}
# parse content
$Text = [IO.File]::ReadAllText($File)
Write-Debug "Extracting certificate information..."
if ($Text -match "(?msx).*-{5}BEGIN\sCERTIFICATE-{5}(.+)-{5}END\sCERTIFICATE-{5}") {
$RawData = [Convert]::FromBase64String($Matches[1])
try {$Cert = New-Object Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList @(,$RawData)}
catch {Write-Warning "The data is invalid."; return}
Write-Debug "X.509 certificate is correct."
} else {Write-Warning "Missing certificate file."; return}
if ($Text -match "(?msx).*-{5}BEGIN\sPRIVATE\sKEY-{5}(.+)-{5}END\sPRIVATE\sKEY-{5}") {
Write-Debug "Processing Private Key module."
$Bytes = [Convert]::FromBase64String($matches[1])
if ($Bytes[0] -eq 48) {Write-Debug "Starting asn.1 decoding."}
else {Write-Warning "The data is invalid."; return}
$offset = 0
# main sequence
Write-Debug "Process outer Sequence tag."
$return = Get-ASNLength $Bytes $offset
Write-Debug "outer Sequence length is $($return.PayloadLength) bytes."
$offset += $return.FullLength - $return.PayloadLength
Write-Debug "New offset is: $offset"
# zero integer
Write-Debug "Process zero byte"
$return = Get-ASNLength $Bytes $offset
Write-Debug "outer zero byte length is $($return.PayloadLength) bytes."
$offset += $return.FullLength
Write-Debug "New offset is: $offset"
# algorithm identifier
Write-Debug "Proess algorithm identifier"
$return = Get-ASNLength $Bytes $offset
Write-Debug "Algorithm identifier length is $($return.PayloadLength) bytes."
$offset += $return.FullLength
Write-Debug "New offset is: $offset"
# octet string
$return = Get-ASNLength $Bytes $offset
Write-Debug "Private key octet string length is $($return.PayloadLength) bytes."
$offset += $return.FullLength - $return.PayLoadLength
Write-Debug "New offset is: $offset"
} elseif ($Text -match "(?msx).*-{5}BEGIN\sRSA\sPRIVATE\sKEY-{5}(.+)-{5}END\sRSA\sPRIVATE\sKEY-{5}") {
Write-Debug "Processing RSA KEY module."
$Bytes = [Convert]::FromBase64String($matches[1])
if ($Bytes[0] -eq 48) {Write-Debug "Starting asn.1 decoding"}
else {Write-Warning "The data is invalid"; return}
$offset = 0
Write-Debug "New offset is: $offset"
} else {Write-Warning "The data is invalid"; return}
# private key sequence
Write-Debug "Process private key sequence."
$return = Get-ASNLength $Bytes $offset
Write-Debug "Private key length (including inner ASN.1 tags) is $($return.PayloadLength) bytes."
$offset += $return.FullLength - $return.PayLoadLength
Write-Debug "New offset is: $offset"
# zero integer
Write-Debug "Process zero byte"
$return = Get-ASNLength $Bytes $offset
Write-Debug "Zero byte length is $($return.PayloadLength) bytes."
$offset += $return.FullLength
Write-Debug "New offset is: $offset"
# modulus
Write-Debug "Processing private key modulus."
$return = Get-ASNLength $Bytes $offset
Write-Debug "Private key modulus length is $($return.PayloadLength) bytes."
$modulus = $Bytes[($offset + $return.FullLength - $return.PayLoadLength)..($offset + $return.FullLength - 1)]
$modulus = Get-NormalizedArray $modulus
$offset += $return.FullLength
Write-Debug "New offset is: $offset"
# public exponent
Write-Debug "Process private key public exponent."
$return = Get-ASNLength $Bytes $offset
Write-Debug "Private key public exponent length is $($return.PayloadLength) bytes."
Write-Debug "Private key public exponent padding is $(4 - $return.PayLoadLength) byte(s)."
$padding = New-Object byte[] -ArgumentList (4 - $return.PayLoadLength)
[Byte[]]$PublicExponent = $padding + $Bytes[($offset + $return.FullLength - $return.PayLoadLength)..($offset + $return.FullLength - 1)]
$offset += $return.FullLength
Write-Debug "New offset is: $offset"
# private exponent
Write-Debug "Process private key private exponent."
$return = Get-ASNLength $Bytes $offset
Write-Debug "Private key private exponent length is $($return.PayloadLength) bytes."
$PrivateExponent = $Bytes[($offset + $return.FullLength - $return.PayLoadLength)..($offset + $return.FullLength - 1)]
$PrivateExponent = Get-NormalizedArray $PrivateExponent
$offset += $return.FullLength
Write-Debug "New offset is: $offset"
# prime1
Write-Debug "Process Prime1."
$return = Get-ASNLength $Bytes $offset
Write-Debug "Prime1 length is $($return.PayloadLength) bytes."
$Prime1 = $Bytes[($offset + $return.FullLength - $return.PayLoadLength)..($offset + $return.FullLength - 1)]
$Prime1 = Get-NormalizedArray $Prime1
$offset += $return.FullLength
Write-Debug "New offset is: $offset"
# prime2
Write-Debug "Process Prime2."
$return = Get-ASNLength $Bytes $offset
Write-Debug "Prime2 length is $($return.PayloadLength) bytes."
$Prime2 = $Bytes[($offset + $return.FullLength - $return.PayLoadLength)..($offset + $return.FullLength - 1)]
$Prime2 = Get-NormalizedArray $Prime2
$offset += $return.FullLength
Write-Debug "New offset is: $offset"
# exponent1
Write-Debug "Process Exponent1."
$return = Get-ASNLength $Bytes $offset
Write-Debug "Exponent1 length is $($return.PayloadLength) bytes."
$Exponent1 = $Bytes[($offset + $return.FullLength - $return.PayLoadLength)..($offset + $return.FullLength - 1)]
$Exponent1 = Get-NormalizedArray $Exponent1
$offset += $return.FullLength
Write-Debug "New offset is: $offset"
# exponent2
Write-Debug "Process Exponent2."
$return = Get-ASNLength $Bytes $offset
Write-Debug "Exponent2 length is $($return.PayloadLength) bytes."
$Exponent2 = $Bytes[($offset + $return.FullLength - $return.PayLoadLength)..($offset + $return.FullLength - 1)]
$Exponent2 = Get-NormalizedArray $Exponent2
$offset += $return.FullLength
Write-Debug "New offset is: $offset"
# coefficient
Write-Debug "Process Coefficient."
$return = Get-ASNLength $Bytes $offset
Write-Debug "Coeicient length is $($return.PayloadLength) bytes."
$Coefficient = $Bytes[($offset + $return.FullLength - $return.PayLoadLength)..($offset + $return.FullLength - 1)]
$Coefficient = Get-NormalizedArray $Coefficient
# creating Private Key BLOB structure
Write-Debug "Calculating key length."
$bitLen = "{0:X4}" -f $($modulus.Length * 8)
Write-Debug "Key length is $($modulus.Length * 8) bits."
[byte[]]$bitLen1 = iex 0x$([int]$bitLen.Substring(0,2))
[byte[]]$bitLen2 = iex 0x$([int]$bitLen.Substring(2,2))
[Byte[]]$PrivateKey = 0x07,0x02,0x00,0x00,0x00,0x24,0x00,0x00,0x52,0x53,0x41,0x32,0x00
[Byte[]]$PrivateKey = $PrivateKey + $bitLen1 + $bitLen2 + $PublicExponent + ,0x00 + `
$modulus + $Prime1 + $Prime2 + $Exponent1 + $Exponent2 + $Coefficient + $PrivateExponent
$Base = [Convert]::ToBase64String($PrivateKey)
$TempFile = [IO.Path]::GetTempFileName()
$CertFileName = $TempFile + ".cer"
$KeyFileName = $TempFile + ".key"
[IO.File]::WriteAllBytes($CertFileName, $Cert.RawData)
Set-Content -Path $KeyFileName -Value $Base -Encoding Ascii
certutil -f -MergePFX $CertFileName $OutputPath
$TempFile, $CertFileName, $KeyFileName | %{del $_ -Force}
}
Free Windows Admin Tool Kit Click here and download it now
July 26th, 2012 3:03pm
You missed a dot in the dot source command. In your case you need to run two commands:
. .\scriptfilename.ps1
Convert-OpenSSLPrivateKey -InputPath .\pemfile.pem -OutputPath .\converted.pfx
Note the first dot in the first command. After first command a function will be loaded to your PowerShell session and the second line will actually execute it.My weblog: http://en-us.sysadmins.lv
PowerShell PKI Module: http://pspki.codeplex.com
Windows PKI reference:
on TechNet wiki
July 26th, 2012 4:16pm
still have no luck.
And what is: "..\scriptfilename.ps1". I don't have such script:
PS C:\temp\cert> . .\scriptfilename.ps1
The term '.\scriptfilename.ps1' is not recognized as the name of a cmdlet, function, script file, or operable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:2
+ . <<<< .\scriptfilename.ps1
+ CategoryInfo : ObjectNotFound: (.\scriptfilename.ps1:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
And after I run this command still no output:
Convert-OpenSSLPrivateKey
-InputPath .\pemfile.pem
-OutputPath .\converted.pfx
Free Windows Admin Tool Kit Click here and download it now
July 27th, 2012 1:12am
still have no luck.
And what is: "..\scriptfilename.ps1". I don't have such script:
PS C:\temp\cert> . .\scriptfilename.ps1
The term '.\scriptfilename.ps1' is not recognized as the name of a cmdlet, function, script file, or operable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:2
+ . <<<< .\scriptfilename.ps1
+ CategoryInfo : ObjectNotFound: (.\scriptfilename.ps1:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
And after I run this command still no output:
Convert-OpenSSLPrivateKey
-InputPath .\pemfile.pem
-OutputPath .\converted.pfx
I run these two commands, till no output:
PS C:\temp\cert> . .\Convert-OpenSSLPrivateKey
PS C:\temp\cert> .\Convert-OpenSSLPrivateKey -InputPath .\cert.pem -OutputPath .\file.pfx
July 27th, 2012 1:12am
. .\Convert-OpenSSLPrivateKey.ps1
Convert-OpenSSLPrivateKey -InputPath .\cert.pem -OutputPath .\file.pfx
you just need to put your file name in the first line. This looks as exact command you need to run.My weblog: http://en-us.sysadmins.lv
PowerShell PKI Module: http://pspki.codeplex.com
Windows PKI reference:
on TechNet wiki
Free Windows Admin Tool Kit Click here and download it now
July 27th, 2012 1:34am
thank you for replay,
I got error:
WARNING: Missing certificate file.
Maybe I need to insert
Primary Intermediate CA and
Secondary Intermediate CA?
July 27th, 2012 1:46am
this is because you have invalid header sequence:
-----BEGIN CERTIFICATE-----
Y29tL3JhcGlkc3NsLmNydDANBgkqhkiG9w0BAQUFAAOCAQEAPi9+jm1o+v6z4O3b
IwkPLPlI4EfFUw04CbajnPjLRE5Ri0C1SnzHHD9iGOHKBBZA/rSH16r36APounsB
UvhvrKBQXJ/l08nfiTtnmwNndR/9TUHMZsZPlW7efi/UwPiE4OVMWkaZXNbmLZq/
hrOJHQ==
-----BEGIN CERTIFICATE-----
in the last line BEGIN must be replaced with END. However, this is not valid X.509 certificate. It is too small and it doesn't look as a DER-encoded file.My weblog: http://en-us.sysadmins.lv
PowerShell PKI Module: http://pspki.codeplex.com
Windows PKI reference:
on TechNet wiki
Free Windows Admin Tool Kit Click here and download it now
July 27th, 2012 2:05am
this is because you have invalid header sequence:
-----BEGIN CERTIFICATE-----
Y29tL3JhcGlkc3NsLmNydDANBgkqhkiG9w0BAQUFAAOCAQEAPi9+jm1o+v6z4O3b
IwkPLPlI4EfFUw04CbajnPjLRE5Ri0C1SnzHHD9iGOHKBBZA/rSH16r36APounsB
UvhvrKBQXJ/l08nfiTtnmwNndR/9TUHMZsZPlW7efi/UwPiE4OVMWkaZXNbmLZq/
hrOJHQ==
-----BEGIN CERTIFICATE-----
in the last line BEGIN must be replaced with END. However, this is not valid X.509 certificate. It is too small and it doesn't look as a DER-encoded file.My weblog: http://en-us.sysadmins.lv
PowerShell PKI Module: http://pspki.codeplex.com
Windows PKI reference:
on TechNet wiki
July 27th, 2012 2:07am
thank you Vadims it worked, I have certificate now. Your script works fine.
best wishes from Lt :)
Free Windows Admin Tool Kit Click here and download it now
July 27th, 2012 3:28am