Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Examples: Added Crypto #492

Merged
merged 2 commits into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions daprdocs/content/en/go-sdk-docs/go-client/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ To encrypt:

```go
// Encrypt the data using Dapr
out, err := sdkClient.Encrypt(context.Background(), rf, dapr.EncryptOptions{
out, err := client.Encrypt(context.Background(), rf, dapr.EncryptOptions{
// These are the 3 required parameters
ComponentName: "mycryptocomponent",
KeyName: "mykey",
Expand All @@ -419,7 +419,7 @@ To decrypt:

```go
// Decrypt the data using Dapr
out, err := sdkClient.Decrypt(context.Background(), rf, dapr.EncryptOptions{
out, err := client.Decrypt(context.Background(), rf, dapr.EncryptOptions{
// Only required option is the component name
ComponentName: "mycryptocomponent",
})
Expand Down
69 changes: 69 additions & 0 deletions examples/crypto/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Dapr Crypto Example with go-sdk

## Step

### Prepare

- Dapr installed

> In order to run this sample, make sure that OpenSSL is available on your system.


This sample requires a private RSA key and a 256-bit symmetric (AES) key. We will generate them using OpenSSL:

```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 Go service app with Dapr:

<!-- STEP
name: Run crypto service
expected_stdout_lines:
- '== 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'
- "Exited App successfully"
expected_stderr_lines:
output_match_mode: substring
-->

```bash
dapr run --app-id crypto --resources-path ./components/ -- go run .
```

<!-- END_STEP -->

### Cleanup

<!-- STEP
expected_stdout_lines:
- '✅ app stopped successfully: crypto'
expected_stderr_lines:
name: Shutdown dapr
-->

```bash
dapr stop --app-id crypto
(lsof -i:8080 | grep crypto) | awk '{print $2}' | xargs kill
```

<!-- END_STEP -->

## Result

```shell
== APP == Encrypted the message, got 856 bytes
== APP == Decrypted the message, got 24 bytes
== APP == The secret is "passw0rd"
== APP == Wrote encrypted data to encrypted.out
== APP == Wrote decrypted data to decrypted.out.jpg
```
11 changes: 11 additions & 0 deletions examples/crypto/components/local-storage.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
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
Binary file added examples/crypto/desert.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
162 changes: 162 additions & 0 deletions examples/crypto/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
package main

import (
"bytes"
"context"
"fmt"
"io"
"log"
"os"
"strings"

dapr "github.com/dapr/go-sdk/client"
)

const (
// Name of the crypto component to use
CryptoComponentName = "localstorage"
// Name of the RSA private key to use
RSAKeyName = "rsa-private-key.pem"
// Name of the symmetric (AES) key to use
SymmetricKeyName = "symmetric-key-256"
)

func main() {
// Create a new Dapr SDK client
client, err := dapr.NewClient()
if err != nil {
log.Fatalf("Failed to initialize the Dapr client: %v", err)
}
defer client.Close()

// 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)
}

func encryptDecryptString(client dapr.Client) {
const message = `The secret is "passw0rd"`

// 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",
},
)
if err != nil {
log.Fatalf("Failed to encrypt the message: %v", err)
}

// The method returns a readable stream, which we read in full in memory
encBytes, err := io.ReadAll(encStream)
if err != nil {
log.Fatalf("Failed to read the stream for the encrypted message: %v", err)
}

fmt.Printf("Encrypted the message, got %d bytes\n", len(encBytes))

// 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,
},
)
if err != nil {
log.Fatalf("Failed to decrypt the message: %v", err)
}

// The method returns a readable stream, which we read in full in memory
decBytes, err := io.ReadAll(decStream)
if err != nil {
log.Fatalf("Failed to read the stream for the decrypted message: %v", err)
}

// Print the message on the console
fmt.Printf("Decrypted the message, got %d bytes\n", len(decBytes))
fmt.Println(string(decBytes))
}

func encryptDecryptFile(client dapr.Client) {
const fileName = "desert.jpg"

// Get a readable stream to the input file
plaintextF, err := os.Open(fileName)
if err != nil {
log.Fatalf("Failed to open plaintext file: %v", err)
}
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",
},
)
if err != nil {
log.Fatalf("Failed to encrypt the file: %v", err)
}

// Write the encrypted data to a file "encrypted.out"
encryptedF, err := os.Create("encrypted.out")
if err != nil {
log.Fatalf("Failed to open destination file: %v", err)
}
_, err = io.Copy(encryptedF, encStream)
if err != nil {
log.Fatalf("Failed to write encrypted stream to file: %v", err)
}
encryptedF.Close()

fmt.Println("Wrote encrypted data to encrypted.out")

// Now, decrypt the encrypted data
// First, open the file "encrypted.out" again, this time for reading
encryptedF, err = os.Open("encrypted.out")
if err != nil {
log.Fatalf("Failed to open encrypted file: %v", err)
}
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,
},
)
if err != nil {
log.Fatalf("Failed to decrypt the file: %v", err)
}

// Write the decrypted data to a file "decrypted.out.jpg"
decryptedF, err := os.Create("decrypted.out.jpg")
if err != nil {
log.Fatalf("Failed to open destination file: %v", err)
}
_, err = io.Copy(decryptedF, decStream)
if err != nil {
log.Fatalf("Failed to write decrypted stream to file: %v", err)
}
decryptedF.Close()

fmt.Println("Wrote decrypted data to decrypted.out.jpg")
}
Loading