Let’s take a look at the Dapr cryptography building block. In this Quickstart, you’ll create an application that encrypts and decrypts data using the Dapr cryptography APIs. You’ll:
Currently, you can experience the cryptography API using the Go SDK.
This quickstart includes a JavaScript application called
crypto-quickstart
.
For this example, you will need:
Clone the sample provided in the Quickstarts repo
git clone https://github.com/dapr/quickstarts.git
In the terminal, from the root directory, navigate to the cryptography sample.
cd cryptography/javascript/sdk
Navigate into the folder with the source code:
cd ./crypto-quickstart
Install the dependencies:
npm install
The application code defines two required keys:
Generate two keys, an RSA key and and AES key using OpenSSL and write these to two files:
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
Run the Go service app with Dapr:
dapr run --app-id crypto-quickstart --resources-path ../../../components/ -- npm start
Expected output
== APP == 2023-10-25T14:30:50.435Z INFO [GRPCClient, GRPCClient] Opening connection to 127.0.0.1:58173
== APP == == Encrypting message using buffers
== APP == Encrypted the message, got 856 bytes
== APP == == Decrypting message using buffers
== APP == Decrypted the message, got 24 bytes
== APP == The secret is "passw0rd"
== APP == == Encrypting message using streams
== APP == Encrypting federico-di-dio-photography-Q4g0Q-eVVEg-unsplash.jpg to encrypted.out
== APP == Encrypted the message to encrypted.out
== APP == == Decrypting message using streams
== APP == Decrypting encrypted.out to decrypted.out.jpg
== APP == Decrypted the message to decrypted.out.jpg
local-storage.yaml
Earlier, you created a directory inside crypto-quickstarts
called keys
. In the local-storage
component YAML, the path
metadata maps to the newly created keys
directory.
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: localstorage
spec:
type: crypto.dapr.localstorage
version: v1
metadata:
- name: path
# Path is relative to the folder where the example is located
value: ./keys
index.mjs
The application file encrypts and decrypts messages and files using the RSA and AES keys that you generated. The application creates a new Dapr SDK client:
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);
}
Once the client is created, the application encrypts a message:
async function encryptDecryptBuffer(client) {
// Message to encrypt
const plaintext = `The secret is "passw0rd"`
// First, encrypt the message
console.log("== Encrypting message using buffers");
const encrypted = await client.crypto.encrypt(plaintext, {
componentName: "localstorage",
keyName: "rsa-private-key.pem",
keyWrapAlgorithm: "RSA",
});
console.log("Encrypted the message, got", encrypted.length, "bytes");
The application then decrypts the message:
// Decrypt the message
console.log("== Decrypting message using buffers");
const decrypted = await client.crypto.decrypt(encrypted, {
componentName: "localstorage",
});
console.log("Decrypted the message, got", decrypted.length, "bytes");
console.log(decrypted.toString("utf8"));
// ...
}
Next, the application encrypts a large image file:
async function encryptDecryptStream(client) {
// First, encrypt the message
console.log("== Encrypting message using streams");
console.log("Encrypting", testFileName, "to encrypted.out");
await pipeline(
createReadStream(testFileName),
await client.crypto.encrypt({
componentName: "localstorage",
keyName: "symmetric-key-256",
keyWrapAlgorithm: "A256KW",
}),
createWriteStream("encrypted.out"),
);
console.log("Encrypted the message to encrypted.out");
The application then decrypts the large image file:
// Decrypt the message
console.log("== Decrypting message using streams");
console.log("Decrypting encrypted.out to decrypted.out.jpg");
await pipeline(
createReadStream("encrypted.out"),
await client.crypto.decrypt({
componentName: "localstorage",
}),
createWriteStream("decrypted.out.jpg"),
);
console.log("Decrypted the message to decrypted.out.jpg");
}
This quickstart includes a Go application called
crypto-quickstart
.
For this example, you will need:
Clone the sample provided in the Quickstarts repo
git clone https://github.com/dapr/quickstarts.git
In the terminal, from the root directory, navigate to the cryptography sample.
cd cryptography/go/sdk
Navigate into the folder with the source code:
cd ./crypto-quickstart
The application code defines two required keys:
Generate two keys, an RSA key and and AES key using OpenSSL and write these to two files:
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
Run the Go service app with Dapr:
dapr run --app-id crypto-quickstart --resources-path ../../../components/ -- go run .
Expected output
== APP == dapr client initializing for: 127.0.0.1:52407
== APP == Encrypted the message, got 856 bytes
== APP == Decrypted the message, got 24 bytes
== APP == The secret is "passw0rd"
== APP == Wrote decrypted data to encrypted.out
== APP == Wrote decrypted data to decrypted.out.jpg
local-storage.yaml
Earlier, you created a directory inside crypto-quickstarts
called keys
. In the local-storage
component YAML, the path
metadata maps to the newly created keys
directory.
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: localstorage
spec:
type: crypto.dapr.localstorage
version: v1
metadata:
- name: path
# Path is relative to the folder where the example is located
value: ./keys
app.go
The application file encrypts and decrypts messages and files using the RSA and AES keys that you generated. The application creates a new Dapr SDK client:
func main() {
// Create a new Dapr SDK client
client, err := dapr.NewClient()
//...
// Step 1: encrypt a string using the RSA key, then decrypt it and show the output in the terminal
encryptDecryptString(client)
// Step 2: encrypt a large file and then decrypt it, using the AES key
encryptDecryptFile(client)
}
Once the client is created, the application encrypts a message:
func encryptDecryptString(client dapr.Client) {
// ...
// Encrypt the message
encStream, err := client.Encrypt(context.Background(),
strings.NewReader(message),
dapr.EncryptOptions{
ComponentName: CryptoComponentName,
// Name of the key to use
// Since this is a RSA key, we specify that as key wrapping algorithm
KeyName: RSAKeyName,
KeyWrapAlgorithm: "RSA",
},
)
// ...
// The method returns a readable stream, which we read in full in memory
encBytes, err := io.ReadAll(encStream)
// ...
fmt.Printf("Encrypted the message, got %d bytes\n", len(encBytes))
The application then decrypts the message:
// Now, decrypt the encrypted data
decStream, err := client.Decrypt(context.Background(),
bytes.NewReader(encBytes),
dapr.DecryptOptions{
// We just need to pass the name of the component
ComponentName: CryptoComponentName,
// Passing the name of the key is optional
KeyName: RSAKeyName,
},
)
// ...
// The method returns a readable stream, which we read in full in memory
decBytes, err := io.ReadAll(decStream)
// ...
// Print the message on the console
fmt.Printf("Decrypted the message, got %d bytes\n", len(decBytes))
fmt.Println(string(decBytes))
}
Next, the application encrypts a large image file:
func encryptDecryptFile(client dapr.Client) {
const fileName = "liuguangxi-66ouBTTs_x0-unsplash.jpg"
// Get a readable stream to the input file
plaintextF, err := os.Open(fileName)
// ...
defer plaintextF.Close()
// Encrypt the file
encStream, err := client.Encrypt(context.Background(),
plaintextF,
dapr.EncryptOptions{
ComponentName: CryptoComponentName,
// Name of the key to use
// Since this is a symmetric key, we specify AES as key wrapping algorithm
KeyName: SymmetricKeyName,
KeyWrapAlgorithm: "AES",
},
)
// ...
// Write the encrypted data to a file "encrypted.out"
encryptedF, err := os.Create("encrypted.out")
// ...
encryptedF.Close()
fmt.Println("Wrote decrypted data to encrypted.out")
The application then decrypts the large image file:
// Now, decrypt the encrypted data
// First, open the file "encrypted.out" again, this time for reading
encryptedF, err = os.Open("encrypted.out")
// ...
defer encryptedF.Close()
// Now, decrypt the encrypted data
decStream, err := client.Decrypt(context.Background(),
encryptedF,
dapr.DecryptOptions{
// We just need to pass the name of the component
ComponentName: CryptoComponentName,
// Passing the name of the key is optional
KeyName: SymmetricKeyName,
},
)
// ...
// Write the decrypted data to a file "decrypted.out.jpg"
decryptedF, err := os.Create("decrypted.out.jpg")
// ...
decryptedF.Close()
fmt.Println("Wrote decrypted data to decrypted.out.jpg")
}
Watch this demo video of the cryptography API from the Dapr Community Call #83:
We’re continuously working to improve our Quickstart examples and value your feedback. Did you find this Quickstart helpful? Do you have suggestions for improvement?
Join the discussion in our discord channel.