diff --git a/README.md b/README.md
index bc4ce73..5d60005 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,12 @@
# PyTorch/CSPRNG
-torchcsprng is a [PyTorch C++/CUDA extension](https://pytorch.org/tutorials/advanced/cpp_extension.html) that provides [cryptographically secure pseudorandom number generators](https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator) for PyTorch.
-
[![CircleCI](https://circleci.com/gh/pytorch/csprng.svg?style=shield&circle-token=64701692dd7f13f31019612289f0200fdb661dc2)](https://circleci.com/gh/pytorch/csprng)
+torchcsprng is a [PyTorch C++/CUDA extension](https://pytorch.org/tutorials/advanced/cpp_extension.html) that provides:
+
+- [AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) 128-bit encryption/decryption in two modes: [ECB](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_codebook_(ECB)) and [CTR](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_(CTR)) [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/pytorch/csprng/blob/master/examples/encrypt_decrypt.ipynb)
+- [cryptographically secure pseudorandom number generators](https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator) for PyTorch. [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/pytorch/csprng/blob/master/examples/csprng.ipynb)
+
## Design
torchcsprng generates a random 128-bit key on CPU using one of its generators and runs
@@ -22,6 +25,24 @@ Advantages:
## Features
+torchcsprng 0.2.0 exposes new API for tensor encryption/decryption. Tensor encryption/decryption API is dtype agnostic, so a tensor of any dtype can be encrypted and the result can be stored to a tensor of any dtype. An encryption key also can be a tensor of any dtype. Currently torchcsprng supports [AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) cipher with 128-bit key in two modes: [ECB](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_codebook_(ECB)) and [CTR](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_(CTR)).
+
+* `torchcsprng.encrypt(input: Tensor, output: Tensor, key: Tensor, cipher: string, mode: string)`
+
+> - `input` tensor can be any CPU or CUDA tensor of any dtype and size in bytes(zero-padding is used to make its size in bytes divisible by block size in bytes)
+> - `output` tensor can have any dtype and the same device as `input` tensor and the size in bytes rounded up to the block size in bytes(16 bytes for AES 128)
+> - `key` tensor can have any dtype and the same device as `input` tensor and size in bytes equal to 16 for AES 128
+> - `cipher` currently can be only one supported value `"aes128"`
+> - `mode` currently can be either [`"ecb"`](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_codebook_(ECB)) or [`"ctr"`](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_(CTR))
+
+* `torchcsprng.decrypt(input: Tensor, output: Tensor, key: Tensor, cipher: string, mode: string)`
+
+> - `input` tensor can be any CPU or CUDA tensor of any dtype with size in bytes divisible by the block size in bytes(16 bytes for AES 128)
+> - `output` tensor can have any dtype but the same device as `input` tensor and the same size in bytes as `input` tensor
+> - `key` tensor can have any dtype and the same device as `input` tensor and size in bytes equal to 16 for AES 128
+> - `cipher` currently can be only one supported value `"aes128"`
+> - `mode` currently can be either [`"ecb"`](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_codebook_(ECB)) or [`"ctr"`](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_(CTR))
+
torchcsprng exposes two methods to create crypto-secure and non-crypto-secure PRNGs:
| Method to create PRNG | Is crypto-secure? | Has seed? | Underlying implementation |
@@ -48,52 +69,58 @@ The following list of methods supports all forementioned PRNGs:
## Installation
-CSPRNG works with Python 3.6/3.7/3.8 on the following operating systems and can be used with PyTorch tensors on the following devices:
+CSPRNG works with Python 3.6-3.9 on the following operating systems and can be used with PyTorch tensors on the following devices:
| Tensor Device Type | Linux | macOS | MS Window |
|--------------------|-----------|---------------|----------------|
| CPU | Supported | Supported | Supported |
-| CUDA | Supported | Not Supported | Coming |
+| CUDA | Supported | Not Supported | Supported since 0.2.0 |
+
+The following is the corresponding CSPRNG versions and supported Python versions.
+
+| PyTorch | CSPRNG | Python | CUDA |
+|---------|--------|----------|------------------|
+| 1.8.0 | 0.2.0 | 3.7-3.9 | 10.1, 10.2, 11.1 |
+| 1.7.1 | 0.1.4 | 3.6-3.8 | 9.2, 10.1, 10.2 |
+| 1.7.0 | 0.1.3 | 3.6-3.8 | 9.2, 10.1, 10.2 |
+| 1.6.0 | 0.1.2 | 3.6-3.8 | 9.2, 10.1, 10.2 |
+
### Binary Installation
Anaconda:
-| OS | CUDA | |
-|---------|-----------------------------------------------|----------------------------------------------|
-| Linux | 9.2
10.1
10.2
None | conda install torchcsprng cudatoolkit=9.2 -c pytorch
conda install torchcsprng cudatoolkit=10.1 -c pytorch
conda install torchcsprng cudatoolkit=10.2 -c pytorch
conda install torchcsprng cpuonly -c pytorch |
-| macOS | None | conda install torchcsprng cpuonly -c pytorch |
-| Windows | None | conda install torchcsprng cpuonly -c pytorch |
+| OS | CUDA | |
+|---------------|------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| Linux/Windows | 10.1
10.2
11.1
None | conda install torchcsprng cudatoolkit=10.1 -c pytorch -c conda-forge
conda install torchcsprng cudatoolkit=10.2 -c pytorch -c conda-forge
conda install torchcsprng cudatoolkit=11.1 -c pytorch -c conda-forge
conda install torchcsprng cpuonly -c pytorch -c conda-forge |
+| macOS | None | conda install torchcsprng -c pytorch |
pip:
-| OS | CUDA | |
-|---------|-----------------------------------------------|-------------------------------------------------------------------------------------|
-| Linux | 9.2
10.1
10.2
None | pip install torchcsprng==0.1.2+cu92 torch==1.6.0+cu92 -f https://download.pytorch.org/whl/torch_stable.html
pip install torchcsprng==0.1.2+cu101 torch==1.6.0+cu101 -f https://download.pytorch.org/whl/torch_stable.html
pip install torchcsprng torch
pip install torchcsprng==0.1.2+cpu torch==1.6.0+cpu -f https://download.pytorch.org/whl/torch_stable.html |
-| macOS | None | pip install torchcsprng torch |
-| Windows | None | pip install torchcsprng torch -f https://download.pytorch.org/whl/torch_stable.html |
+| OS | CUDA | |
+|---------------|------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| Linux/Windows | 10.1
10.2
11.1
None | pip install torchcsprng==0.2.0+cu101 torch==1.8.0+cu101 -f https://download.pytorch.org/whl/cu101/torch_stable.html
pip install torchcsprng==0.2.0 torch==1.8.0 -f https://download.pytorch.org/whl/cu102/torch_stable.html
pip install torchcsprng==0.2.0+cu111 torch==1.8.0+cu111 -f https://download.pytorch.org/whl/cu111/torch_stable.html
pip install torchcsprng==0.2.0+cpu torch==1.8.0+cpu -f https://download.pytorch.org/whl/cpu/torch_stable.html |
+| macOS | None | pip install torchcsprng torch |
### Nightly builds:
Anaconda:
-| OS | CUDA | |
-|---------|-----------------------------------------------|------------------------------------------------------|
-| Linux | 9.2
10.1
10.2
None | conda install torchcsprng cudatoolkit=9.2 -c pytorch-nightly
conda install torchcsprng cudatoolkit=10.1 -c pytorch-nightly
conda install torchcsprng cudatoolkit=10.2 -c pytorch-nightly
conda install torchcsprng cpuonly -c pytorch-nightly |
-| macOS | None | conda install torchcsprng cpuonly -c pytorch-nightly |
-| Windows | None | conda install torchcsprng cpuonly -c pytorch-nightly |
+| OS | CUDA | |
+|---------------|------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| Linux/Windows | 10.1
10.2
11.1
None | conda install torchcsprng cudatoolkit=10.1 -c pytorch-nightly -c conda-forge
conda install torchcsprng cudatoolkit=10.2 -c pytorch-nightly -c conda-forge
conda install torchcsprng cudatoolkit=11.1 -c pytorch-nightly -c conda-forge
conda install torchcsprng cpuonly -c pytorch-nightly -c conda-forge |
+| macOS | None | conda install torchcsprng -c pytorch-nightly |
pip:
-| OS | CUDA | |
-|---------|-----------------------------------------------|----------------------------------------------------------------------------------------------------|
-| Linux | 9.2
10.1
10.2
None | pip install --pre torchcsprng -f https://download.pytorch.org/whl/nightly/cu92/torch_nightly.html
pip install --pre torchcsprng -f https://download.pytorch.org/whl/nightly/cu101/torch_nightly.html
pip install --pre torchcsprng -f https://download.pytorch.org/whl/nightly/cu102/torch_nightly.html
pip install --pre torchcsprng -f https://download.pytorch.org/whl/nightly/cpu/torch_nightly.html |
-| macOS | None | pip install --pre torchcsprng -f https://download.pytorch.org/whl/nightly/cpu/torch_nightly.html |
-| Windows | None | pip install --pre torchcsprng -f https://download.pytorch.org/whl/nightly/cpu/torch_nightly.html |
+| OS | CUDA | |
+|---------------|------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| Linux/Windows | 10.1
10.2
11.1
None | pip install --pre torchcsprng -f https://download.pytorch.org/whl/nightly/cu101/torch_nightly.html
pip install --pre torchcsprng -f https://download.pytorch.org/whl/nightly/cu102/torch_nightly.html
pip install --pre torchcsprng -f https://download.pytorch.org/whl/nightly/cu111/torch_nightly.html
pip install --pre torchcsprng -f https://download.pytorch.org/whl/nightly/cpu/torch_nightly.html |
+| macOS | None | pip install --pre torchcsprng -f https://download.pytorch.org/whl/nightly/cpu/torch_nightly.html |
### From Source
-torchcsprng is a Python C++/CUDA extension that depends on PyTorch. In order to build CSPRNG from source it is required to have Python(>=3.6) with PyTorch(>=1.6.0) installed and C++ compiler(gcc/clang for Linux, XCode for macOS, Visual Studio for MS Windows).
+torchcsprng is a Python C++/CUDA extension that depends on PyTorch. In order to build CSPRNG from source it is required to have Python(>=3.7) with PyTorch(>=1.8.0) installed and C++ compiler(gcc/clang for Linux, XCode for macOS, Visual Studio for MS Windows).
To build torchcsprng you can run the following:
```console
python setup.py install
diff --git a/examples/csprng.ipynb b/examples/csprng.ipynb
new file mode 100644
index 0000000..e0e719c
--- /dev/null
+++ b/examples/csprng.ipynb
@@ -0,0 +1,226 @@
+{
+ "nbformat": 4,
+ "nbformat_minor": 0,
+ "metadata": {
+ "colab": {
+ "name": "csprng.ipynb",
+ "provenance": [],
+ "collapsed_sections": []
+ },
+ "kernelspec": {
+ "name": "python3",
+ "display_name": "Python 3"
+ }
+ },
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "Lpno_zUJT8ms"
+ },
+ "source": [
+ "# Cryptographically secure pseudorandom number generators for PyTorch\n",
+ "\n",
+ "The torchcsprng API is available in `torchcsprng` module:\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "db4YYky-PDI_"
+ },
+ "source": [
+ "!pip install torchcsprng==0.2.0 torch==1.8.0 -f https://download.pytorch.org/whl/cu102/torch_stable.html"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "O1s_j8CPPHSn"
+ },
+ "source": [
+ "import torch\n",
+ "import torchcsprng as csprng"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "o1Kz25IoS9m-"
+ },
+ "source": [
+ "device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "HLlLxkDIUWCG"
+ },
+ "source": [
+ "Create crypto-secure PRNG from /dev/urandom:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "yyyYlq5kUQss"
+ },
+ "source": [
+ "urandom_gen = csprng.create_random_device_generator('/dev/urandom')"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "xbUCnJfkUdUI"
+ },
+ "source": [
+ "Create empty boolean tensor on the `device` and initialize it with random values from `urandom_gen`:\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "zmj_VlIzUYIO"
+ },
+ "source": [
+ "torch.empty(10, dtype=torch.bool, device=device).random_(generator=urandom_gen)"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "ycODsYhtUud9"
+ },
+ "source": [
+ "Create empty int16 tensor on the `device` and initialize it with random values in range [0, 100) from `urandom_gen`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "uel-jbW9UlZH"
+ },
+ "source": [
+ "torch.empty(10, dtype=torch.int16, device=device).random_(100, generator=urandom_gen)"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "1jXW1FEmVMW_"
+ },
+ "source": [
+ "Create non-crypto-secure MT19937 PRNG:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "sL-cwFGfVOrp"
+ },
+ "source": [
+ "mt19937_gen = csprng.create_mt19937_generator()\n",
+ "torch.empty(10, dtype=torch.int64, device=device).random_(torch.iinfo(torch.int64).min, to=None, generator=mt19937_gen)"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "KW96wT4UVXBm"
+ },
+ "source": [
+ "Create crypto-secure PRNG from default random device:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "tjwbuE6FVRgm"
+ },
+ "source": [
+ "default_device_gen = csprng.create_random_device_generator()\n",
+ "torch.randn(10, device=device, generator=default_device_gen)"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "qYgdkZAYVfZT"
+ },
+ "source": [
+ "Create non-crypto-secure MT19937 PRNG with seed:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "xjOsYOxxVbzg"
+ },
+ "source": [
+ "mt19937_gen = csprng.create_mt19937_generator(42)\n",
+ "first = torch.empty(10, device=device).geometric_(p=0.2, generator=mt19937_gen)"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "cV77v7tHVlRd"
+ },
+ "source": [
+ "Recreate MT19937 PRNG with the same seed:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "i0O2lC0hVjAg"
+ },
+ "source": [
+ "mt19937_gen = csprng.create_mt19937_generator(42)\n",
+ "second = torch.empty(10, device=device).geometric_(p=0.2, generator=mt19937_gen)"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "OcgSK0mejcef"
+ },
+ "source": [
+ "Check that `first` equals to `second`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "vMx1BRO3jh7L"
+ },
+ "source": [
+ "assert (first == second).all()"
+ ],
+ "execution_count": null,
+ "outputs": []
+ }
+ ]
+}
\ No newline at end of file
diff --git a/examples/encrypt_decrypt.ipynb b/examples/encrypt_decrypt.ipynb
new file mode 100644
index 0000000..54a5a66
--- /dev/null
+++ b/examples/encrypt_decrypt.ipynb
@@ -0,0 +1,307 @@
+{
+ "nbformat": 4,
+ "nbformat_minor": 0,
+ "metadata": {
+ "colab": {
+ "name": "encrypt_decrypt.ipynb",
+ "provenance": [],
+ "collapsed_sections": []
+ },
+ "kernelspec": {
+ "name": "python3",
+ "display_name": "Python 3"
+ }
+ },
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "4JG-7IJgz_dK"
+ },
+ "source": [
+ "# PyTorch/CSPRNG encrypt/decrypt examples"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "H8TZemj30JvQ"
+ },
+ "source": [
+ "torchcsprng 0.2.0 exposes new API for tensor encryption/decryption. Tensor encryption/decryption API is dtype agnostic, so a tensor of any dtype can be encrypted and the result can be stored to a tensor of any dtype. An encryption key also can be a tensor of any dtype. Currently torchcsprng supports AES cipher with 128-bit key in two modes: ECB and CTR."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "jC1O-C25vI0W"
+ },
+ "source": [
+ "!pip install torchcsprng==0.2.0 torch==1.8.0 -f https://download.pytorch.org/whl/cu102/torch_stable.html"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "su2RWWdOrWFU"
+ },
+ "source": [
+ "import torch\n",
+ "import torchcsprng as csprng"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "NHTOLPZ_3254"
+ },
+ "source": [
+ "device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "17L0sgmy0R6o"
+ },
+ "source": [
+ "torchcsprng implementation of AES with 128 bit key requires to have a key tensor of 16 bytes but of any dtype"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "rw7WYZ-50To9"
+ },
+ "source": [
+ "key = torch.empty(16, dtype=torch.uint8, device=device).random_(0, 256)\n",
+ "key"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "RRfvyfHM4MY1"
+ },
+ "source": [
+ "Alternatively it can be a tensor of 8 elements of `torch.int16` or even 4 elements of `torch.float32`"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "rCy01t1-0dtO"
+ },
+ "source": [
+ "The size of input tensor is 42 * (32/8) = 168 bytes. AES 128 operates with 16-bytes blocks, so zero-padding of 8 bytes will be used to form 176 bytes(eleven 16-bytes blocks)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "LcuVmhyU0WTn"
+ },
+ "source": [
+ "initial = torch.empty(42, dtype=torch.float32, device=device).normal_(-24.0, 42.0)\n",
+ "initial"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "rPNq2u4e3tlJ"
+ },
+ "source": [
+ "torchcsprng requires output tensor to be of the same size in bytes as input tensor rounded up to 16 bytes(AES 128 block size), so if `torch.int64` is dtype of the destination tensor size must be 176 / (64/8) = 22"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "RAJya9GT0gb4"
+ },
+ "source": [
+ "encrypted = torch.empty(22, dtype=torch.int64, device=device)"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "-DCI4QOh4oGX"
+ },
+ "source": [
+ "Call `torchcsprng.encrypt` to encrypt `initial` tensor in [ECB](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_codebook_(ECB)) mode with 128-bit `key` tensor and store the result to `encrypted` tensor."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "TK4OjPRq4lsJ"
+ },
+ "source": [
+ "csprng.encrypt(initial, encrypted, key, \"aes128\", \"ecb\")"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "yXUAwFHh5PSy"
+ },
+ "source": [
+ "Create an output tensor"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "4LtJ-kD446DJ"
+ },
+ "source": [
+ "decrypted = torch.empty_like(initial)"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "8VcF04mf6Rn5"
+ },
+ "source": [
+ "Call `torchcsprng.decrypt` to decrypt `encrypted` tensor in ECB mode with 128-bit `key` tensor and store the result to `decrypted` tensor."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "kojXCFGK5v6l"
+ },
+ "source": [
+ "csprng.decrypt(encrypted, decrypted, key, \"aes128\", \"ecb\")"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "9dEBSPD6EFSu"
+ },
+ "source": [
+ "Let's check that `decrypted` equals to `initial`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "yOc1ftnM5yyj"
+ },
+ "source": [
+ "assert (decrypted == initial).all()"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "cQWyteLlE4mQ"
+ },
+ "source": [
+ "Another example is to use [CTR](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_(CTR)) mode with 128-bit `key` tensor of 4 elements of dtype `dtype=torch.float32`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "ZFInqYawD7ks"
+ },
+ "source": [
+ "key = torch.empty(4, dtype=torch.float32, device=device).random_()\n",
+ "key"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "FRz94NaZGyRS"
+ },
+ "source": [
+ "Let's encrypt 100 elements `torch.bool` tensor and store the result in 56 elements `torch.int16` tensor:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "8uiqxiehF_is"
+ },
+ "source": [
+ "initial = torch.empty(100, dtype=torch.bool, device=device).random_()\n",
+ "initial"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "G0URlmQYGfcW"
+ },
+ "source": [
+ "encrypted = torch.empty(56, dtype=torch.int16, device=device)\n",
+ "csprng.encrypt(initial, encrypted, key, \"aes128\", \"ctr\")"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "U9Zz2oXoHw9Q"
+ },
+ "source": [
+ "Decrypt it back and check that `decrypted` equals to `initial`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "YXNcdUbXHoPC"
+ },
+ "source": [
+ "decrypted = torch.empty_like(initial)\n",
+ "csprng.decrypt(encrypted, decrypted, key, \"aes128\", \"ctr\")\n",
+ "decrypted"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "ie7epw1SKrdQ"
+ },
+ "source": [
+ "assert (decrypted == initial).all()"
+ ],
+ "execution_count": null,
+ "outputs": []
+ }
+ ]
+}
\ No newline at end of file