Vectors of Trust
A few years ago I was working on a variety of systems in the US federal government space, and I kept running into a fairly pervasive requirement: Levels of Assurance, or LoA. This measure of security was being levied as a requirement for all kinds of systems, often whether it made any sense in context or not. Limitations in LoA have lead to the development of Vectors of Trust, which is now in the process of being published as a standard.
What is a Level of Assurance?
The whole idea behind LoA is fairly simple. When someone is logging in to your system, you want to know who they are. The more sensitive your system, the more you want to know who that person is and the more sure you want to be about that knowledge. The US federal government defined the requirements for LoA in a document known as OMB M-04-04, which was later augmented by NIST Special Publication 800–63. Taken together, these documents provide federal agencies a way to determine the best way to let people log in to their systems.
So let’s say you’ve got a moderately sensitive system. You want to know who’s logging in, but you don’t want to make it overly difficult for them to get accounts or get into the system, since you’ve got a lot of people that need to use it and they need to do so often. Consequently, you decide that you’ll ask people for driver’s licenses (or other state-issued ID cards) when they get an account, and they can log in to that account using a username and password. What you’ve just done is identity proof the person and issue them a credential based on a shared secret, their password. You can even put requirements on how easily guessable their password is.
But then let’s say you’ve got a much more sensitive system, like the big red button that launches missiles. You want to be very, very sure that the people you let push the big shiny button are the people who are supposed to be pushing that button. As a result, instead of just letting someone roll up with a driver’s license to get an account, you have a trained interviewer review lots of documentation, including passports and proof of address, and perhaps even interviews with references. Then when you decide to give them an account, you don’t want something as simple as a password. Passwords can be stolen or guessed, so maybe you want to give them a physical device and a complex secret, or some other stack of hard-to-forge credentials.
When you’ve got a lot of different systems for people to use, it’s helpful to standardize a notion of this measurement so that these systems more or less work like each other and are compatible to some degree. This is exactly the intent of the LoA scale. That way, with these guidelines you can look at a system and say “this requires LoA 2” and someone else can say “this credential meets LoA 2” and everything works like you expect it to, most of the time.
Where Things Start to Go Sideways
The LoA scale ties together identity proofing and the strength of the credential used to log in and presents them as a single value, binding the physical identity of a person to the digital identity understandable by a computer system. This makes a good deal of sense for federal government systems being accessed by federal government employees, which is of course the intended application of the federal 800–63 guidelines. However, people soon realized that the definitions of LoA and the associated requirements for them provided a handy framework for describing authentication needs across a wide variety of systems.
Well, they were almost good enough. As it turned out, people generally needed to tweak the requirements or definitions a bit to fit their use cases. The result of this was that one group’s LoA 2 was quantitatively different from another group’s LoA 2, or the realization that their needs fit in between the federal government’s definitions. This lead to some people clamoring for finer granularity, defining things as “LoA 2.5” to cover these gaps.
But there were even more use cases that didn’t fit the LoA model at all. For example, what if you were an organization dealing with political dissidents? You’d want to avoid connections to a person’s physical identity however possible, which would put things into a lower LoA classification. However, you wouldn’t want important accounts to be easily taken over (say, by the state power that they’re acting against), so that calls for a higher LoA classification. But the LoA is a single scale and we can’t have both simultaneously, and it’s impossible to model this very important use case using that structure.
What do we do when the tools we have no longer suit our purpose? We make new tools — and that’s where Vectors of Trust comes in.
Breaking Up LoA
Back in the fall of 2014 I was invited to an Internet Society meeting in Utrecht, Netherlands. There were a lot of great conversations during that meeting, and it was there that I started to formalize an idea about how to make the LoA work for a wider world. Namely, I felt that we needed to blow it to pieces.
More specifically, I contended that we should break the LoA’s single value into a set of orthogonal components. The LoA calculation in NIST’s 800–63 was already taking into account several aspects of the identity transaction, as we’ve seen, so the problem really only came with the fact that the output of the calculation was a single scalar value. I proposed that instead of this scalar, we represent the calculation as a vector.
Initially I proposed three components to this vector:
- How strongly the person was identity proofed, which ties to their physical identity
- How resistant a given credential is to attacks like impersonation, guessing, and theft
- How strongly a given transaction’s assertion is protected as it’s passed between parties over the network
So far, these measurements aren’t all that different from what goes into the calculation of an LoA, and in fact that’s where these pieces came from. But here’s the real trick: instead of taking them together into a single number, these three components would be expressed in such a way that they would be carried together in a single string but the values of each component would still be available separately. Each of these component categories would be assigned a letter: P for identity proofing, C for the credential strength, and A for the assertion strength. Each of these categories would have defined within it values that correspond to different levels or aspects of the category. Proofing, for example, would have a single-digit number that increases depending on how well we know the person receiving the credentials. Credential strength, on the other hand, would get a single letter representing the underlying technologies in use and the ability to be used more than once.
For a concrete example, our government LoA 3 use case would have its identity proofing, credential, and assertion all at a single level. This could be expressed in a simple VoT as P3.Ce.Ac and passed over the network along with other identity information. But when we look at our use case of a strongly authenticated anonymous dissident, we would want them to be strongly authenticated and asserted but not tied to verified attributes (that is, proofed) at all. Consequently, this could be expressed in a simple VoT as P0.Ce.Ac. Furthermore, each of these values could be mapped into an associated LoA, if needed.
An RP could use this construct to see that an incoming user was logged in to the IdP with very strong credentials, but that any attributes about the user (such as their name or address) haven’t been vetted. If the RP cared only about the strong credentials, that’s all it would check. But if it expected users to have been proofed and vetted by the IdP (such as with a government employee), then it could easily reject users that didn’t fit that criteria. Similarly, an RP could use this same vector construct to request particular behaviors from the IdP. An RP could still decide if it likes the results it got back from an IdP, whether or not the IdP honored that request.
Anchoring the Vector
Along with this vector construct, I proposed that we have a machine-readable description of the server itself, which I called a trustmark, to serve as an anchor for the values in the vector. This anchor was inspired directly by the fine work from the Georgia Institute of Technology on machine-readable trust frameworks. Their work is focused around automated processing of policies across domains, which is a much larger and more complex problem than what we wanted to tackle with VoT. The vector itself should have all of the information an RP needs to process an authentication transaction. But if the vector contains all the information about the transaction that we need, why would we need a separate anchor?
One of the problems that we saw with LoA was that one group’s version of LoA 2 wasn’t quite the same as another group’s LoA 2. From the beginning, I contended that these vectors made sense only in the context of a relationship between the IdP and the RP, since the RP has to decide how much it trusts an IdP to do what it claims to have done within the vector. We could have said that interpreting these vectors was entirely up to the RP — and ultimately it is — but we wanted to be able to give the RP at least a pointer to the context in which it should interpret these things. With that, we decided that all vectors needed to be paired with a URL pointing to a human-readable document that defines how to interpret the components therein.
From the early discussions around the VoT concept, we quickly realized that any concrete definition of vector components or values wasn’t going to be universally applicable. But now that we’re anchoring the vector’s contents to a separate document, we can define new vector components and new values that are more applicable to specific instances, and still use the same basic VoT processing and expression platform. This does mean that my version of P3.Ce.Ac might not be the same as yours, but we can at least tell them apart by their different trustmark URLs. There’s also a good chance that my components are defined similarly (if not identically) to yours.
Flexibility and Structure
There has been a lot of discussion on the VoT mailing list about what the draft document should contain. We quickly saw that people disagreed about what the vector component categories themselves should be, as well as what values should be in each of those categories. We also saw disagreement about any implied or explicit ordering of those values. For instance, one group might consider hardware tokens more secure than It was fairly obvious that we would not be able to invent a single, universal solution to this complex problem space. Our approach with the draft was to skate the line between having enough flexibility to apply to various approaches while still maintaining enough structure to make it meaningful across systems.
The draft VoT document defines a set of categories and values that are meant to be generally applicable to a wide variety of situations. In addition to defining the structure of a vector, the document has a set of defaults for when something more specific isn’t available. This set includes the three components defined above — proofing (P), credential strength (C), and assertion strength (A) — along with a fourth for dealing with credential management lifecycles, marked with M. Many systems, such as those covered by the NIST documents, have fairly strict lifecycle policies, and those systems can leave this component out. However, other systems needed this flexibility, and it was added to the base set.
Some also proposed aspects like the operational management of the IdP, such as how the IdP would handle disaster recovery. These were left out of the draft since, unlike other components, it’s not something that would vary based on the transaction. Instead, these kinds of stable items can be handled with the trustmark construct that fits alongside VoT.
And what if for some use case there is a real need for an operational category? Other documents can define their own categories, reuse categories from VoT with their own value definitions, or pull in externally-defined lists entirely. The trustmark that goes with your vector value defines how to interpret that value in a meaningful way. This flexibility lets the VoT approach work in a much wider range of environments without each environment needing to invent its own system from scratch.
The Future and Legacy of VoT
The initial idea behind VoT was the subject of a side meeting in Utrecht, and in that space a number of very clever and engaged people added their inputs to the concept. The draft of VoT was discussed at length on an IETF-hosted mailing list, and you can see the archives of that discussion online. Unlike most IETF lists, this list was not associated with a formal IETF working group, but the discussion resulted in a draft document that is on its way to publication as an RFC standards document. The meeting in Utrecht and the list discussions added a lot of depth and definition to my initial proposal, but more importantly it got the idea of VoT out into the wild where it could take root.
The most interesting place that VoT has shown up has to be the new version of NIST’s 800–63 digital authentication guidelines. Instead of defining requirements for fulfilling the LoA scale, as previous versions had done, this version defines three orthogonal assurance levels: Identity Assurance Level (IAL), Authenticator Assurance Level (AAL), and Federation Assurance Level (FAL). These deal with identity proofing, credential strength and management, and assertions presented over a federated identity protocol. The guidelines still provide ways to map a combination of IAL, AAL, and FAL into an LoA for government use cases, but the definitions of each category can also be used separately from LoA.
Sound familiar? It’s no surprise: several of the key authors of the new 800–63 guidelines (including myself) were involved in VoT and the discussions around it. We explicitly set out to address the shortcomings in the old 800–63 guidelines in a way that works for a wide variety of people, and a VoT-style approach was a good way to do that.
VoT was not the first or only call for breaking up LoA, but it was one of the first solutions to be codified in a way tried to balance the need for flexibility and the resulting complexity in this way. VoT set out to be more fine-grained and expressive than LoA but much less complex than a bag of attributes with massive amounts of metadata. Skating this middle line is no mean feat, but we think we’ve done a decent job here. The draft is in its final stages of ratification right now, and in the near future, we’ll see an RFC that fully formalizes VoT as a standard. Hopefully, we will also see a set of documents that define their own trustmarks to anchor these vectors to real use cases.