Skip to content

Commit 81c22ab

Browse files
authored
initial commit example-browser (#69)
Examples of how to use the AWS Encryption SDK for JavaScript in a browser.
1 parent 24c72da commit 81c22ab

File tree

13 files changed

+434
-3
lines changed

13 files changed

+434
-3
lines changed

modules/example-browser/Readme.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# AWS Encryption SDK for Javascript examples in a browser
2+
3+
This repository holds examples for encrypt and decrypt in a browser
4+
using KMS and RSA keys.
5+
6+
# To test KMS encryption in a browser locally on OSX
7+
8+
```
9+
npm run example:kms
10+
open kms_simple.html
11+
```
12+
13+
# To test RSA encryption in a browser locally on OSX
14+
15+
```
16+
npm run example:rsa
17+
open rsa_simple.html
18+
```
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
const webpack = require('webpack')
2+
const path = require('path')
3+
const {defaultProvider} = require('@aws-sdk/credential-provider-node')
4+
5+
module.exports = (async () => ({
6+
entry: './src/kms_simple.ts',
7+
// devtool: 'inline-source-map',
8+
module: {
9+
rules: [
10+
{
11+
test: /kms_simple.ts$/,
12+
use: [
13+
{
14+
loader: 'ts-loader',
15+
options: {
16+
configFile: 'tsconfig.module.json'
17+
}
18+
}
19+
],
20+
include: /kms_simple.ts/,
21+
exclude: [/node_modules/, /rsa_simple/]
22+
}
23+
]
24+
},
25+
resolve: {
26+
extensions: [ '.tsx', '.ts', '.js' ]
27+
},
28+
output: {
29+
filename: 'kms_simple_bundle.js',
30+
path: path.resolve(__dirname, 'build')
31+
},
32+
plugins: [
33+
new webpack.DefinePlugin({
34+
'AWS_CREDENTIALS': JSON.stringify(await defaultProvider()())
35+
})
36+
],
37+
node: {
38+
util: 'empty'
39+
}
40+
}))()
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<!DOCTYPE>
2+
3+
<html>
4+
<head>
5+
<meta charset="utf-8">
6+
<title>Client Side KMS Encryption Test</title>
7+
<script src="./build/kms_simple_bundle.js"></script>
8+
</head>
9+
<body>
10+
</html>

modules/example-browser/package.json

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{
2+
"name": "@aws-crypto/example-browser",
3+
"private": true,
4+
"version": "0.0.1",
5+
"scripts": {
6+
"prepublishOnly": "npm run build",
7+
"build": "tsc -b tsconfig.json && tsc -b tsconfig.module.json",
8+
"test": "mocha --require ts-node/register tests/**/*tests.ts",
9+
"example:rsa": "webpack -d --config rsa.webpack.config.js",
10+
"example:kms": "webpack -d --config kms.webpack.config.js"
11+
},
12+
"author": {
13+
"name": "AWS Crypto Tools Team",
14+
"email": "[email protected]",
15+
"url": "https://aws.amazon.com/javascript/"
16+
},
17+
"license": "Apache-2.0",
18+
"dependencies": {
19+
"@aws-crypto/decrypt-browser": "^0.0.1",
20+
"@aws-crypto/encrypt-browser": "^0.0.1",
21+
"@aws-crypto/material-management-browser": "^0.0.1",
22+
"@aws-crypto/raw-rsa-keyring-browser": "^0.0.1",
23+
"@aws-crypto/kms-keyring-browser": "^0.0.1",
24+
"@aws-sdk/util-base64-browser": "0.1.0-preview.1",
25+
"tslib": "^1.9.3"
26+
},
27+
"devDependencies": {
28+
"@types/chai": "^4.1.4",
29+
"@types/mocha": "^5.2.5",
30+
"chai": "^4.1.2",
31+
"mocha": "^5.2.0",
32+
"ts-loader": "^5.3.3",
33+
"ts-node": "^7.0.1",
34+
"typescript": "^3.2.0",
35+
"webpack": "^4.30.0",
36+
"@aws-sdk/credential-provider-node": "^0.1.0-preview.4",
37+
"webpack-cli": "^3.3.0"
38+
},
39+
"main": "./build/main/index.js",
40+
"module": "./build/module/index.js",
41+
"types": "./build/main/index.d.ts"
42+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
const path = require('path')
2+
3+
module.exports = {
4+
entry: './src/rsa_simple.ts',
5+
// devtool: 'inline-source-map',
6+
module: {
7+
rules: [
8+
{
9+
test: /rsa_simple.ts$/,
10+
use: [
11+
{
12+
loader: 'ts-loader',
13+
options: {
14+
configFile: 'tsconfig.module.json'
15+
}
16+
}
17+
],
18+
include: /rsa_simple.ts/,
19+
exclude: [/node_modules/, /kms_simple/]
20+
}
21+
]
22+
},
23+
resolve: {
24+
extensions: [ '.tsx', '.ts', '.js' ]
25+
},
26+
output: {
27+
filename: 'rsa_simple_bundle.js',
28+
path: path.resolve(__dirname, 'build')
29+
}
30+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!DOCTYPE>
2+
3+
<html>
4+
<head>
5+
<meta charset="utf-8">
6+
<title>Client Side RSA Encryption Test</title>
7+
<script src="./build/rsa_simple_bundle.js"></script>
8+
</head>
9+
<body>
10+
</body>
11+
</html>

modules/example-browser/src/index.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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+
/*
17+
* Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
18+
*
19+
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use
20+
* this file except in compliance with the License. A copy of the License is
21+
* located at
22+
*
23+
* http://aws.amazon.com/apache2.0/
24+
*
25+
* or in the "license" file accompanying this file. This file is distributed on an
26+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
27+
* implied. See the License for the specific language governing permissions and
28+
* limitations under the License.
29+
*/
30+
31+
/*
32+
* This library has no exported implementation.
33+
* It is intended to be used as a reference.
34+
*/
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
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 using a KMS Keyring
17+
* to encrypt and decrypt using the AWS Encryption SDK for Javascript in a browser.
18+
*/
19+
20+
import { encrypt } from '@aws-crypto/encrypt-browser'
21+
import { decrypt } from '@aws-crypto/decrypt-browser'
22+
import {
23+
KmsKeyringBrowser,
24+
KMS,
25+
getClient
26+
} from '@aws-crypto/kms-keyring-browser'
27+
import { toBase64 } from '@aws-sdk/util-base64-browser'
28+
29+
/* This is injected by webpack.
30+
* The webpack.DefinePlugin will replace the values when bundling.
31+
* The credential values are pulled from @aws-sdk/credential-provider-node
32+
* Use any method you like to get credentials into the browser.
33+
* See kms.webpack.config
34+
*/
35+
declare const AWS_CREDENTIALS: {accessKeyId: string, secretAccessKey:string }
36+
37+
;(async function kmsSimpleExample () {
38+
/* A KMS CMK to generate the data key is required.
39+
* Access to KMS generateDataKey is required for the generatorKeyId.
40+
*/
41+
const generatorKeyId = 'arn:aws:kms:us-west-2:658956600833:alias/EncryptDecrypt'
42+
43+
/* Adding Alternate KMS keys that can decrypt.
44+
* Access to KMS encrypt is required for every CMK in keyIds.
45+
* Often this used to have a local CMK in multiple regions.
46+
* In this example, I am using the same CMK.
47+
* This is *only* to demonstrate how the CMK ARN's are configured.
48+
*/
49+
const keyIds = ['arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f']
50+
51+
/* Need a client provider that will inject correct credentials.
52+
* The credentials here are injected by webpack from your environment bundle is created
53+
* The credential values are pulled using @aws-sdk/credential-provider-node.
54+
* See kms.webpack.config
55+
* You should inject your credential into the browser in a secure manner,
56+
* that works with your application.
57+
*/
58+
const { accessKeyId, secretAccessKey } = AWS_CREDENTIALS
59+
60+
/* getClient takes a KMS client constructor
61+
* and optional configuration values.
62+
* The credentials can be injected here,
63+
* because browser do not have a standard credential discover process the way Node.js does.
64+
*/
65+
const clientProvider = getClient(KMS, {
66+
credentials: {
67+
accessKeyId,
68+
secretAccessKey
69+
}
70+
})
71+
72+
/* The KMS Keyring must be configured with the desired CMK's */
73+
const keyring = new KmsKeyringBrowser({ clientProvider, generatorKeyId, keyIds })
74+
75+
/* Encryption Context is a *very* powerful tool for controlling and managing access.
76+
* It is ***not*** secret!
77+
* Remember encrypted data is opaque, encryption context will help your run time checking.
78+
* Just because you have decrypted a JSON file, and it successfully parsed,
79+
* does not mean it is the intended JSON file.
80+
*/
81+
const context = {
82+
stage: 'demo',
83+
purpose: 'simple demonstration app',
84+
origin: 'us-west-2'
85+
}
86+
87+
/* I need something to encrypt. */
88+
const plainText = new Uint8Array([1, 2, 3, 4, 5])
89+
90+
/* Encrypt the data. */
91+
const { cipherMessage } = await encrypt(keyring, plainText, { encryptionContext: context })
92+
93+
/* Log the plain text. */
94+
console.log('plainText:', plainText)
95+
document.write('</br>plainText:' + plainText + '</br>')
96+
97+
/* In case you want to check compatibility, I log the cipher text. */
98+
const cipherMessageBase64 = toBase64(cipherMessage)
99+
console.log(cipherMessageBase64)
100+
document.write(cipherMessageBase64)
101+
102+
const { clearMessage, messageHeader } = await decrypt(keyring, cipherMessage)
103+
104+
/* Grab the encryption context so I can verify it. */
105+
const { encryptionContext } = messageHeader
106+
107+
/* Verify the encryption context.
108+
* Depending on the Algorithm Suite, the `encryptionContext` _may_ contain additional values.
109+
* In Signing Algorithm Suites the public verification key is serialized into the `encryptionContext`.
110+
* So it is best to make sure that all the values that you expect exist as opposed to the reverse.
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+
document.write('</br>Decrypted:' + clearMessage)
120+
console.log(clearMessage)
121+
})()

0 commit comments

Comments
 (0)