Comments on WebCryptoAPI

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Hello all,

Below are my comments after reading the current draft of WebCryptoAPI.
 I apologize if I've repeated anything stated before; I've not really
followed the discussion leading up to this document's current state.



Potential Defects:
==============================================

The definition for "PBKDF2" includes an editor note that does not
appear to be relevant.  It discusses a "password" field that is not
present in any of the immediately surrounding content.


Comments:
==============================================

Key Storage/Retrieval
- ----------------------------------------------

The draft discusses "retrieving keys" -- distinct from import/unwrap
- -- but does not in any other way indicate how this is dealt with.  It
would help to explicitly mention that key storage/retrieval can be
done with mechanisms that support structured cloning, such as IndexedDB.


KeyPairs and Extractability
- ----------------------------------------------

Assuming that when generateKey returns a KeyPair that the public key
is always extractable, this should be explicitly stated somewhere
separate from the individually registered algorithms.  At a minimum,
this ought to be stated in § 18.3. "Defining an Algorithm", but it
could also be helpful for have it stated at or around § 14.3.6. "The
generateKey method" from the perspective of an API user.


"Defining an algorithm" Guidelines
- ----------------------------------------------

If the to-be-defined algorithm supports the "importKey" operation, the
definition ought to clearly specify how [extractable] applies.

Examples
- ----------------------------------------------

It would be nice to a somewhat non-trivial deriveKey example.  For my
own edification, I put together a mythical example (included below) to
see if I'm understanding the API interactions correctly.  And, please,
correct my misconceptions of how the API works if my example has
egregious  errors.

Key Lifetimes
- ----------------------------------------------

I suspect this is controversial.  It would be nice if a generated Key
could have some sort of lifetime that the user agent enforces.  At a
minimum, I would highly desire the ability to specify that a Key
should not be used for more than a browser session (similar to
sessionStorage), but would value having a fixed expiration date/time
or a certain amount of time after generateKey's promise is fulfilled.

I realize that this can complicate things (e.g., how does this
interact with importKey?), and can live with some restrictions (e.g.,
limited-life Keys are never extractable).  I think it's also
acceptable for the lifetime to be tied to just the private Key of a
KeyPair, if it helps simplify things at all.


Thank you,

- - m&m

Matt Miller < mamille2@cisco.com >
Cisco Systems, Inc.

- -----BEGIN EXAMPLE-----

// Agree to a session key with another user
var promise,
    us = {},
    them = {},
    sessionKey = null;

// helper for prefixing data with a length encoding
function __UINT32(value) {
    var output = new Uint8Array([
        (value >>> 24) & 0xff,
        (value >>> 16) & 0xff,
        (value >>> 8) & 0xff,
        value & 0xff
    ]);
}

// Generate an EC Key for ECDH
var params = {
    name: "ECDH",
    namedCurve: "P-256"
};
promise = window.crypto.subtle.generateKey(params,
                                           false,
                                           [ "deriveKey" ]);
promise = promise.then(function (keypair) {
    // remember the generated key for right now
    us.pivateKey = keypair.privateKey;
    us.publicKey = keypair.publicKey;

    // set our identifier
    var ident = new TextEncoding("utf-8").encode("me@example.com");
    us.info = new Uint8Array(4 + ident.byteLength);
    us.info.set(__UINT32(ident.byteLength));
    us.info.set(ident, 4);

    // export public key as JWK
    return window.crypto.subtle.exportKey("jwk", us.publicKey);
});

promise = promise.then(function(jwk) {
    // exchange public keys with 'them';
    // returns a promise with the other user's public key,
    // it could use XMLHttpRequest or WebSocket for the actual exchnage
    return exchangePeerInfo({
        publicKey: jwk,
        info: us.info
    });
});

promise = promise.then(function (other) {
    them = other;

    // import the key
    return window.crypto.subtle.importKey("jwk",
                                          them.key,
                                          { name: "ECDH" },
                                          true,
                                          [ "deriveBits" ]);
});

promise = promise.then(function (theirKey) {
    // remember their Key object
    them.publicKey = theirKey;

    // generate the shared secret "Key"
    var params = {
        name: "ECDH",
        public: their.publicKey
    };

    return window.crypto.subtle.deriveKey(params,
                                          us.privateKey,
                                          { name: "CONCAT" },
                                          false,
                                          [ "deriveKey" ]);
});

promise = promise.then(function (secret) {
    // construct the algorithmId UINT32(algorithm.length) || algorithm
    var algName = new TextEncoder("utf-8").encode("A128GCM");
    var algId = new Uint8Array(4 + algName.byteLength);
    algId.set(__UINT32(algName.byteLength));
    algId.set(algName, 4);

    var params = {
        name: "CONCAT",
        hash: "SHA-256",
        algorithmsId: algId,
        partyUInfo: us.info,
        partyVInfo: them.info
    };

    var derived = {
        name: "AES-GCM",
        length: 128
    };
    return window.crypto.subtle.deriveKey(params,
                                          secret,
                                          derived,
                                          false,
                                          [ "encrypt", "decrypt" ]);
});

promise.then(console.log.bind(console, "the session key is: "),
             console.error.bind(console, "generating session key failed");

- -----END EXAMPLE-----
-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.22 (Darwin)
Comment: GPGTools - https://gpgtools.org
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQEcBAEBCgAGBQJTWXY9AAoJEDWi+S0W7cO1RDAH/1kHELdgg9DDWTg9yalaL8NQ
yo7Sn/HqyYH5UTFurlVahHuuZlcdeCtsH2cL5PnMQfqmKjCTCJ/iDzmaGpSX4Pt3
mAZIlQY15ze+WhA9b3noZkXoEGZJPwWN4nY7Xy07cBag0sEoWAJXKmgc2UMKNGbU
aOMmxQzsp3gxLW7LXEEWFsD/iC1fzNLiyXSKZVUtBTI3Kkk3ic9FAP5tYXLggyEu
Xk6jpPgLAxHF73M/E+xAxtPBpfDNbQUluAv9V6nTQwr1+ciaIYXeOoGClCgjwFkn
AxpiPAdujre9e3VeVBgkJR+5tNVLFysxCqOBqIgxo2p1ODeFsYOXpHn27PfSrJY=
=jl7W
-----END PGP SIGNATURE-----

Received on Friday, 25 April 2014 13:28:06 UTC