Quick answer: The 0X8009310E error means the Windows CryptoAPI hit an ASN.1 string that's marked as UTF8 but contains bytes that aren't valid UTF8 — usually a corrupt or badly encoded certificate. Re-export the certificate as DER or Base64, re-import it, and the error goes away.
I've seen this pop up on everything from a Windows Server 2019 box doing LDAPS to a developer's Windows 11 machine trying to sign a ClickOnce manifest. The error message is maddeningly vague: "ASN1 bad tag value met" or "Bad Unicode (UTF8)". What's actually happening is the ASN.1 parser inside crypt32.dll expects a UTF8String field, reads the bytes, and finds a sequence that doesn't decode. ASN.1 has several string types — PrintableString, IA5String, BMPString, UTF8String — and if a certificate was generated by a sloppy tool or got mangled in transit, the declared type won't match the payload. CryptoAPI refuses to guess.
Common triggers: a certificate you downloaded from a web portal got saved as HTML instead of binary, an internal CA issued a cert with a non-ASCII character in the Subject Alternative Name that wasn't encoded properly, or a Base64 copy-paste dropped a line break in the wrong spot. I've also seen it when a smart card driver returns a truncated buffer on older middleware.
Step-by-step fix
- Identify the bad certificate. The error usually names the file or the store operation. If it's a file, right-click it, choose Open, and look at the Details tab. If Windows can't even open it, that's your culprit.
- Re-download or re-export the certificate in a clean format. From the machine that issued it, open
certlm.mscorcertmgr.msc, right-click the cert, All Tasks → Export. Choose Base64 encoded X.509 (.CER) if you plan to paste it, or DER encoded binary X.509 (.CER) if you're moving a file. Do not use the .P7B format here — it wraps things in PKCS#7 and can preserve the same bad encoding. - Verify the file is actually binary or Base64, not HTML. Open it in Notepad. A DER file starts with garbled bytes. A Base64 cert starts with
-----BEGIN CERTIFICATE-----. If you see<html>or a login page, that's your problem — the download was intercepted by a captive portal or SSO redirect. - Import with certutil instead of the wizard. The GUI importer is picky about encoding;
certutilis more forgiving and gives you a real error message.
After running it, you should seecertutil -addstore -f "Root" C:\certs\fixed.cer certutil -addstore -f "My" C:\certs\fixed.pfxCertUtil: -addstore command completed successfully.If it fails, the output will tell you which byte offset tripped the ASN.1 parser. - Clear the CryptoAPI cache. Stale cached certs can keep throwing the old error even after you fix the file. Stop the Cryptographic Services and restart it:
Then delete the catroot2 cache — Windows rebuilds it on next boot:net stop cryptsvc && net start cryptsvcnet stop cryptsvc ren %systemroot%\System32\catroot2 catroot2.old net start cryptsvc - Re-test the original operation. Import the cert, run your LDAPS bind, sign your installer, whatever failed before. The error should be gone. If it isn't, move to the alternative fixes below.
Don't skip step 5. I've watched people re-import a perfectly good cert three times and keep hitting 0X8009310E because the old cached copy was still loaded in memory.
If the main fix doesn't work
Check the SAN for bad characters
Open the cert with certutil -dump C:\certs\fixed.cer and read the Subject Alternative Name block. If you see a non-ASCII character (accented letter, emoji, Unicode dash) in a DNS name or email, the issuing CA probably stamped it as a UTF8String but wrote Latin-1 bytes. The fix is to reissue the cert without that character — the CA admin needs to do it, you can't patch the encoding client-side.
Reset the user's crypto profile
For smart card and TPM scenarios on Windows 10 21H2 or later, the user profile's key container can get wedged. Back up first, then:
cd %APPDATA%\Microsoft\Crypto
ren RSA RSA.old
ren DSS DSS.old
Log off and back on. You'll lose any software-based private keys stored in the user profile, so only do this if you've got a hardware-backed cert or a re-issuable one.
Patch the offending tool
If this fires from your own code, you're likely calling CryptQueryObject or CertCreateCertificateContext with a buffer that's been through a text-mode read. Open the file with FILE_FLAG_BINARY or fopen(path, "rb"). A single missing b in a file-open call is the root cause of about a third of these reports I've handled.
Prevention
Always move certs as DER binary or Base64 text, never as whatever the browser hands you when you click a download link. Verify every cert with certutil -dump before it goes near production. And if you run an internal CA, set the Subject Alternative Name policy to reject non-ASCII characters at issuance time — you'll never see 0X8009310E again. Also keep your smart card middleware current; Gemalto and Yubico both shipped fixes for truncated ASN.1 buffers in 2021-era releases.