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

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics