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

Cherry picking 42a99c2 into release branch #1135

Merged
merged 2 commits into from
Jan 22, 2025
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
74 changes: 74 additions & 0 deletions cryptography/python/sdk/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# 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:
alicejgibbons marked this conversation as resolved.
Show resolved Hide resolved

- Encrypt and then decrypt a short string, reading the result in-memory
- Encrypt and then decrypt a large file, storing the encrypted and decrypted data to files

Visit the documentation to learn more about the [Cryptography building block](https://v1-11.docs.dapr.io/developing-applications/building-blocks/cryptography/) in Dapr.
alicejgibbons marked this conversation as resolved.
Show resolved Hide resolved

> **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:

- Python application `crypto-quickstart`

### Run Python service with Dapr

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

1. Navigate into the folder with the source code:

<!-- STEP
name: Navigate into folder
expected_stdout_lines:
expected_stderr_lines:
-->

```bash
cd ./crypto-quickstart
pip3 install -r requirements.txt
```

<!-- 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 Python service app with Dapr:

<!-- STEP
name: Run order-processor service
working_dir: crypto-quickstart
expected_stdout_lines:
- '== APP == Encrypted the message, got 856 bytes'
- '== APP == Decrypted the message, got 24 bytes'
alicejgibbons marked this conversation as resolved.
Show resolved Hide resolved
- '== 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-quickstart --resources-path ../../../components/ -- python3 app.py
```

<!-- END_STEP -->
6 changes: 6 additions & 0 deletions cryptography/python/sdk/crypto-quickstart/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Output files
encrypted.out
decrypted.out.jpg

# Generated keys
keys/
95 changes: 95 additions & 0 deletions cryptography/python/sdk/crypto-quickstart/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
from dapr.clients import DaprClient
from dapr.clients.grpc._crypto import EncryptOptions, DecryptOptions

# Name of the crypto component to use
CRYPTO_COMPONENT_NAME = 'localstorage'
# Name of the RSA private key to use
RSA_KEY_NAME = 'rsa-private-key.pem'
# Name of the symmetric (AES) key to use
SYMMETRIC_KEY_NAME = 'symmetric-key-256'


def main():
print('Running gRPC client synchronous API')

with DaprClient() as dapr:
# Step 1: encrypt a string using the RSA key, then decrypt it and show the output in the terminal
print('Running encrypt/decrypt operation on string')
encrypt_decrypt_string(dapr)

# Step 2: encrypt a large file and then decrypt it, using the AES key
print('Running encrypt/decrypt operation on file')
encrypt_decrypt_file(dapr)


def encrypt_decrypt_string(dapr: DaprClient):
message = 'The secret is "passw0rd"'

# Encrypt the message
resp = dapr.encrypt(
data=message.encode(),
options=EncryptOptions(
component_name=CRYPTO_COMPONENT_NAME,
key_name=RSA_KEY_NAME,
key_wrap_algorithm='RSA',
),
)

# The method returns a readable stream, which we read in full in memory
encrypt_bytes = resp.read()
print(f'Encrypted the message, got {len(encrypt_bytes)} bytes')

# Decrypt the encrypted data
resp = dapr.decrypt(
data=encrypt_bytes,
options=DecryptOptions(
component_name=CRYPTO_COMPONENT_NAME,
key_name=RSA_KEY_NAME,
),
)

# The method returns a readable stream, which we read in full in memory
decrypt_bytes = resp.read()
print(f'Decrypted the message, got {len(decrypt_bytes)} bytes')

print(decrypt_bytes.decode())
assert message == decrypt_bytes.decode()


def encrypt_decrypt_file(dapr: DaprClient):
file_name = 'desert.jpg'

# Encrypt the file
with open(file_name, 'r+b') as target_file:
encrypt_stream = dapr.encrypt(
data=target_file.read(),
options=EncryptOptions(
component_name=CRYPTO_COMPONENT_NAME,
key_name=SYMMETRIC_KEY_NAME,
key_wrap_algorithm='AES',
),
)

# Write the encrypted data to a file "encrypted.out"
with open('encrypted.out', 'w+b') as encrypted_file:
encrypted_file.write(encrypt_stream.read())
print('Wrote encrypted data to encrypted.out')

# Decrypt the encrypted data
with open('encrypted.out', 'r+b') as encrypted_file:
decrypt_stream = dapr.decrypt(
data=encrypted_file.read(),
options=DecryptOptions(
component_name=CRYPTO_COMPONENT_NAME,
key_name=SYMMETRIC_KEY_NAME,
),
)

# Write the decrypted data to a file "decrypted.out.jpg"
with open('decrypted.out.jpg', 'w+b') as decrypted_file:
decrypted_file.write(decrypt_stream.read())
print('Wrote decrypted data to decrypted.out.jpg')


if __name__ == '__main__':
main()
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions cryptography/python/sdk/crypto-quickstart/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dapr>=1.13.0a,<1.14.0
typing-extensions
9 changes: 9 additions & 0 deletions cryptography/python/sdk/makefile
Original file line number Diff line number Diff line change
@@ -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
Loading