The open source TodoMVC project implements a Todo application using popular JavaScript MV* frameworks. Some of the implementations add support for compile to JavaScript languages, module loaders and real time backends. This presentation will demonstrate a TodoMVC implementation which adds support for the forthcoming W3C Web Cryptography API, as well as review some key cryptographic concepts and definitions.
Instead of storing the Todo list as plaintext in localStorage, this "secure" TodoMVC implementation encrypts Todos using a password derived key. The PBKDF2 algorithm is used for the deriveKey operation, with getRandomValues generating a cryptographically random salt. The importKey method sets up usage of AES-CBC for both encrypt and decrypt operations. The final solution helps address item "A6-Sensitive Data Exposure" from the OWASP Top 10.
With the Web Cryptography API being a recommendation in 2014, any Q&A time will likely include browser implementations and limitations, and whether JavaScript cryptography adds any value.
3. Project which offers the same Todo application
implemented using MV* concepts in most of the popular
JavaScript MV* frameworks of today.
http://todomvc.com/
https://github.com/tastejs/todomvc
4.
5. Today's Session "todos"
● Review some cryptography concepts
● Look at the Web Cryptography API
● Combine these to secure TodoMVC
6. Supporting Materials
(if you want to follow along)
Presentation and Source Code
https://github.com/hakanson/todomvc-jquery-webcryptoapi
Demo
https://hakanson.github.io/todomvc-jquery-webcryptoapi
8. TodoMVC Uses localStorage
Chrome keeps localStorage in an SQLite file:
OS X: ~/Library/Application Support/Google/Chrome/Default/Local Storage
Windows: %HOMEPATH%AppDataLocalGoogleChromeUser DataDefaultLocal Storage
$ sqlite3 http_todomvc.com_0.localstorage
sqlite> select * from ItemTable;
todos-jquery|[{"id":"c8f7b7e1-88bf-451b-8aff-
04c9ac2544aa","title":"secure using Web
Cryptography API","completed":false}]
9. OWASP Top 10 2013
● A1-Injection
● A2-Broken Authentication and Session Management
● A3-Cross-Site Scripting (XSS)
● A4-Insecure Direct Object References
● A5-Security Misconfiguration
● A6-Sensitive Data Exposure
● A7-Missing Function Level Action Control
● A8-Cross-Site Request Forgery (CSRF)
● A9-Using Components with Known Vulnerabilities
● A10-Unvalidated Redirects and Forwards
https://www.owasp.org/index.php/Top_10_2013
10. A6-Sensitive Data Exposure
Covers sensitive data protection from the
moment sensitive data is provided by the user,
sent to and stored within the application, and
then sent back to the browser again.
11. A6-Sensitive Data Exposure
Am I Vulnerable To 'Sensitive Data Exposure'?
1. Is any of this data stored in clear text long term,
including backups of this data?
2. …
3. …
4. …
5. …
https://www.owasp.org/index.php/Top_10_2013-A6
12. Acceptance Criteria
● Enter password before accessing "todos"
● Data encrypted "at rest" in localStorage
14. W3C Web Cryptography API
This specification describes a JavaScript API
for performing basic cryptographic operations in
web applications, such as hashing, signature
generation and verification, and encryption and
decryption.
http://www.w3.org/TR/WebCryptoAPI/
16. SubtleCrypto Interface
● Provides a set of methods for dealing with
low-level cryptographic primitives and
algorithms.
● Named SubtleCrypto to reflect the fact that
many of these algorithms have subtle usage
requirements in order to provide the required
algorithmic security guarantees.
17. Web Cryptography Working Group
Key Dates
○ April 2012: Group Formation
○ March 2014: Last Call Working Draft
○ ????: Expected Candidate Recommendation
○ ????: Expected Proposed Recommendation
○ 2015: Expected Recommendation
http://www.w3.org/2012/webcrypto/Overview.html
19. Chromium Dashboard
Web Crypto API
Implementation Status
Enabled by default in desktop Chrome 37 (launch bug)
Available in Chrome for Android release 37.
Consensus & Standardization
● Firefox: In development
● Internet Explorer: In development
● Opera: Shipped in release 24
● Opera for Android: Shipped in release 24
● Safari: In development
● Web Developers: Mixed signals
21. IE Platform Status
Web Crypto API
Note: IE11 implementation based on spec before
change from CryptoOperation to Promise based API
22. Promises/A+
A promise represents the eventual result of an
asynchronous operation. The primary way of
interacting with a promise is through its then
method, which registers callbacks to receive
either a promise's eventual value or the reason
why the promise cannot be fulfilled.
23. Chromium Dashboard
Promises (ES6)
Implementation Status
Enabled by default in desktop Chrome 32 (launch bug)
Available in Chrome for Android release 32.
Consensus & Standardization
● Firefox: Shipped
● Internet Explorer: Public support
● Opera: Shipped in release 19
● Opera for Android: Shipped in release 19
● Safari: In development
● Web Developers: Mixed signals
24. Microsoft Research JavaScript
Cryptography Library
● The algorithms are exposed via the W3C
WebCrypto interface, and are tested against
the Internet Explorer 11 implementation of
that interface.
● This library is under active development.
Future updates to this library may change
the programming interfaces.
Date Published: 17 June 2014
26. Javascript Cryptography Considered
Harmful (circa 2010)
● Opinion on browser Javascript cryptography
○ "no reliable way for any piece of Javascript code to
verify its execution environment"
○ "can't outsource random number generation in a
cryptosystem"
○ "practically no value to doing crypto in Javascript
once you add SSL to the mix"
○ "store the key on that server [and] documents there"
http://www.matasano.com/articles/javascript-cryptography/
● Didn't consider the "offline" user experience
27. Host-Proof Hosting
● In A Blink
○ Sketch: Locked inside data cloud, key at browser.
● Solution
○ Host sensitive data in encrypted form, so that clients
can only access and manipulate it by providing a
pass-phrase which is never transmitted to the
server.
○ All encryption and decryption takes place inside the
browser itself.
http://ajaxpatterns.org/Host-Proof_Hosting (July 2005)
28. Host-Proof Hosting "Requirements"
● Secure transport mechanism (HTTPS).
● Trust provider that hosts web application and
serves HTML and JavaScript resources.
● Defend against and accept risk of script
injection (XSS) threat.
○ However, unauthorized access by hackers only
attacks users who access the application while
infected, and not the entire persisted data store.
29. My "Requirement"
● Avoid proving "Schneier's Law"
○ Anyone can invent a security system that he himself
cannot break.
31. Glossary
Glossary of Key Information Security Terms
http://nvlpubs.nist.gov/nistpubs/ir/2013/NIST.IR.7298r2.pdf
SOURCE: NISTIR 7298
32. Cryptography
The discipline that embodies principles, means,
and methods for providing information security,
including confidentiality, data integrity, non-repudiation,
and authenticity.
SOURCE: SP 800-21
33. Pseudorandom number generator
(PRNG)
An algorithm that produces a sequence of bits
that are uniquely determined from an initial
value called a seed. The output of the PRNG
“appears” to be random.
A cryptographic PRNG has the additional
property that the output is unpredictable, given
that the seed is not known.
SOURCE: CNSSI-4009
34. crypto.getRandomValues()
If you provide an integer-based TypedArray,
the function is going fill the array with
cryptographically random numbers.
var buf = new Uint8Array(32);
window.crypto.getRandomValues(buf);
https://developer.mozilla.org/en-US/docs/DOM/window.crypto.getRandomValues
http://msdn.microsoft.com/en-us/library/ie/dn302324(v=vs.85).aspx
35. Cryptographic Hash Function
A function that maps a bit string of arbitrary
length to a fixed length bit string.
Approved hash functions satisfy the following
properties:
● One-way
● Collision resistant
SOURCE: SP 800-21
36. Message Digest
The result of applying a hash function to a
message. Also known as a “hash value” or
“hash output”.
SOURCE: SP 800-107
37. OpenSSL Command Line
$ echo -n "The quick brown fox jumps over the
lazy dog" | openssl dgst -sha256
(stdin)=
d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb76
2d02d0bf37c9e592
38. QUnit Test
QUnit.test( 'SHA-256', function ( assert ) {
var testVector = {
data: 'The quick brown fox jumps over the lazy dog',
sha256Hash : 'd7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592'
};
var encoder = new TextEncoder();
var dataBuf = encoder.encode( testVector.data );
assert.promise( crypto.subtle.digest( { name: 'sha-256' }, dataBuf )
.then( function (result) {
var hash = $.Uint8Util.toHexString( new Uint8Array( result ) );
assert.equal( hash, testVector.sha256Hash );
}));
});
39. QUnit Extension
QUnit.extend( QUnit.assert, {
promise: function ( promise ) {
var assert = this;
QUnit.stop();
promise.catch( function ( err ) {
assert.ok( false, err.message );
}).then( function ( ) {
QUnit.start();
});
}
});
40. ex: DOMException
code: 9
message: "WebCrypto is only supported over secure origins. See
http://crbug.com/373032"
name: "NotSupportedError"
__proto__: DOMException
For example these are considered secure origins:
● chrome-extension://xxx
● https://xxx
● wss://xxx
● file://xxx
● http://localhost/
● http://127.0.0.1/
Whereas these are considered insecure:
● http://foobar
● ws://foobar
41. TextEncoder
Encoding API
Script API to allow encoding/decoding of strings from
binary data.
Firefox 19
https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder
Intent to Ship in Chrome 38
Issue 243354: Implement Text Encoding API
Polyfill
https://github.com/inexorabletash/text-encoding
42. $.Uint8Util
toHexString( buf : Uint8Array ) : string
fromHexString ( s : string ) : Uint8Array
(still looking for a better way)
44. Hash-based Message Authentication
Code (HMAC)
A message authentication code that uses a
cryptographic key in conjunction with a hash
function.
SOURCE: FIPS 201; CNSSI-4009
45. Cryptographic Key
A parameter used in conjunction with a cryptographic
algorithm that determines
● the transformation of plaintext data into ciphertext data,
● the transformation of ciphertext data into plaintext data,
● a digital signature computed from data,
● ...
SOURCE: FIPS 140-2
46. Symmetric Key
A cryptographic key that is used to perform
both the cryptographic operation and its
inverse, for example to encrypt and decrypt, or
create a message authentication code and to
verify the code.
SOURCE: SP 800-63; CNSSI-4009
47. Digital Signature
The result of a cryptographic transformation of
data which, when properly implemented,
provides the services of:
1. origin authentication,
2. data integrity, and
3. signer non-repudiation.
SOURCE: FIPS 140-2
48. OpenSSL Command Line
$ echo -n "The quick brown fox jumps
over the lazy dog" | openssl dgst -
sha256 -hmac "key"
(stdin)=
f7bc83f430538424b13298e6aa6fb143ef4d59
a14946175997479dbc2d1a3cd8
49. QUnit.test( 'HMAC using SHA-256', function ( assert ) {
var testVector = {
data: 'The quick brown fox jumps over the lazy dog',
key: 'key',
hash : 'f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8'
};
var hmacSha256 = { name: 'hmac', hash: { name: 'sha-256' } };
var encoder = new TextEncoder();
var dataBuf = encoder.encode( testVector.data );
var keyBuf = encoder.encode( testVector.key );
});
50. QUnit.test( 'HMAC using SHA-256', function ( assert ) {
var testVector = {
data: 'The quick brown fox jumps over the lazy dog',
key: 'key',
hash : 'f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8'
};
var hmacSha256 = { name: 'hmac', hash: { name: 'sha-256' } };
var encoder = new TextEncoder();
var dataBuf = encoder.encode( testVector.data );
var keyBuf = encoder.encode( testVector.key );
assert.promise( crypto.subtle.importKey( 'raw', keyBuf, hmacSha256,
true, ['sign', 'verify'] )
.then( function ( keyResult ) {
}));
});
51. QUnit.test( 'HMAC using SHA-256', function ( assert ) {
var testVector = {
data: 'The quick brown fox jumps over the lazy dog',
key: 'key',
hash : 'f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8'
};
var hmacSha256 = { name: 'hmac', hash: { name: 'sha-256' } };
var encoder = new TextEncoder();
var dataBuf = encoder.encode( testVector.data );
var keyBuf = encoder.encode( testVector.key );
assert.promise( crypto.subtle.importKey( 'raw', keyBuf, hmacSha256,
true, ['sign', 'verify'] )
.then( function ( keyResult ) {
return crypto.subtle.sign( hmacSha256, keyResult, dataBuf )
.then( function ( signResult ) {
var hash = $.Uint8Util.toHexString( new Uint8Array( signResult ) );
assert.equal( hash, testVector.hash );
})
}));
});
52. KJH-256 Hash
QUnit.test( 'KJH-256', function ( assert ) {
var testVector = {
data: 'The quick brown fox jumps over the lazy dog',
};
var encoder = new TextEncoder();
var dataBuf = encoder.encode( testVector.data );
assert.promise( crypto.subtle.digest( { name: 'kjh-256' }, dataBuf )
.then( function ( result ) {
var hash = $.Uint8Util.toHexString( new Uint8Array( result ) );
assert.equal( hash, 'kjh' );
}));
});
53. Error Results
IE 11
NotSupportedError
Chrome 37
Algorithm: Unrecognized name
Firefox 35
An invalid or illegal string was specified
Opera 24
Algorithm: Unrecognized name
MSR Crypto 1.2
unsupported algorithm
Webkit Nightly
NotSupportedError: DOM Exception 9
54. QUnit.test( 'HMAC using KJH-256', function ( assert ) {
var testVector = {
data: 'The quick brown fox jumps over the lazy dog',
key: 'key'
};
var encoder = new TextEncoder();
var dataBuf = encoder.encode( testVector.data );
var keyBuf = encoder.encode( testVector.key );
var hmacKjh256 = { name: 'hmac', hash: { name: 'kjh-256' } };
assert.promise( crypto.subtle.importKey( 'raw', keyBuf, hmacKjh256,
true, ['sign', 'verify'] )
.then( function ( keyResult ) {
return crypto.subtle.sign( hmacKjh256, keyResult, dataBuf )
.then( function ( signResult ) {
var hash = $.Uint8Util.toHexString( new Uint8Array( signResult ) );
assert.equal( hash, 'kjh' );
})
}));
});
55. Error Results
IE 11
failed, expected argument to be truthy, was: false
Chrome 37
HmacImportParams: hash: Algorithm: Unrecognized name
Firefox 35
An invalid or illegal string was specified
Opera 24
HmacImportParams: hash: Algorithm: Unrecognized name
MSR Crypto 1.2
Error: unsupported hash alorithm (sha-224, sha-256, sha-384, sha-512)
Webkit Nightly
NotSupportedError: DOM Exception 9
56.
57. Cipher, Plaintext and Ciphertext
Cipher - Series of transformations that
converts plaintext to ciphertext using the
Cipher Key.
See Also: Inverse Cipher
SOURCE: FIPS 197
58. AES
The Advanced Encryption Standard specifies a
U.S. government approved cryptographic
algorithm that can be used to protect electronic
data.
The AES algorithm is a symmetric block cipher
that can encrypt (encipher) and decrypt
(decipher) information.
SOURCE: FIPS 197
59. (CC BY 3.0) http://www.moserware.com/2009/09/stick-figure-guide-to-advanced.html
60. Initialization Vector (IV)
A vector used in defining the starting point of an
encryption process within a cryptographic
algorithm.
SOURCE: FIPS 140-2
70. Password-Based Key Derivation
Functions (PBKDF)
● The randomness of cryptographic keys is
essential for the security of cryptographic
applications.
SOURCE: SP 800-132
71. Password-Based Key Derivation
Functions (PBKDF)
● The randomness of cryptographic keys is
essential for the security of cryptographic
applications.
● Most user-chosen passwords have low
entropy and weak randomness properties.
○ shall not be used directly as cryptographic keys
SOURCE: SP 800-132
72. Password-Based Key Derivation
Functions (PBKDF)
● The randomness of cryptographic keys is
essential for the security of cryptographic
applications.
● Most user-chosen passwords have low
entropy and weak randomness properties.
○ shall not be used directly as cryptographic keys
● KDFs are deterministic algorithms that are
used to derive cryptographic keying material
from a secret value, such as a password.
SOURCE: SP 800-132
73. Salt
A non-secret value that is used in a
cryptographic process, usually to ensure that
the results of computations for one instance
cannot be reused by an Attacker.
SOURCE: SP 800-63; CNSSI-4009
74. PBKDF Specification
Input:
P Password
S Salt
C Iteration count
kLen Length of MK in bits; at most (232-1) x hLen
Parameter:
PRF HMAC with an approved hash function
hlen Digest size of the hash function
Output:
mk Master key
http://csrc.nist.gov/publications/nistpubs/800-132/nist-sp800-132.pdf
79. Data Flow and Storage (expected)
● Salt = initial random
● IV = initial random
● Ciphertext = AES( todos, Key, IV )
80. Data Flow and Storage (actual)
● PBKDF2 only implemented in Firefox 33
● Substitute HMAC to generate 256 bit key
○ (do not try this at home)
81. Set and Confirm Password
On first use, password must be established.
82. Password Entry Field
<header id="header">
<h1><span>secure</span> todos</h1>
<input id="new-todo"
placeholder="What needs to be done?"
class="hidden">
<input id="todo-password"
type="password"
placeholder="Enter Password"
autofocus
class="edit">
</header>
83. Render Password Entry Field
render: function () {
var todos, placeholder;
if (this.todos) {
this.$password.addClass('hidden');
// todos list rendering...
} else {
if (!cryptoStorage.initialized) {
placeholder = (this.$password.data('confirm') ?
'Confirm Password' : 'Set Password');
this.$password.attr('placeholder', placeholder);
}
this.$password.removeClass('hidden').focus();
}
}
84. Enter and Validate Password
On subsequent uses, password must be
entered to unlock todos.
An invalid password will shake the password
input field and outline in red.
87. validatePassword: function (password, confirmPassword) {
var that = this;
if (confirmPassword && confirmPassword != password) {
return new Promise(function (resolve, reject) {
reject(new Error('passwords do not match'));
});
}
return cryptoStorage.authenticate(password).then(function () {
return util.store();
}).then(function (result) {
that.todos = result;
})
}
88. Convert store to return a Promise
store: function (data) {
if (data) {
return cryptoStorage.setItem(data);
} else {
return cryptoStorage.getItem();
}
}