- 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