Skip to content

Commit d1b67de

Browse files
committed
Add crypto exaple
Signed-off-by: sirivarma <[email protected]>
1 parent a4b9e26 commit d1b67de

File tree

7 files changed

+574
-14
lines changed

7 files changed

+574
-14
lines changed

.github/workflows/validate.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,4 +185,9 @@ jobs:
185185
working-directory: ./examples
186186
run: |
187187
mm.py ./src/main/java/io/dapr/examples/pubsub/stream/README.md
188+
- name: Validate crypto example
189+
working-directory: ./examples
190+
run: |
191+
mm.py ./src/main/java/io/dapr/examples/crypto/README.md
192+
188193
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
apiVersion: dapr.io/v1alpha1
2+
kind: Component
3+
metadata:
4+
name: localstoragecrypto
5+
spec:
6+
type: crypto.dapr.localstorage
7+
version: v1
8+
metadata:
9+
# Path to the directory containing keys (PEM files)
10+
# On Linux/Mac: ~/.dapr/keys
11+
# On Windows: %USERPROFILE%\.dapr\keys
12+
- name: path
13+
value: "${HOME}/.dapr/keys"
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
/*
2+
* Copyright 2021 The Dapr Authors
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
* Unless required by applicable law or agreed to in writing, software
8+
* distributed under the License is distributed on an "AS IS" BASIS,
9+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
* See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
13+
14+
package io.dapr.examples.crypto;
15+
16+
import io.dapr.client.DaprClientBuilder;
17+
import io.dapr.client.DaprPreviewClient;
18+
import io.dapr.client.domain.DecryptRequestAlpha1;
19+
import io.dapr.client.domain.EncryptRequestAlpha1;
20+
import io.dapr.config.Properties;
21+
import io.dapr.config.Property;
22+
import reactor.core.publisher.Flux;
23+
24+
import java.nio.charset.StandardCharsets;
25+
import java.util.Map;
26+
27+
/**
28+
* CryptoExample demonstrates using the Dapr Cryptography building block
29+
* to encrypt and decrypt data using a cryptography component.
30+
*
31+
* <p>This example shows:
32+
* <ul>
33+
* <li>Encrypting plaintext data with a specified key and algorithm</li>
34+
* <li>Decrypting ciphertext data back to plaintext</li>
35+
* <li>Working with streaming data for large payloads</li>
36+
* </ul>
37+
*
38+
* <p>Prerequisites:
39+
* <ul>
40+
* <li>Dapr installed and initialized</li>
41+
* <li>A cryptography component configured (e.g., local storage crypto)</li>
42+
* <li>A key pair available for the crypto component</li>
43+
* </ul>
44+
*/
45+
public class CryptoExample {
46+
47+
// The crypto component name as defined in the component YAML file
48+
private static final String CRYPTO_COMPONENT_NAME = "localstoragecrypto";
49+
50+
// The key name to use for encryption/decryption
51+
private static final String KEY_NAME = "mykey";
52+
53+
// The key wrap algorithm - RSA-OAEP-256 for RSA keys
54+
private static final String KEY_WRAP_ALGORITHM = "RSA-OAEP-256";
55+
56+
/**
57+
* The main method demonstrating encryption and decryption with Dapr.
58+
*
59+
* @param args Command line arguments (unused).
60+
*/
61+
public static void main(String[] args) {
62+
Map<Property<?>, String> overrides = Map.of(
63+
Properties.HTTP_PORT, "3500",
64+
Properties.GRPC_PORT, "50001"
65+
);
66+
67+
try (DaprPreviewClient client = new DaprClientBuilder().withPropertyOverrides(overrides).buildPreviewClient()) {
68+
69+
// Original message to encrypt
70+
String originalMessage = "Hello, Dapr Cryptography! This is a secret message.";
71+
byte[] plainText = originalMessage.getBytes(StandardCharsets.UTF_8);
72+
73+
System.out.println("=== Dapr Cryptography Example ===");
74+
System.out.println("Original message: " + originalMessage);
75+
System.out.println();
76+
77+
// Encrypt the message
78+
System.out.println("Encrypting message...");
79+
EncryptRequestAlpha1 encryptRequest = new EncryptRequestAlpha1(
80+
CRYPTO_COMPONENT_NAME,
81+
Flux.just(plainText),
82+
KEY_NAME,
83+
KEY_WRAP_ALGORITHM
84+
);
85+
86+
// Collect encrypted data from the stream
87+
byte[] encryptedData = client.encrypt(encryptRequest)
88+
.collectList()
89+
.map(chunks -> {
90+
int totalSize = chunks.stream().mapToInt(chunk -> chunk.length).sum();
91+
byte[] result = new byte[totalSize];
92+
int pos = 0;
93+
for (byte[] chunk : chunks) {
94+
System.arraycopy(chunk, 0, result, pos, chunk.length);
95+
pos += chunk.length;
96+
}
97+
return result;
98+
})
99+
.block();
100+
101+
System.out.println("Encryption successful!");
102+
System.out.println("Encrypted data length: " + encryptedData.length + " bytes");
103+
System.out.println();
104+
105+
// Decrypt the message
106+
System.out.println("Decrypting message...");
107+
DecryptRequestAlpha1 decryptRequest = new DecryptRequestAlpha1(
108+
CRYPTO_COMPONENT_NAME,
109+
Flux.just(encryptedData)
110+
);
111+
112+
// Collect decrypted data from the stream
113+
byte[] decryptedData = client.decrypt(decryptRequest)
114+
.collectList()
115+
.map(chunks -> {
116+
int totalSize = chunks.stream().mapToInt(chunk -> chunk.length).sum();
117+
byte[] result = new byte[totalSize];
118+
int pos = 0;
119+
for (byte[] chunk : chunks) {
120+
System.arraycopy(chunk, 0, result, pos, chunk.length);
121+
pos += chunk.length;
122+
}
123+
return result;
124+
})
125+
.block();
126+
127+
String decryptedMessage = new String(decryptedData, StandardCharsets.UTF_8);
128+
System.out.println("Decryption successful!");
129+
System.out.println("Decrypted message: " + decryptedMessage);
130+
System.out.println();
131+
132+
// Verify the message matches
133+
if (originalMessage.equals(decryptedMessage)) {
134+
System.out.println("✓ Success! The decrypted message matches the original.");
135+
} else {
136+
System.out.println("✗ Error! The decrypted message does not match the original.");
137+
}
138+
139+
} catch (Exception e) {
140+
System.err.println("Error during crypto operations: " + e.getMessage());
141+
throw new RuntimeException(e);
142+
}
143+
}
144+
}
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
## Dapr Cryptography API Examples
2+
3+
This example provides the different capabilities provided by Dapr Java SDK for Cryptography. For further information about Cryptography APIs please refer to [this link](https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/)
4+
5+
### Using the Cryptography API
6+
7+
The Java SDK exposes several methods for this -
8+
* `client.encrypt(...)` for encrypting data using a cryptography component.
9+
* `client.decrypt(...)` for decrypting data using a cryptography component.
10+
11+
## Pre-requisites
12+
13+
* [Dapr CLI](https://docs.dapr.io/getting-started/install-dapr-cli/).
14+
* Java JDK 11 (or greater):
15+
* [Microsoft JDK 11](https://docs.microsoft.com/en-us/java/openjdk/download#openjdk-11)
16+
* [Oracle JDK 11](https://www.oracle.com/technetwork/java/javase/downloads/index.html#JDK11)
17+
* [OpenJDK 11](https://jdk.java.net/11/)
18+
* [Apache Maven](https://maven.apache.org/install.html) version 3.x.
19+
20+
### Checking out the code
21+
22+
Clone this repository:
23+
24+
```sh
25+
git clone https://github.com/dapr/java-sdk.git
26+
cd java-sdk
27+
```
28+
29+
Then build the Maven project:
30+
31+
```sh
32+
# make sure you are in the `java-sdk` directory.
33+
mvn install
34+
```
35+
36+
Then get into the examples directory:
37+
38+
```sh
39+
cd examples
40+
```
41+
42+
### Initialize Dapr
43+
44+
Run `dapr init` to initialize Dapr in Self-Hosted Mode if it's not already initialized.
45+
46+
### Setting Up the Cryptography Component
47+
48+
Before running the examples, you need to set up a cryptography component. This example uses the local storage crypto component.
49+
50+
1. Create a directory for your keys:
51+
52+
```bash
53+
mkdir -p ~/.dapr/keys
54+
```
55+
56+
2. Generate an RSA key pair (you can use OpenSSL):
57+
58+
```bash
59+
# Generate a 4096-bit RSA private key
60+
openssl genrsa -out ~/.dapr/keys/mykey 4096
61+
62+
# Extract the public key
63+
openssl rsa -in ~/.dapr/keys/mykey -pubout -out ~/.dapr/keys/mykey.pub
64+
```
65+
66+
The component configuration file is already provided in `./components/crypto/localstorage.yaml`.
67+
68+
### Running the Example
69+
70+
This example uses the Java SDK Dapr client to **Encrypt and Decrypt** data.
71+
72+
#### Example 1: Basic Crypto Example
73+
74+
`CryptoExample.java` demonstrates basic encryption and decryption of a simple message.
75+
76+
```java
77+
public class CryptoExample {
78+
private static final String CRYPTO_COMPONENT_NAME = "localstoragecrypto";
79+
private static final String KEY_NAME = "mykey";
80+
private static final String KEY_WRAP_ALGORITHM = "RSA-OAEP-256";
81+
82+
public static void main(String[] args) {
83+
try (DaprPreviewClient client = new DaprClientBuilder().buildPreviewClient()) {
84+
85+
String originalMessage = "Hello, Dapr Cryptography!";
86+
byte[] plainText = originalMessage.getBytes(StandardCharsets.UTF_8);
87+
88+
// Encrypt the message
89+
EncryptRequestAlpha1 encryptRequest = new EncryptRequestAlpha1(
90+
CRYPTO_COMPONENT_NAME,
91+
Flux.just(plainText),
92+
KEY_NAME,
93+
KEY_WRAP_ALGORITHM
94+
);
95+
96+
byte[] encryptedData = client.encrypt(encryptRequest)
97+
.collectList()
98+
.map(chunks -> /* combine chunks */)
99+
.block();
100+
101+
// Decrypt the message
102+
DecryptRequestAlpha1 decryptRequest = new DecryptRequestAlpha1(
103+
CRYPTO_COMPONENT_NAME,
104+
Flux.just(encryptedData)
105+
);
106+
107+
byte[] decryptedData = client.decrypt(decryptRequest)
108+
.collectList()
109+
.map(chunks -> /* combine chunks */)
110+
.block();
111+
}
112+
}
113+
}
114+
```
115+
116+
Use the following command to run this example:
117+
118+
<!-- STEP
119+
name: Run Crypto Example
120+
expected_stdout_lines:
121+
- "== APP == ✓ Success! The decrypted message matches the original."
122+
background: true
123+
output_match_mode: substring
124+
sleep: 10
125+
-->
126+
127+
```bash
128+
dapr run --resources-path ./components/crypto --app-id crypto-app --dapr-http-port 3500 --dapr-grpc-port 50001 -- java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.crypto.CryptoExample
129+
```
130+
131+
<!-- END_STEP -->
132+
133+
#### Example 2: Streaming Crypto Example
134+
135+
`StreamingCryptoExample.java` demonstrates advanced scenarios including:
136+
- Multi-chunk data encryption
137+
- Large data encryption (100KB+)
138+
- Custom encryption ciphers
139+
140+
```bash
141+
dapr run --resources-path ./components/crypto --app-id crypto-app --dapr-http-port 3500 --dapr-grpc-port 50001 -- java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.crypto.StreamingCryptoExample
142+
```
143+
144+
### Sample Output
145+
146+
```
147+
=== Dapr Cryptography Example ===
148+
Original message: Hello, Dapr Cryptography! This is a secret message.
149+
150+
Encrypting message...
151+
Encryption successful!
152+
Encrypted data length: 512 bytes
153+
154+
Decrypting message...
155+
Decryption successful!
156+
Decrypted message: Hello, Dapr Cryptography! This is a secret message.
157+
158+
✓ Success! The decrypted message matches the original.
159+
```
160+
161+
### Supported Key Wrap Algorithms
162+
163+
The following key wrap algorithms are supported:
164+
- `A256KW` (alias: `AES`) - AES key wrap
165+
- `A128CBC`, `A192CBC`, `A256CBC` - AES CBC modes
166+
- `RSA-OAEP-256` (alias: `RSA`) - RSA OAEP with SHA-256
167+
168+
### Supported Data Encryption Ciphers
169+
170+
Optional data encryption ciphers:
171+
- `aes-gcm` (default) - AES in GCM mode
172+
- `chacha20-poly1305` - ChaCha20-Poly1305 cipher
173+
174+
### Cleanup
175+
176+
To stop the app, run (or press CTRL+C):
177+
178+
<!-- STEP
179+
name: Cleanup
180+
-->
181+
182+
```bash
183+
dapr stop --app-id crypto-app
184+
```
185+
186+
<!-- END_STEP -->

0 commit comments

Comments
 (0)