+1 vote
by (160 points)

Our organization has a daily process where we upload a file to a client of ours using the RebEx libraries – ftp + SSL. The process worked without issue but our certificate was coming up on expiration and our IT department generated a new set. The certificate was sent to our counterparty who installed it and we updated the process to use the new certificate on our end, but we began getting the error " Unable to Acquire Private Key (0x80090014)” when we would try to connect to their server to upload the file.

I attempted to use the Sample Component (FtpWinFormClient.exe) to connect manually and it failed – the debug log for that attempt is below. We considered the possibility that the issue is on our counterparty’s end since very little has changed on our side (all we did was point to the new certificate file – it even uses the same Certificate password as the old file). However, when we attempted to make a manual connection with different FTP software (WS_FTP), we were able to successfully connect and manually upload the file, which again leads me to believe the problem is on our end.

Are you able to provide any additional info regarding the error message below’s meaning or causes? I would be happy to provide to you any additional information you require to assist in this matter.

Thank you.

11:27:20.727 Info Info: Connecting to REDACTED using Ftp 4.0.4700.0.
11:27:20.742 Info Info: Using proxy none.
11:27:20.914 Debug Info: Connection succeeded.
11:27:21.008 Info Response: 220 Welcome-to-REDACTED
11:27:21.039 Info Command: AUTH TLS
11:27:21.123 Info Response: 234 AUTH TLS OK.
11:27:21.201 Debug Info: Upgrading control connection to TLS/SSL.
11:27:21.279 Info TLS: State StateChange:Negotiating
11:27:21.310 Debug TLS: HandshakeMessage:ClientHello was sent.
11:27:21.651 Debug TLS: HandshakeMessage:ServerHello was received.
11:27:21.714 Debug TLS: HandshakeMessage:Certificate was received.
11:27:21.761 Debug TLS: HandshakeMessage:CertificateRequest was received.
11:27:21.792 Debug TLS: HandshakeMessage:ServerHelloDone was received.
11:27:21.823 Debug TLS: Verifying server certificate ('CN=REDACTED).
11:27:21.886 Debug TLS: Certificate verification result: Accept
11:27:21.917 Debug TLS: Client certificate authentication was requested.
11:27:21.948 Debug TLS: Suitable client certificate is available ('REDACTED).
11:27:21.980 Debug TLS: HandshakeMessage:Certificate was sent.
11:27:22.026 Debug TLS: HandshakeMessage:ClientKeyExchange was sent.
11:27:22.075 Info TLS: Performing client certificate authentication.
11:27:22.090 Debug TLS: Error while processing TLS packet: Rebex.Security.Certificates.CertificateException: Unable to acquire private key (0x80090014).
at Rebex.Security.Certificates.Certificate.b1cyy(Byte[] , SignatureHashAlgorithm , Int32 , Boolean )
at Rebex.Security.Certificates.Certificate.SignHash(Byte[] hash, SignatureHashAlgorithm alg, Boolean silent)
at gbMKS.QsaHcZ.RYVUe(Byte[] , Int32 , Int32 , 1RjReZZ )
at gbMKS.QsaHcZ.OnHandshakeReceived(Byte[] buffer, Int32 offset, Int32 count)
at gbMKS.1UaphuZ.2YjOc(Byte[] , Int32 , Int32 )
at gbMKS.1UaphuZ.1rsOcLZ()
11:27:22.121 Info TLS: Info Info:UnexpectedException
11:27:22.153 Info TLS: Alert Alert:Alert was sent.
11:27:22.184 Info TLS: State StateChange:Closed
11:27:22.199 Debug TLS: Closing TLS socket.
11:27:22.231 Error Info: Rebex.Net.TlsException: Unable to acquire private key (0x80090014). ---> Rebex.Net.TlsException: Unable to acquire private key (0x80090014). ---> Rebex.Security.Certificates.CertificateException: Unable to acquire private key (0x80090014).
at Rebex.Security.Certificates.Certificate.b1cyy(Byte[] , SignatureHashAlgorithm , Int32 , Boolean )
at Rebex.Security.Certificates.Certificate.SignHash(Byte[] hash, SignatureHashAlgorithm alg, Boolean silent)
at gbMKS.QsaHcZ.RYVUe(Byte[] , Int32 , Int32 , 1RjReZZ )
at gbMKS.QsaHcZ.OnHandshakeReceived(Byte[] buffer, Int32 offset, Int32 count)
at gbMKS.1UaphuZ.2YjOc(Byte[] , Int32 , Int32 )
at gbMKS.1UaphuZ.1rsOcLZ()
--- End of inner exception stack trace ---
at gbMKS.1UaphuZ.1rsOcLZ()
at gbMKS.1UaphuZ.qzm1d()
at gbMKS.l7gsR.sjyGnZ(TlsParameters )
at Rebex.Net.Ftp.1I1Vik(TlsParameters , FtpSecureUpgradeType )
at Rebex.Net.Ftp.2eOMSNZ(String , Int32 , TlsParameters , FtpSecurity )
--- End of inner exception stack trace ---
at Rebex.Net.Ftp.2eOMSNZ(String , Int32 , TlsParameters , FtpSecurity )

Applies to: Rebex FTP/SSL

1 Answer

0 votes
by (147k points)
selected by
 
Best answer

UPDATE:
We have added support for certificates with private keys stored in CNG Key Storage Providers into Rebex components version 2016 R2.2.


This error occurred during an attempt to perform client certificate authentication, which failed because the specified client certificate's private key could not be accessed. The error was reported by Windows CryptoAPI's CryptAcquireCertificatePrivateKey function and the error code means that an invalid provider type was specified.

We can't tell for sure what caused this without further investigation, but a common cause is a certificate associated with a CNG key stored by a key storage provider (KSP) instead of CryptoAPI CSP provider. See this blog post at MSDN if you are interested in details.

Please download this hotfix build and let us know whether it solves the issue. Thanks for bringing this to our attention.

by (160 points)
Thank you for getting back to me.  I downloaded the hotfix build but unfortunately I can't simply use the new .dll files with the RebEx-provided sample GUI FTP client that I was using yesterday.  Instead I have recompiled our product against the new libraries and will need to test them in our live environment, which will happen later today.  I will update with the results then.
by (160 points)
Unfortunately my tests were unsuccessful, or at least inconclusive.  The first time I attempted to run our process using the hotfix dll's you provided I was instructed that I needed a trial key.  I followed the link provided and was able to specify the trial key in my code and recompile.  My next attempt resulted in a new error message that I am hopeful that you can help diagnose:

Unable to create MD5SHA1 hash.
   at Rebex.Net.Ftp.EA(String W, Int32 L, TlsParameters J, SslMode R, FtpSecureUpgradeType D)
   at Rebex.Net.Ftp.AB(String W, Int32 L, TlsParameters J, SslMode R, FtpSecureUpgradeType D)
   at Rebex.Net.Ftp.Connect(String serverName, Int32 serverPort, SslMode security)
   at REDACTED.Utilities.FTPClient.Connect()
   at REDACTED.Utilities.FTPClient.Login()
   at REDACTED

Unable to create MD5SHA1 hash.
   at Rebex.Net.MPG.YX()
   at Rebex.Net.MPG.UX()
   at Rebex.Net.TlsSocket.Negotiate()
   at Rebex.Net.VYG.KW(TlsParameters W)
   at Rebex.Net.Ftp.MB(TlsParameters W, FtpSecureUpgradeType L)
   at Rebex.Net.Ftp.EA(String W, Int32 L, TlsParameters J, SslMode R, FtpSecureUpgradeType D)

Unable to create MD5SHA1 hash.
   at Rebex.Security.Certificates.Certificate.TF(Byte[] W, SignatureHashAlgorithm L, Boolean J, Boolean R)
   at Rebex.Security.Certificates.Certificate.SignHash(Byte[] hash, SignatureHashAlgorithm alg, Boolean silent)
   at Rebex.Net.BPG.LG(Byte[] W, Int32 L, Int32 J, XPG R)
   at Rebex.Net.BPG.FL(Byte[] W, Int32 L, Int32 J)
   at Rebex.Net.MPG.WX(Byte[] W, Int32 L, Int32 J)
   at Rebex.Net.MPG.YX()

If it helps clarify our situation at all, the new certificate we are attempting to use uses SHA256 whereas our old certificate used SHA1.  Additionally, the server we are attempting to connect to at our counterparty supports TLS1.0 and nothing later.  I don't know if this could be related to our issues or if it is just a red herring - but as I mentioned, we are able to connect and upload files to that same TLS1.0 server using the SHA256 certificate using WS_FTP.

I appreciate your continued help.
by (147k points)
Thanks a lot! We now have a reasonably clear picture of what is going on. The new certificate was indeed installed into a CNG KSP instead of (still much more common) CSP key storage, and the hotfix actually made that key accessible to Rebex Certificate class.

However, in TLS 1.0, a combination of MD5 and SHA1 hashes is used in RSA signatures and this seems to be no longer supported when using CNG KSP keys - this is why the current error occurs.

Nowadays, this is usually not an issue because the MD5/SHA1 combo was removed in TLS 1.2, but this is not the case in your scenario.

But why does WS_FTP work? I can think of several possibilities:
a) There might be some way to convince CryptoAPI or CNG to do what we need.
b) You are supplying the client certificate (and the associated private key) to WS_FTP differently.
c) WS_FTP might be working around a similar error by exporting the key from CNG KSP to temporary CSP key storage or to a custom RSA implementation.

While (a) is possible, we have not been able to find any way to to this so far.
Can you let us know whether (b) migh be a possibility?
And if you would like to give (c) a try, please get the new hotfix build:
http://www.rebex.net/getfile/c29c7ff2ea24469f93e7bca4d4d49429/RebexFileTransferPack-HotfixBuild6059-Trial-Binaries.zip

(The trial key will still work with this one.)
by (160 points)
Thank you for your update.  Our head of IT was able to use OpenSSL to repackage the new SHA256 key that was failing as CSP instead of CNGKSP.  Once that was done we were able to use the project built around RebEx 2012 R3 as it was to transmit files to our counterparty’s TLS1.0 server without any additional steps being taken on their side or ours.  This is sufficient for our needs and we consider the matter closed at this time.
by (147k points)
Simple solutions are often the best. Anyway, thanks for bringing this issue to our attention - you helped us make Rebex FTP/SSL better.
by (58.9k points)
edited by
The above hotfixes have been released in version 2016 R2.2: http://www.rebex.net/total-pack/history.aspx#2016R2.2
...