Skip to content

Commit 6e23c2d

Browse files
committed
feat(example-browser): Add fallback example
Adding an example of useing a fallback. This example uses MSRCrypto version 1.6.0.
1 parent bce3979 commit 6e23c2d

File tree

7 files changed

+9527
-2
lines changed

7 files changed

+9527
-2
lines changed
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<!DOCTYPE>
2+
3+
<html>
4+
<head>
5+
<meta charset="utf-8">
6+
<title>Client Side AWS Encryption SDK with MSRCrypto as a fallback</title>
7+
<script src="../build/fallback_bundle.js"></script>
8+
</head>
9+
<body>
10+
<script>
11+
// This is exported via the webpack library setting
12+
test.testFallback()
13+
</script>
14+
</body>
15+
</html>

modules/example-browser/package.json

+24-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
"example-aes": "webpack -d --config webpack_configs/aes.webpack.config.js",
1313
"example-kms": "webpack -d --config webpack_configs/kms.webpack.config.js",
1414
"example-multi-keyring": "webpack -d --config webpack_configs/multi_keyring.webpack.config.js",
15-
"example-caching-cmm": "webpack -d --config webpack_configs/caching_cmm.webpack.config.js"
15+
"example-caching-cmm": "webpack -d --config webpack_configs/caching_cmm.webpack.config.js",
16+
"example-fallback": "webpack -d --config webpack_configs/fallback.webpack.config.js"
1617
},
1718
"author": {
1819
"name": "AWS Crypto Tools Team",
@@ -22,9 +23,30 @@
2223
"license": "Apache-2.0",
2324
"dependencies": {
2425
"@aws-crypto/client-browser": "file:../client-browser",
26+
"@aws-sdk/util-base64-browser": "0.1.0-preview.1",
27+
"tslib": "^1.9.3",
2528
"@aws-sdk/util-base64-browser": "1.0.0-alpha.2",
26-
"tslib": "^1.9.3"
29+
"@types/chai": "^4.1.4",
30+
"@types/mocha": "^5.2.5",
31+
"@typescript-eslint/eslint-plugin": "^1.9.0",
32+
"@typescript-eslint/parser": "^1.9.0",
33+
"chai": "^4.1.2",
34+
"karma": "^4.1.0",
35+
"karma-chai": "^0.1.0",
36+
"karma-chrome-launcher": "^2.2.0",
37+
"karma-coverage-istanbul-reporter": "^2.0.4",
38+
"karma-mocha": "^1.3.0",
39+
"karma-webpack": "^3.0.5",
40+
"mocha": "^5.2.0",
41+
"nyc": "^14.0.0",
42+
"standard": "^12.0.1",
43+
"ts-loader": "^5.3.3",
44+
"ts-node": "^7.0.1",
45+
"typescript": "^3.5.0",
46+
"webpack": "^4.30.0",
47+
"webpack-cli": "^3.3.11"
2748
},
49+
"devDependencies": {},
2850
"main": "./build/main/index.js",
2951
"module": "./build/module/index.js",
3052
"types": "./build/main/index.d.ts"
+126
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/*
2+
* Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use
5+
* this file except in compliance with the License. A copy of the License is
6+
* located at
7+
*
8+
* http://aws.amazon.com/apache2.0/
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed on an
11+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12+
* implied. See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
/* This is a simple example of configuring a fallback
17+
* for the AWS Encryption SDK for Javascript
18+
* in a browser.
19+
*/
20+
21+
import {
22+
RawAesWrappingSuiteIdentifier,
23+
RawAesKeyringWebCrypto,
24+
encrypt,
25+
decrypt,
26+
synchronousRandomValues,
27+
configureFallback,
28+
AlgorithmSuiteIdentifier
29+
} from '@aws-crypto/client-browser'
30+
import { toBase64 } from '@aws-sdk/util-base64-browser'
31+
32+
/* In this example we use the JavaScript implementation
33+
* of WebCrypto from MSRCrypto
34+
* and configure it as a fallback for the AWS Encryption SDK.
35+
* The implementation will only be used if it is needed.
36+
* The AWS Encryption SDK will _always_ prefer the native browser implementation.
37+
* The msrCrypto source file is included as a script tag in the HTML file.
38+
* See fallback.html
39+
*/
40+
// @ts-ignore
41+
import { subtle } from './msrcrypto'
42+
configureFallback(subtle)
43+
44+
/* This is done to facilitate testing. */
45+
export async function testFallback () {
46+
/* You need to specify a name
47+
* and a namespace for raw encryption key providers.
48+
* The name and namespace that you use in the decryption keyring *must* be an exact,
49+
* *case-sensitive* match for the name and namespace in the encryption keyring.
50+
*/
51+
const keyName = 'aes-name'
52+
const keyNamespace = 'aes-namespace'
53+
54+
/* The wrapping suite defines the AES-GCM algorithm suite to use. */
55+
const wrappingSuite = RawAesWrappingSuiteIdentifier.AES256_GCM_IV12_TAG16_NO_PADDING
56+
57+
// Get your plaintext master key from wherever you store it.
58+
const unencryptedMasterKey = synchronousRandomValues(32)
59+
60+
/* Import the plaintext master key into a WebCrypto CryptoKey. */
61+
const masterKey = await RawAesKeyringWebCrypto.importCryptoKey(unencryptedMasterKey, wrappingSuite)
62+
63+
/* Configure the Raw AES keyring. */
64+
const keyring = new RawAesKeyringWebCrypto({ keyName, keyNamespace, wrappingSuite, masterKey })
65+
66+
/* Encryption context is a *very* powerful tool for controlling and managing access.
67+
* It is ***not*** secret!
68+
* Encrypted data is opaque.
69+
* You can use an encryption context to assert things about the encrypted data.
70+
* Just because you can decrypt something does not mean it is what you expect.
71+
* For example, if you are are only expecting data from 'us-west-2',
72+
* the origin can identify a malicious actor.
73+
* See: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context
74+
*/
75+
const context = {
76+
stage: 'demo',
77+
purpose: 'simple demonstration app',
78+
origin: 'us-west-2'
79+
}
80+
81+
/* Find data to encrypt. */
82+
const plainText = new Uint8Array([1, 2, 3, 4, 5])
83+
84+
/* Encrypt the data. */
85+
const { result } = await encrypt(keyring, plainText, { encryptionContext: context, suiteId: AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16 })
86+
87+
/* Log the plain text
88+
* only for testing and to show that it works.
89+
*/
90+
console.log('plainText:', plainText)
91+
document.body.insertAdjacentHTML('beforeend', `<p>plainText:<p>${plainText}</p> </p>`)
92+
93+
/* Log the base64-encoded result
94+
* so that you can try decrypting it with another AWS Encryption SDK implementation.
95+
*/
96+
const resultBase64 = toBase64(result)
97+
console.log(resultBase64)
98+
document.body.insertAdjacentHTML('beforeend', `<p>${resultBase64}</p>`)
99+
100+
const { plaintext, messageHeader } = await decrypt(keyring, result)
101+
102+
/* Grab the encryption context so you can verify it. */
103+
const { encryptionContext } = messageHeader
104+
105+
/* Verify the encryption context.
106+
* If you use an algorithm suite with signing,
107+
* the Encryption SDK adds a name-value pair to the encryption context that contains the public key.
108+
* Because the encryption context might contain additional key-value pairs,
109+
* do not add a test that requires that all key-value pairs match.
110+
* Instead, verify that the key-value pairs you expect match.
111+
*/
112+
Object
113+
.entries(context)
114+
.forEach(([key, value]) => {
115+
if (encryptionContext[key] !== value) throw new Error('Encryption Context does not match expected values')
116+
})
117+
118+
/* Log the clear message
119+
* only for testing and to show that it works.
120+
*/
121+
console.log(plaintext)
122+
document.body.insertAdjacentHTML('beforeend', `<p>plainText:<p>${plaintext}</p> </p>`)
123+
124+
/* Return the values to make testing easy. */
125+
return { plainText, plaintext }
126+
}

0 commit comments

Comments
 (0)