Windows TLS and Schannel · 3 of 3
Certificates the Windows Way: Stores, Private Keys and Who May Use Them
Why a certificate can be installed yet unusable: where Windows keeps certificates and private keys, how the stores relate, and which identity may use them.
Few support conversations are as frustrating as this one: the certificate is installed, anyone can see it in the console, it has not expired, and yet the service that is supposed to use it refuses to start or fails every secure connection. The cause is almost never the cryptography. It is nearly always about where on the Windows machine the certificate was put, whether its private key came with it, and whether the account the service runs under is allowed to use that key. This guide explains how Windows organises certificates into stores, how the machine's stores and each user's stores relate, where trust in the top-level certificate authorities comes from and how it is kept up to date, why a certificate and its private key are two separate objects with separate permissions, how different programs on the same computer read trust differently, and what all of it means for AI agents that run as services under their own identities.
A filing cabinet with labelled drawers
Start with what a certificate is, in one sentence: it is a digital identity card, signed by an organisation others trust, that ties a name such as a website address to a public key, the half of a key pair that can safely be shared. Programs use certificates in Transport Layer Security (TLS), the protection behind HTTPS, to prove who they are and to decide whom to believe. How those checks work is a story of its own; this guide is about where the cards are kept.
Windows keeps certificates in certificate stores, and they are easiest to imagine as a filing cabinet with labelled drawers. Each drawer has a job. The Personal drawer holds certificates that belong to this computer or this user, usually together with their private keys, the never-shared part that proves ownership. The Trusted Root Certification Authorities drawer holds the top-level issuers the machine believes without further proof. The Intermediate Certification Authorities drawer holds the in-between issuers that link a website's certificate back to a root. There is an Enterprise Trust drawer, a Trusted People drawer and, importantly, an Untrusted Certificates drawer, often called Disallowed, for certificates that must be refused even if everything else about them looks fine.
The names change depending on where you look, which confuses many newcomers. The management consoles show friendly names such as Personal and Trusted Root Certification Authorities. Microsoft's programming documentation uses short system names: MY for Personal, Root for trusted roots, CA for intermediates and Trust for enterprise trust. PowerShell, the Windows command shell, exposes the same drawers as folders on a special Cert: drive, using the short names again, so the Personal drawer of the computer appears as Cert:\LocalMachine\My.
A real machine has far more drawers than these few. On the Windows 11 computer examined for this guide, the machine-wide location contained 30 stores, from the familiar My, Root and CA to specialised ones such as Remote Desktop, TrustedPublisher and several created by installed software. For TLS, though, a small set does nearly all of the work, and knowing those well is enough to diagnose most problems.
| Console name | Short name | What it holds | Typical TLS use |
|---|---|---|---|
| Personal | My | This computer's or user's own certificates, ideally with private keys | The certificate a server presents, or a client certificate |
| Trusted Root Certification Authorities | Root | Top-level issuers believed without further proof | Deciding whether a server's certificate can be trusted |
| Intermediate Certification Authorities | CA | In-between issuers that link certificates to a root | Completing the path from a certificate to a trusted root |
| Untrusted Certificates | Disallowed | Certificates that must be refused | Blocking a known-bad certificate everywhere at once |
Two locations: the machine and each user
The filing cabinet comes in more than one copy. Microsoft's documentation describes two main store locations. The local machine location belongs to the computer itself: it is, in Microsoft's words, local to the computer and global to all users on it, and it lives under the machine-wide part of the Windows registry. The current user location belongs to one user account and lives under that user's part of the registry. Every person who signs in, and every account a service runs as, has its own current user location.
The two are connected by a rule that explains a lot of everyday behaviour. Microsoft states that all current user stores, except the Personal store, inherit the contents of the local machine stores. Add a root certificate to the machine's Trusted Root store, and it appears in every user's Trusted Root store as well. On the Windows 11 computer examined for this guide, the machine's Root store held 75 certificates and the signed-in user's Root store showed 76: the machine's roots, inherited, plus one more held in the user's own location.
The exception matters just as much as the rule. Personal is not inherited in either direction. A certificate imported into one person's Personal store is visible only to programs running as that person. A Windows service, which runs under its own account rather than as the person who installed it, never sees that person's Personal store. This is the root of one of the most common mistakes: double-clicking a certificate file while signed in as yourself puts it in your own Personal store, where the service you meant it for cannot find it.
Windows gives each location its own console. The Local Machine certificates console, certlm.msc, shows the computer's stores; the Current User console, certmgr.msc, shows the signed-in person's. There are further locations for special cases, including one per service and stores pushed down from Group Policy, the Windows system for sending the same settings to many computers, which Microsoft says are downloaded at startup or sign-in. For TLS, the first question in any investigation is simply: which location, and whose?
Where trust at the top comes from
The Trusted Root store deserves a closer look, because everything a Schannel program decides about whom to believe ends there. If a server's certificate leads back to a root in this store, the connection can be trusted; if not, it fails. So who decides what is in it?
On a connected Windows machine, the answer is mostly Microsoft's Root Certificate Program, which collects the top-level authorities that meet its requirements and distributes them through lists called Certificate Trust Lists (CTLs). Microsoft's documentation explains that computers able to reach Windows Update can receive updated trust lists daily, and that organisations without internet access can redirect computers to a file or web server inside their own network that hosts the same lists. The same mechanism carries a list of certificates to distrust, so a certificate known to be compromised can be refused on every connected machine without anyone touching it by hand.
The practical consequence surprises many people: the Root store on a connected computer is not a fixed list frozen at installation. The trust lists are refreshed in the background, so what the store holds can change without anyone touching it. Counting the certificates in the store therefore gives a snapshot, not a specification, and two machines on the same Windows release should not be expected to show identical counts.
The distrust side is easy to overlook and worth a look on any machine you are responsible for. The Untrusted Certificates store, Disallowed in PowerShell, holds certificates that Windows will refuse even when they chain to a trusted root, and it is fed by the same update mechanism. Listing it with Get-ChildItem on the Cert: drive changes nothing and shows whether the machine has been receiving those updates. An empty or very old distrust store on a server that is meant to be connected is a quiet sign that its trust lists are not being refreshed at all.
Organisations add their own trust on top. A company that runs its own certificate authority, so that internal servers can have certificates without buying them, needs every machine to trust that authority's root. The supported route is to distribute the root through Group Policy into the machine's stores, from where every user location inherits it. Microsoft also describes an enterprise store that is synchronised from the directory every eight hours. The same caution applies to every route: anything added to the machine's Trusted Root store is believed by every Schannel program on the computer, which is exactly why additions deserve care and a record.
The certificate and its key are two different things
Here is the idea that unlocks most certificate problems on Windows: a certificate and its private key are two separate objects, stored in different places, with different permissions.
The certificate itself is public by design. It contains the name, the public key, the issuer's signature and the validity dates, and anyone may read it; sending it to strangers is exactly what a server does at the start of every connection. The private key is the opposite: whoever holds it can act as the certificate's owner. Windows therefore keeps it apart. Microsoft's documentation for Cryptography Next Generation (CNG), the Windows layer that provides cryptographic building blocks, describes how private keys are stored in their own key files, in per-user folders for user keys and in machine folders for computer keys, and how long-lived keys are used inside the protected Local Security Authority (LSA) process rather than in the program that asked.
A useful picture is a hotel key card and the hotel's register. The card itself is a plastic rectangle anyone can look at. What makes it open a door is the matching entry in the hotel's system, and the hotel decides who may use it. A certificate sitting in a store is the card. Whether it opens anything depends on whether its private key is present, and on whether the account trying to use it is on the list.
Because the key lives in its own file, in its own folder, under its own permissions, it does not travel with the certificate by accident. Copying a certificate from one machine's console to another copies the public part only. The supported way to move a certificate together with its key is to export both into a single password-protected file, commonly with the .pfx extension, and to import that file on the destination machine, into the right store, and only if the key was marked as exportable when it was created. Keys that were deliberately created as non-exportable cannot be moved at all, which is a feature, not a fault.
This explains two ways a certificate can look installed and still be useless. The first is a certificate imported without its private key, which happens when someone imports only the public certificate file instead of the bundle that includes the key; the console shows the certificate, but there is nothing behind it. The second is a key that exists but is not readable by the account that needs it. PowerShell can reveal the first case without changing anything, because every certificate on the Cert: drive carries a property called HasPrivateKey; the second needs a look at the key's permissions, which the Local Machine console shows under Manage Private Keys.
# Certificates in the computer's Personal store, with key and expiry information
Get-ChildItem Cert:\LocalMachine\My |
Select-Object Subject, Thumbprint, HasPrivateKey, NotAfter
# How many trusted roots the machine and the current user can see
(Get-ChildItem Cert:\LocalMachine\Root).Count
(Get-ChildItem Cert:\CurrentUser\Root).CountWhy a service cannot use a certificate that is plainly installed
Put the pieces together and the classic failure becomes predictable. A service needs a certificate for TLS. Someone installs it. The service still fails. There are three questions to ask, in order, and between them they explain the great majority of cases.
First, is the certificate in the store the service actually reads? Server software on Windows normally looks in the computer's Personal store, the local machine location. Microsoft's instructions for the Remote Desktop listener, for example, say the certificate must be imported into the Personal store of the computer account and is then referenced by its thumbprint, a short fingerprint that identifies one certificate exactly. A certificate imported into a person's own Personal store is in the wrong cabinet entirely.
Second, does the certificate have its private key? If HasPrivateKey reports false, the server has nothing to prove its identity with, and no setting will fix that short of importing the certificate again from a file that includes the key.
Third, may the service's account use that key? Every Windows service runs in the security context of an account, and Windows compares that account against the permissions on whatever the service tries to open. Microsoft's guidance for encrypting connections to SQL Server spells out the consequence: the SQL Server service account must have read permission on the certificate's private key, and if it runs as a non-privileged account, that permission has to be added, or the service can fail to restart. The same reasoning applies to any service. A key that the administrator who imported it can use is not automatically usable by a service running as a different account.
A typical case shows how quickly the checks pay off. An administrator receives a certificate file for an internal web service, double-clicks it while signed in, and follows the import wizard. The certificate now appears in the console, so the job looks done, but the service still fails. The first check finds the certificate in the administrator's own Personal store rather than the computer's. Imported again into the computer's store from the bundle that includes the key, it passes the second check. The service still fails until the third check reveals that its account has no permission on the key; one permission later, it starts.
Only after all three answers are yes is it worth looking at anything more subtle. The order matters because each question is cheap to check without changing anything, and each rules out a whole family of causes.
Not every program reads the same trust
Trust is also where the difference between programs on one computer shows up most clearly. Programs that use Schannel, the TLS component built into Windows, decide whom to believe using the Windows stores described above. Programs that bring their own TLS library may read those stores, part of them, or none of them.
Python is a good example of a mixture. Its ssl module performs the connection with the OpenSSL library rather than Schannel, but the documentation for its default certificate loading states that on Windows it loads certification authority certificates from the CA and ROOT system stores. So a Python program using the standard defaults borrows Windows' list of trusted roots while doing the actual TLS work with a different library. Many Python programs, however, use helper libraries that can be set up to carry their own list of trusted roots instead, so the answer for a specific program depends on how it was built.
Google Chrome takes a different approach. The Chrome Root Program's own documentation explains that on Windows, in a change rolled out from Chrome 105 and switched on by default from Chrome 108, Chrome uses its own Chrome Root Store and its own certificate verifier, and that it does not rely on the default trust store shipped with the operating system. It does, however, automatically pick up certificates that an administrator or user has added to the Windows Trusted Root and Trusted People stores, including those pushed by Group Policy, and it honours the Untrusted Certificates stores as a list to refuse.
The consequence for anyone managing a Windows machine is subtle but important. A root that Microsoft's program distributes is trusted by Schannel programs and by Python's defaults, but not necessarily by Chrome, which applies its own selection. A root that your organisation adds deliberately is trusted by all three. And Microsoft's .NET guidance points out the flip side: adding a certificate to the machine's stores affects every application on the system, which is why it also offers a way to give a single program its own private list of trusted roots instead.
When the program must prove who it is
So far the certificate has belonged to a server. Sometimes the client has to show one too. In mutual TLS, both sides present certificates: the server proves it is the real server, and the client proves it is an allowed caller. It is common between services inside an organisation, and between programs and sensitive tools, because it replaces a shared password with something much harder to steal and replay.
Everything in this guide applies to client certificates in exactly the same way. The client certificate lives in a Personal store, together with its private key. If the client is a person using a browser, that is usually the person's own Personal store. If the client is a service, the certificate must be in a store that the service's account can see, normally the computer's Personal store, and the service's account must be allowed to use the private key. Microsoft's guidance for .NET states the same requirement from the programmer's side: when a program authenticates as a client in mutual TLS, the certificate it supplies must contain the private key.
Servers built on Schannel can go one step further and link a client certificate to a Windows user account, so that presenting the certificate is the same as signing in as that user; Microsoft's documentation describes one-to-one and many-to-one mappings for this. That is a powerful feature and a reason to treat client certificates with the same care as passwords.
Client certificates also expire, just like server certificates, and when they do the failure appears on the client side as a refused connection that worked yesterday. Every certificate on the Cert: drive carries a NotAfter property holding its expiry date, so a read-only listing of the Personal store, sorted by that date, is one of the simplest health checks a team can schedule for any service that authenticates with a certificate.
The lesson for a beginner is that mutual TLS adds no new kind of storage. It adds a second place where the same three questions apply: right store, key present, account allowed. Most failures in mutual TLS that look mysterious turn out to be one of those three on the client side, rather than anything wrong with the server.
AI agents run as services, so check as the service
An artificial intelligence (AI) agent is software in which a large language model (LLM) works out the next step, after which network calls to models, tools and data sources perform it. In production, agents rarely run as the developer who wrote them. They run as services, scheduled tasks or web applications, each under its own identity: a virtual account named after the service, such as NT SERVICE followed by the service name, a group managed service account shared across a set of servers, or the identity of a web application pool. Those identities are exactly the accounts this guide has been talking about.
That is why certificate problems with agents almost never look like cryptography problems. An agent that worked perfectly on a developer's laptop, where the developer's own Personal store held the client certificate for a tool server, fails in production because its service account cannot see that store. An agent that serves its own tool endpoint over HTTPS fails to start because its identity was never given read permission on the private key. An agent that calls an internal service fails trust checks on one server and not another, because only one of them received the organisation's root through Group Policy, or because the agent's runtime carries its own list of trusted roots.
The gap between a developer's machine and production is where most of these surprises live. On a laptop, the developer is both the person who imports certificates and the account the agent runs as, so every store and every key is automatically within reach. In production those two roles split apart, and every assumption made silently on the laptop becomes a question with a separate answer. Testing an agent under its real service identity before release, even on a test machine, removes most of that gap at once.
The fixes are rarely complicated once the right question is asked. The key is to treat the agent's identity as the subject of every certificate check, not the person deploying it, and to know which trust store the agent's runtime actually reads.
For teams that run agents, a short checklist built from read-only checks catches most of these before they reach production, and lets a leader say with evidence whether an agent's certificates are actively managed or merely present.
- Name the account each agent runs as, and check certificates from that account's point of view, not the deployer's.
- Keep agent server and client certificates in the computer's Personal store, and confirm HasPrivateKey is true.
- Grant the agent's account read access to its private keys only, and record where that permission was granted.
- Know whether the agent's runtime reads the Windows trust stores or carries its own roots, and test trust from the agent itself.
- Prefer a per-application list of trusted roots over adding roots to the whole machine when only one agent needs them.
Key takeaways
- Windows keeps certificates in stores with distinct jobs: Personal for a computer's or user's own certificates, Trusted Root and Intermediate for trust, Disallowed for refusals.
- There are machine stores and per-user stores; user stores inherit the machine's stores except Personal, so services never see a person's Personal certificates.
- On connected machines the Trusted Root store is refreshed through Microsoft's Root Certificate Program, and organisations add their own roots through Group Policy.
- A certificate and its private key are separate objects; a service can use a certificate only if it is in the right store, has its key, and the service's account may read that key.
- Programs read trust differently: Schannel programs use the Windows stores, Python's defaults borrow them, and Chrome uses its own root store plus roots added locally.
- AI agents run under their own identities, so check every certificate question from the agent's account and runtime, not the deployer's.
Glossary
- Certificate
- A signed digital identity card that ties a name, such as a website address, to a public key.
- Private key
- The never-shared member of a key pair, which proves ownership of a certificate; Windows stores and permissions it separately from the certificate.
- Certificate store
- A named collection of certificates on Windows, such as Personal, Trusted Root or Disallowed.
- Local machine store
- The computer-wide certificate location shared by all users and services on that computer.
- Current user store
- One account's own certificate location; it inherits the machine's stores except Personal.
- Thumbprint
- A short fingerprint that identifies one certificate exactly, often used to tell a service which certificate to use.
- Certificate Trust List (CTL)
- A signed list Microsoft distributes so Windows machines can update which root certificates they trust or refuse.
- Mutual TLS
- A TLS connection in which both the server and the client present certificates to prove who they are.
- Service account
- The identity a Windows service runs as, such as a virtual account or a group managed service account.
Further reading
- Local Machine and Current User Certificate Stores (Microsoft Learn)
- System Store Locations (Microsoft Learn)
- Configure trusted roots and disallowed certificates in Windows (Microsoft Learn)
- Configure SQL Server Database Engine for encrypting connections (Microsoft Learn)
- Chrome Root Program Frequently Asked Questions (Chromium)
- ssl: TLS/SSL wrapper for socket objects (Python documentation)
- about_Certificate_Provider (Microsoft Learn)
Sources
This article is based only on public, authoritative Microsoft documentation.
- Local Machine and Current User Certificate Stores — Microsoft Learn
- System Store Locations — Microsoft Learn
- Configure trusted roots and disallowed certificates in Windows — Microsoft Learn
- about_Certificate_Provider (PowerShell) — Microsoft Learn
- Configure SQL Server Database Engine for encrypting connections — Microsoft Learn
- Chrome Root Program FAQ — Chromium
- ssl — TLS/SSL wrapper for socket objects (Python documentation)