WIP: Crypto quickstart for JS

Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com>
This commit is contained in:
ItalyPaleAle 2023-06-08 12:16:23 -07:00
parent 7d140fee39
commit e0799feeb9
8 changed files with 4127 additions and 0 deletions

View File

@ -0,0 +1,5 @@
##lint files
*.cjs
##node modules
node_modules

View File

@ -0,0 +1,68 @@
# Dapr cryptography (Dapr SDK)
In this quickstart, you'll create an application that encrypts, and then decrypts, data using the Dapr cryptography APIs (high-level). We will:
- Encrypt and then decrypt a short string, reading the result in-memory, in a Buffer
- Encrypt and then decrypt a large file, storing the encrypted and decrypted data to files using Node.js streams
Visit the documentation to learn more about the [Cryptography building block](https://v1-11.docs.dapr.io/developing-applications/building-blocks/cryptography/) in Dapr.
> **Note:** This example uses the Dapr SDK. Using the Dapr SDK, which leverages gRPC internally, is **strongly** recommended when using the high-level cryptography APIs (to encrypt and decrypt messages).
This quickstart includes one application:
- Node.js application `crypto-quickstart`
### Run Node.js service with Dapr
1. Navigate into the folder with the source and install dependencies:
<!-- STEP
name: Install Node dependencies
-->
```bash
cd ./crypto-quickstart
npm ci
```
<!-- END_STEP -->
2. This sample requires a private RSA key and a 256-bit symmetric (AES) key. We will generate them using OpenSSL:
<!-- STEP
name: Generate keys
working_dir: crypto-quickstart
expected_stdout_lines:
expected_stderr_lines:
-->
```bash
mkdir -p keys
# Generate a private RSA key, 4096-bit keys
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out keys/rsa-private-key.pem
# Generate a 256-bit key for AES
openssl rand -out keys/symmetric-key-256 32
```
<!-- END_STEP -->
3. Run the Node.js service app with Dapr:
<!-- STEP
name: Run Node publisher
expected_stdout_lines:
- "== APP == Saving Order: { orderId: '1' }"
- "== APP == Getting Order: { orderId: '1' }"
- "Exited App successfully"
expected_stderr_lines:
working_dir: ./crypto-quickstart
output_match_mode: substring
background: true
sleep: 10
-->
```bash
dapr run --app-id crypto-quickstart --resources-path ../../../components/ -- npm start
```
<!-- END_STEP -->

View File

@ -0,0 +1,6 @@
# Output files
encrypted.out
decrypted.out.jpg
# Generated keys
keys/

Binary file not shown.

After

Width:  |  Height:  |  Size: 617 KiB

View File

@ -0,0 +1,87 @@
import { createReadStream, createWriteStream } from "node:fs";
import { readFile, writeFile } from "node:fs/promises";
import { pipeline } from "node:stream/promises";
import { DaprClient, CommunicationProtocolEnum } from "@dapr/dapr";
const daprHost = process.env.DAPR_HOST ?? "127.0.0.1";
const daprPort = process.env.DAPR_GRPC_PORT ?? "50001";
const testFileName = "federico-di-dio-photography-Q4g0Q-eVVEg-unsplash.jpg";
async function start() {
const client = new DaprClient({
daprHost,
daprPort,
communicationProtocol: CommunicationProtocolEnum.GRPC,
});
// Encrypt and decrypt a message from a buffer
await encryptDecryptBuffer(client);
// Encrypt and decrypt a message using streams
await encryptDecryptStream(client);
}
async function encryptDecryptBuffer(client) {
// Message to encrypt
const plaintext = `The secret is "passw0rd"`
// First, encrypt the message
console.log("== Encrypting message using buffers");
const ciphertext = await client.crypto.encrypt(plaintext, {
componentName: "crypto-local",
keyName: "my-rsa-key",
keyWrapAlgorithm: "RSA",
});
console.log("Encrypted the message, got", ciphertext.length, "bytes");
// Decrypt the message
console.log("== Decrypting message using buffers");
const decrypted = await client.crypto.decrypt(ciphertext, {
componentName: "crypto-local",
});
console.log("Decrypted the message, got", decrypted.length, "bytes");
console.log(decrypted.toString("utf8"));
// The contents should be equal
if (decrypted.toString("utf8") != plaintext) {
throw new Error("Decrypted message does not match original message");
}
}
async function encryptDecryptStream(client) {
// First, encrypt the message
console.log("== Encrypting message using streams");
console.log("Encrypting", testFileName, "to ciphertext.out");
await pipeline(
createReadStream(testFileName),
await client.crypto.encrypt({
componentName: "crypto-local",
keyName: "symmetric256",
keyWrapAlgorithm: "A256KW",
}),
createWriteStream("ciphertext.out"),
);
console.log("Encrypted the message to ciphertext.out");
// Decrypt the message
console.log("== Decrypting message using streams");
console.log("Encrypting ciphertext.out to plaintext.out");
await pipeline(
createReadStream("ciphertext.out"),
await client.crypto.decrypt({
componentName: "crypto-local",
}),
createWriteStream("plaintext.out.jpg"),
);
console.log("Decrypted the message to plaintext.out.jpg");
}
await start();

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,20 @@
{
"name": "crypto-quickstart",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"start": "node index.mjs",
"start:dapr": "dapr run --app-id crypto-quickstart --dapr-grpc-port 50001 -- npm run start"
},
"keywords": [],
"author": "",
"license": "MIT",
"dependencies": {
"@dapr/dapr": "^3.0.0"
},
"devDependencies": {
"eslint": "^8.42.0"
}
}

View File

@ -0,0 +1,9 @@
include ../../../docker.mk
include ../../../validate.mk
# Remove generated files
.PHONY: clean
clean:
-rm -r crypto-quickstart/keys
-rm crypto-quickstart/encrypted.out
-rm crypto-quickstart/decrypted.out.jpg