- From: Mitch Zollinger <mzollinger@netflix.com>
- Date: Tue, 12 Jun 2012 19:55:26 -0700
- To: Ryan Sleevi <sleevi@google.com>
- CC: <public-webcrypto@w3.org>
- Message-ID: <4FD8011E.5000202@netflix.com>
On 6/12/2012 3:58 PM, Ryan Sleevi wrote:
>
>
> On Tue, Jun 12, 2012 at 3:30 PM, Mitch Zollinger
> <mzollinger@netflix.com <mailto:mzollinger@netflix.com>> wrote:
>
> On 6/12/2012 2:29 PM, Ryan Sleevi wrote:
>>
>>
>> On Tue, Jun 12, 2012 at 1:31 PM, Mitch Zollinger
>> <mzollinger@netflix.com <mailto:mzollinger@netflix.com>> wrote:
>>
>> On 6/12/2012 12:53 PM, Ryan Sleevi wrote:
>>>
>>>
>>> On Tue, Jun 12, 2012 at 12:38 PM, Mitch Zollinger
>>> <mzollinger@netflix.com <mailto:mzollinger@netflix.com>> wrote:
>>>
>>> On 6/12/2012 1:07 AM, Vijay Bharadwaj wrote:
>>>> <snip>
>>>>
>>>> In all the above cases, once a key is obtained, all the
>>>> actual crypto operations are pretty much the same. So
>>>> is we define all operations in the API which require a
>>>> key such that they take a key object as a parameter,
>>>> then the only difference between the above scenarios
>>>> (from an API perspective) is the operations used to
>>>> instantiate that key object. The above 3 scenarios
>>>> would then correspond to 3 different instantiation
>>>> methods for key objects:
>>>>
>>>> 1.GenerateKey – create a new key for use with a
>>>> specific algorithm. Choice of crypto provider left up
>>>> to the platform.
>>>>
>>>> 2.ImportKey – take a key blob obtained from key
>>>> agreement and create a key object from it. Choice of
>>>> crypto provider left up to the platform.
>>>>
>>>> 3.OpenKey – Locate a key on the host system that
>>>> matches a set of criteria. Choice of crypto provider to
>>>> be made by platform depending on the location of the key.
>>>>
>>>> There is also a fourth primitive which is often used
>>>> with scenario 3 – credential enrollment. This would be
>>>> the operation where the user employs the trusted key to
>>>> obtain a credential (e.g. enrolling for a smart card
>>>> certificate by signing a request using one’s existing
>>>> smart card key).
>>>>
>>>> Does that seem reasonable? Any other families of use
>>>> cases that I’m overlooking?
>>>>
>>>
>>> Good write up.
>>>
>>> I would like to better understand what you (and the
>>> group) think about "crypto providers". When I think
>>> about crypto providers, I think of the JCE (Java
>>> Cryptography Extensions) Crypto Providers & OpenSSL
>>> "engines". In that context, it would seem to me that the
>>> app has varying behavior with regard to crypto provider
>>> selection that may be orthogonal to the type of the key.
>>> One example:
>>>
>>> * If my app detects that a smart card is plugged in & I
>>> can use keys on the smart card for service
>>> authentication, I will not ask the user a security
>>> question when they connect to my webapp. However, if I'm
>>> using another crypto provider (likely the default
>>> provided by the browser) -- with the same keys that
>>> would have been stored in the smart card if the user had
>>> it plugged in -- then I will ask my security question.
>>>
>>> Mitch
>>>
>>>
>>> I think that any app that would do what you propose, without
>>> any other additional proof, would be making
>>> a naive assumption that doesn't really improve the security.
>>> I certainly do not want to expose any such concept to the
>>> web API for exactly that reason.
>>>
>>> In your example, you're relying on the user agent to
>>> honestly answer "smart card" or "not smart card" for where
>>> the key is stored, and then making a server side security
>>> decision based on that.
>>
>> I should have been more explicit. I'll echo much of what you
>> say below (I agree with you):
>>
>> When I say "same key" I'm referring to a key with the same
>> *key name* in both contexts, not actually the same keying
>> material or same UUID (I'm taking the liberty of assuming the
>> UUID exists for now.)
>>
>> The point is that the running web app / web service is making
>> a decision on further authentication steps based on the
>> provenance of the key: was it distributed out-of-bound and
>> considered pre-shared or was it something I made up at webapp
>> runtime?
>>
>>
>>> Such a decision seems a lot like sticking form validation
>>> code in the client to prevent against SQL injection.
>>> Browsers can be mislead or manipulated, so I don't think it
>>> can be reasonably assumed to give an answer that is reliably
>>> accurate.
>>
>> No reliance on trustworthiness of client side JS code assumed
>> here.
>>
>>
>>>
>>> Using Vijay's ontology, if you want to make the distinction
>>> between secure element or not, you, as a service provider,
>>> would do so based upon whether or not you (as a service
>>> provider) were responsible for the provisioning ceremony of
>>> those keys. If you controlled the ceremony, you know the
>>> provenance of those keys, and you know how and where they're
>>> stored.
>>
>> Absolutely agree.
>>
>>
>>>
>>> Whether this means mailing out a smart card, using some
>>> other application/protocol/platform. Examples might be
>>> GlobalPlatform, with it's proof of possessions, some work
>>> product of the IETF's KeyProv WG, something like Anders
>>> Rundgren's Keygen2, etc. However, the size and scope of
>>> work, and the many competing interests involved, seem very
>>> much out of scope for this WG (although admittedly very
>>> interesting and perhaps parallel work to solve)
>>>
>>> To modify your scenario into something that I think would
>>> provide some reasonable assurances:
>>> * If your app detects that the user has a (pre-provisioned
>>> Key ID X), then you can allow that user to authenticate
>>> using Key X.
>>> * If your app does not detect Key X, but detects a
>>> (previously generated via <keygen> or the ephemeral API
>>> Vijay proposed), then it uses Key Y, plus some form of
>>> challenge/security question.
>>> * If your app detects neither Key X nor Key Y, it offers the
>>> user the chance to (online enroll a Key Y, contact you to
>>> obtain a smart card with Key X)
>>
>> Yep. No disagreement from me with this approach. I would
>> rewrite this as:
>> * My app wants to use "AuthKey" to authenticate the client,
>> wherever "AuthKey" may be.
>> * The app attempts to use "HSMProvider" as the crypto
>> provider; if that provider does not work or is not available,
>> it falls back to "DefaultProvider". (For the moment, I'm
>> ignoring the bootstrap of "AuthKey" into each of these
>> providers.)
>> * The app authenticates using "AuthKey", which has an
>> associated UUID which allows me to map the key to one of (a)
>> a key that I provisioned into an HSM (and accessible via
>> "HSMProvider") or (b) a key entrusted to the "Default" provider.
>> * The server side decides, based on Provider/UUID whether to
>> initiate further authentication steps.
>>
>> Mitch
>>
>>
>> I'm not sure the providers are necessary here, which is part of
>> why I'm somewhat opposed to them.
>>
>> Using the KeyQueryList sort of example from the other thread, I
>> would think you'd simply set a KQL for "some criteria"
>> (admittedly, hand-wavey), and you would get back (assuming the
>> user approved/pre-approved) two keys.
>>
>> At that point, you have two keys you're interested in. The
>> question is which (or perhaps both) you want to use for the
>> signing operation. Your web app may make a query to the server
>> and say "I have these two keys, which would you like to use" - at
>> which point, the server might say "Use this one, I know because I
>> presided over the ceremony".
>>
>> Your web app may have already sent that list to the client, and
>> the client JS then knows that key X is preferable over key Y, and
>> upon seeing that it has both Key X and Key Y, attempts the
>> authentication protocol first with Key X.
>>
>> You may even show a UI (using your web apps branding) to allow
>> the user to select which key they wish to use, similar to sites
>> that offer multi-login or oauth/saml style workflows.
>>
>> At no point does the application need to be exposed to the crypto
>> provider or how the key is backed - it's simply a key handle that
>> it can use.
>>
>> My guess (perhaps completely unfounded, based on our current
>> participants) is that most applications using this API will not
>> care about "DefaultProvider" or "HSMProvider", and certainly, I
>> think it introduces a whole host of new, cross-browser
>> standardization issues. For example, consider if we have two
>> implementations, one based on PKCS#11 (eg: Mozilla Firefox,
>> Chrome for Linux) and one based on CryptoAPI/CNG (eg: Internet
>> Exporer, Chrome for Windows, Safari for Windows). Both OS-level
>> APIs may be talking to the same logical smart card/key
>> store/secure element, but because of the very different nature of
>> the APIs, have very different naming schemes to identify them.
>>
>> Using the above example, is there a scenario/workflow where "Try
>> to find Key X, then try to find Key Y", in application logic, is
>> more desirable than "Query for Key X or Key Y", and then in
>> application logic making a decision based upon the response you got?
>
> We can work with either mechanism. What I've described (the two
> keys have the same "name" and the provenance is implied by the
> UUID) fits better conceptually with what we're doing today, but I
> could just as easily query for the two keys and use whatever one I
> got back without worrying explicitly about provenance.
>
> I guess I'm not seeing how KeyQueryList would be used. Given that
> you and Wan-Teh are advocating for something along these lines,
> it's clear I'm missing something. (I know very little about smart
> card usage, so this is not surprising.) Could you give an example?
> In other words, could you fill in the [Some, Criteria, Here]
> portion of your pseudo code example?
>
>> var kql = window.crypto.queryKey([Some, Criteria, Here]);
>
> Mitch
>
>
> Wan-Teh hasn't quite chimed in here on KQL, so I don't presume to
> speak for him :-)
>
> The [Some, Criteria, Here] is, in part, dependent upon the ontology of
> key types we're talking about. Whether Vijay's notation or my original
> suggestion of "ephemeral, persistent, and high-value", it does seem
> like we agree on some distinction between "shared" (between origins /
> between other services) and "origin bound" (as the charter and
> original discussions focused on). The parameters to queryKey are going
> to necessary reflect whatever dimensions we determine are both
> relevant for key management and within the scope of the charter.
>
> There needs to be symmetry between the create/derive functions and the
> query functions, although understandably there will be some slight
> differences since you can't create pre-provisioned keys :)
>
> // Find all RSA keys that are usable for OAEP. Additionally, the
> keying material must be available for
> // the script to use (perhaps it implements some custom scheme that
> builds atop OAEP) and it must not
> // be a key that is cleared when the user clears their browsing data
> (eg: it must be 'long-lived/persistent',
> // which is conceptually similar but slightly different than Vijay's
> 'pre-provisioned' category)
> var kql = window.crypto.queryKey(
> {
> 'algorithm': 'RSA',
> 'mode': 'OAEP',
> 'extractable': true,
> 'temporary': false,
> });
>
> // Retrieve all AES keys available for use with CBC mode. They may be
> temporary keys or
> // persistent keys, it may be keys that were randomly generated and it
> may include keys that
> // were derived from some other algorithm (eg: an ECDHE exchange). No
> particular expression
> // about how it is stored is made.
> var kql = window.crypto.queryKey(
> {
> 'algorithm': 'AES',
> 'mode': 'CBC',
> });
>
> // Retrieve all keys (See [1]) that are backed by a certificate, whose
> issuer is one of IssuerName 1 or
> // IssuerName 2. This may return both RSA and ECC keys, since no
> 'algorithm' has been specified. The
> // key must be usable for signing (which may be ascertained as part of
> the key store or may need to
> // be inferred from the KU/EKU of the associated certificate(s))
> var kql = window.crypto.queryKey(
> {
> 'operation': 'sign',
> 'certificate': {
> 'issuer': [
> [ ArrayBuffer of DER IssuerName 1],
> [ ArrayBuffer of DER IssuerName 2],
> ],
> },
> });
>
> [1] This opens the general API discussion about whether or
> not asymmetric algorithms return one key handle (for a public/private
> key /pair/) or two key handles (one for public, one for private). For
> example, by constraining the operation to 'sign', we imply a private
> key (since 'verify' would be public key), 'encrypt' implies public and
> 'decrypt' implies private. However, it may be better to explicitly
> specify rather than implicitly specify.
>
>
> If we adopt some form of UUID notation (which I still need to mull
> over the privacy risks), one might further expand to
>
> var kql = window.crypto.queryKey(
> {
> 'id': [ 'UUID_1', 'UUID_2' ],
> })
>
> or with an origin-specified naming scheme:
>
> var kql = window.crypto.queryKey(
> {
> 'name': 'NetFlixAuthenticationKey',
> });
>
Thanks for the examples. This makes sense to me now. It is a much more
comprehensive querying mechanism relative to the simple "named"
credentials approach. Either approach will work for us.
Mitch
Received on Wednesday, 13 June 2012 02:55:57 UTC