[Yandex Cloud documentation](../../index.md) > [Yandex Key Management Service](../index.md) > [Step-by-step guides](index.md) > Asymmetric encryption > Data encryption

# Asymmetric data encryption

In this section, you will learn how to use KMS to encrypt and decrypt data using [asymmetric encryption](../concepts/asymmetric-encryption.md).

## Getting started {#before-you-begin}

This guide uses [OpenSSL](https://www.openssl.org/) for encrypting data through the **Bash** command line. If you do not have OpenSSL yet, install it.

{% list tabs %}

- Linux

   Run this command:

   ```bash
   sudo apt-get install openssl
   ```

- Windows

   Use the [Chocolatey](https://chocolatey.org/install) package manager. Run the following command as an admin in the PowerShell terminal:

   ```powershell
   choco install openssl
   ```

{% endlist %}

## Encrypt data {#encryption}

1. If you do not have an encryption key pair, [create](asymmetric-encryption-key.md#create) one.

1. Get a public encryption key and save it:

    {% list tabs group=instructions %}

    - Management console {#console}

      1. In the [management console](https://console.yandex.cloud), select the [folder](../../resource-manager/concepts/resources-hierarchy.md#folder) with the appropriate key pair.
      1. Navigate to **Key Management Service**.
      1. In the left-hand panel, select ![image](../../_assets/kms/asymmetric-key.svg) **Asymmetric keys**.
      1. Navigate to the **Encryption** tab.
      1. In the line with the key pair, click ![image](../../_assets/console-icons/ellipsis.svg) and select **Public key**.
      1. In the window that opens, click **Download** to download a public encryption key.

    - CLI {#cli}

      If you do not have the Yandex Cloud CLI yet, [install and initialize it](../../cli/quickstart.md#install).

      The folder used by default is the one specified when [creating](../../cli/operations/profile/profile-create.md) the CLI profile. To change the default folder, use the `yc config set folder-id <folder_ID>` command. You can also specify a different folder for any command using `--folder-name` or `--folder-id`. If you access a resource by its name, the search will be limited to the default folder. If you access a resource by its ID, the search will be global, i.e., through all folders based on access permissions.

      1. See the description of the CLI command to get a public encryption key:

          ```bash
          yc kms asymmetric-encryption-crypto get-public-key --help
          ```

      1. [Get](../../resource-manager/operations/folder/get-id.md) the ID of the folder where the encryption key pair is saved.

      1. Get the ID of the required encryption key pair by specifying the folder ID:
         
         ```bash
         yc kms asymmetric-encryption-key list \
           --folder-id <folder_ID>
         ```
         
         Result:
         
         ```text
         +----------------------+-----------------------+---------------------------+---------------------+--------+
         |          ID          |          NAME         |   ENCRYPTION ALGORITHM    |     CREATED AT      | STATUS |
         +----------------------+-----------------------+---------------------------+---------------------+--------+
         | abjfmo5enqlr******** | sample-encryption-key | RSA_2048_ENC_OAEP_SHA_256 | 2023-08-16 18:10:03 | ACTIVE |
         +----------------------+-----------------------+---------------------------+---------------------+--------+
         ```

      1. Get a public encryption key by specifying the previously obtained key pair ID:

          ```bash
          yc kms asymmetric-encryption-crypto get-public-key \
            --id <key_pair_ID>
          ```

          Result:

          ```text
          key_id: abj9g2dil5sj********
          public_key: |
          -----BEGIN PUBLIC KEY-----
          MIIB...
          ...QAB
          -----END PUBLIC KEY-----
          ```

          Save this key to a file, e.g., `public.key`. Make sure that lines in the file do not start with spaces.

    - API {#api}

      To get a public encryption key, use the [AsymmetricEncryptionCryptoService/GetPublicKey](../asymmetricencryption/api-ref/grpc/AsymmetricEncryptionCrypto/getPublicKey.md) gRPC API call.

    {% endlist %}

1. Encrypt the message file:

    {% note info %}
    
    The [size](../concepts/asymmetric-encryption.md#encryption) of a message to encrypt depends on the length of an encryption key and hash function.
    
    {% endnote %}

    {% list tabs group=programming_language %}

    - Bash {#bash}

      In the terminal, run this command:

      ```bash
      openssl pkeyutl \
        -in <message_file_path> \
        -encrypt \
        -pubin \
        -inkey <public_key_file_path> \
        -pkeyopt rsa_padding_mode:oaep \
        -pkeyopt rsa_oaep_md:sha256 \
        -pkeyopt rsa_mgf1_md:sha256 | base64 > <ciphertext_file_path>
      ```

      Where:

      * `-in`: Path to the file with the message to encrypt.
      * `-inkey`: Path to the file with the public encryption key.
      * `<ciphertext_file_path>`: Path to the file the encrypted message will be saved to.

      As a result, the encrypted message will be saved to the specified file in the `base64` encoding.

    - Java {#java}

      ```java
      import org.bouncycastle.util.io.pem.PemObject;
      import org.bouncycastle.util.io.pem.PemReader;

      import javax.crypto.BadPaddingException;
      import javax.crypto.Cipher;
      import javax.crypto.IllegalBlockSizeException;
      import javax.crypto.NoSuchPaddingException;
      import java.io.IOException;
      import java.io.StringReader;
      import java.security.*;
      import java.security.spec.*;
      import java.util.Base64;

      public class EncryptRsa {
          public static void main(String[] args) throws Exception {
              String plaintext = "<message>";
              String publicKeyPem = """
              -----BEGIN PUBLIC KEY-----
              <public_key_contents>
              -----END PUBLIC KEY-----""";
              byte[] cipherTextBytes = encryptWithRsaOaep(plaintext, publicKeyPem);
              System.out.println(Base64.getEncoder().encodeToString(cipherTextBytes));
          }

          private static byte[] encryptWithRsaOaep(String plaintext, String publicKeyPem)
          throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException,
          InvalidKeyException, IllegalBlockSizeException, BadPaddingException {

              // Parsing PEM-encoded public key
              PemReader pemReader = new PemReader(new StringReader(publicKeyPem));
              PemObject pemObject = pemReader.readPemObject();
              byte[] publicKeyBytes = pemObject.getContent();

              // Creating a PublicKey object from encoded key bytes
              X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes);
              KeyFactory keyFactory = KeyFactory.getInstance("RSA");
              PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);

              // Creating a Cipher object for encryption
              Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
              cipher.init(Cipher.ENCRYPT_MODE, publicKey);

              // Text encryption
              byte[] plaintextBytes = plaintext.getBytes();

              // return cipher bytes
              return cipher.doFinal(plaintextBytes);
          }
      }
      ```

      Where:
      * `<message_text>`: Message text to encrypt.
      * `<public_key_contents>`: Contents of the public encryption key.
      
      Encryption is based on the [RSA](https://en.wikipedia.org/wiki/RSA_(cryptosystem)) algorithm using `OAEP`and `SHA-256`. The code will return ciphertext as a string in `base64` encoding.

    - Go {#go}

      ```golang
       import (
          "crypto"
          "crypto/rand"
          "crypto/rsa"
          "crypto/x509"
          "encoding/pem"
          "fmt"
          "log"
      )

      func runRsaEncryption() {
          plaintext := "<message>"
          publicKeyPem := `-----BEGIN PUBLIC KEY-----
          <public_key_contents>
          -----END PUBLIC KEY-----`
          ciphertextBytes := encryptRSA(publicKeyPem, plaintext, crypto.SHA256)
          ciphertextBase64 := base64.StdEncoding.EncodeToString(ciphertextBytes)

              fmt.Println("Ciphertext:", ciphertextBase64)
      }

      func encryptRSA(publicKeyPem string, plaintext string, hash crypto.Hash) []byte {

          block, _ := pem.Decode([]byte(publicKeyPem))
          if block == nil {
              log.Fatal("failed to decode PEM block containing public key")
          }

          pub, err := x509.ParsePKIXPublicKey(block.Bytes)
          if err != nil {
      	    log.Fatal(err)
          }

          publicKey, ok := pub.(*rsa.PublicKey)
          if !ok {
      	    log.Fatal("not RSA public key")
          }

          ciphertext, err := rsa.EncryptOAEP(hash.New(), rand.Reader, publicKey, []byte(plaintext), nil)
          if err != nil {
      	    log.Fatal(err)
          }

          return ciphertext
      }
      ```

      Where:
      * `<message_text>`: Message text to encrypt.
      * `<public_key_contents>`: Contents of the public encryption key.
      
      Encryption is based on the [RSA](https://en.wikipedia.org/wiki/RSA_(cryptosystem)) algorithm using `OAEP`and `SHA-256`. The code will return ciphertext as a string in `base64` encoding.

    - Python {#python}

      ```python
      from cryptography.hazmat.primitives.asymmetric import rsa, padding
      from cryptography.hazmat.primitives import hashes
      from cryptography.hazmat.primitives import serialization

      # Define hash algorithms and corresponding salt lengths
      def encrypt_with_rsa_oaep(plaintext, public_key_string, hash_algorithm):
          hash_algorithms = {
              'SHA256': hashes.SHA256,
              'SHA384': hashes.SHA384,
              'SHA512': hashes.SHA512
          }

          # Check if the provided hash algorithm is supported
          if hash_algorithm not in hash_algorithms:
              raise ValueError('Unsupported hash algorithm: ' + hash_algorithm)

          # Loading a PEM Encoded Public Key
          public_key = serialization.load_pem_public_key(
              public_key_string.encode()
          )

          # Text encryption
          ciphertext = public_key.encrypt(
              plaintext.encode(),
              padding.OAEP(
                  mgf=padding.MGF1(algorithm=hash_algorithms[hash_algorithm]()),
                  algorithm=hash_algorithms[hash_algorithm](),
                  label=None
              )
          )

          # Return ciphertext in Byte array format
          return ciphertext

      def test_encrypt_text():
          plaintext = "<message>"
          public_key_string = """
          -----BEGIN PUBLIC KEY-----
          <public_key_contents>
          -----END PUBLIC KEY-----"""
          ciphertext = encrypt_with_rsa_oaep(plaintext, public_key_string,'SHA256')
          ciphertext_base64 = base64.b64encode(ciphertext).decode()
          print("Ciphertext:", ciphertext_base64)
      ```

      Where:
      * `<message_text>`: Message text to encrypt.
      * `<public_key_contents>`: Contents of the public encryption key.
      
      Encryption is based on the [RSA](https://en.wikipedia.org/wiki/RSA_(cryptosystem)) algorithm using `OAEP`and `SHA-256`. The code will return ciphertext as a string in `base64` encoding.

    {% endlist %}

## Decrypt data {#decryption}

{% list tabs group=instructions %}

- CLI {#cli}

  If you do not have the Yandex Cloud CLI yet, [install and initialize it](../../cli/quickstart.md#install).

  The folder used by default is the one specified when [creating](../../cli/operations/profile/profile-create.md) the CLI profile. To change the default folder, use the `yc config set folder-id <folder_ID>` command. You can also specify a different folder for any command using `--folder-name` or `--folder-id`. If you access a resource by its name, the search will be limited to the default folder. If you access a resource by its ID, the search will be global, i.e., through all folders based on access permissions.

  1. See the description of the CLI command to decrypt data with a private encryption key:

      ```bash
      yc kms asymmetric-encryption-crypto decrypt --help
      ```

  1. [Get](../../resource-manager/operations/folder/get-id.md) the ID of the folder where the encryption key pair is saved.

  1. Get the ID of the required encryption key pair by specifying the folder ID:
     
     ```bash
     yc kms asymmetric-encryption-key list \
       --folder-id <folder_ID>
     ```
     
     Result:
     
     ```text
     +----------------------+-----------------------+---------------------------+---------------------+--------+
     |          ID          |          NAME         |   ENCRYPTION ALGORITHM    |     CREATED AT      | STATUS |
     +----------------------+-----------------------+---------------------------+---------------------+--------+
     | abjfmo5enqlr******** | sample-encryption-key | RSA_2048_ENC_OAEP_SHA_256 | 2023-08-16 18:10:03 | ACTIVE |
     +----------------------+-----------------------+---------------------------+---------------------+--------+
     ```

  1. Decrypt the ciphertext:

      ```bash
      yc kms asymmetric-encryption-crypto decrypt \
        --id <key_pair_ID> \
        --ciphertext-file <ciphertext_file_path> \
        --plaintext-file <path_to_file_with_decrypted_message> \
        --inform base64
      ```

      Where:

      * `--id`: Encryption key pair ID you obtained previously.
      * `--ciphertext-file`: Path to the file with the `base64`-encoded ciphertext.
      * `--plaintext-file`: Path to the file to save the decrypted message to.

      Result:

      ```bash
      key_id: abjt22qubivb********
      plaintext: 0KHQv...QuSE=
      ```

      As a result of executing the command, the encrypted message will be decrypted with the private encryption key in KMS and the decrypted text will be saved to the specified file.

- API {#api}

  To decrypt data, use the [AsymmetricEncryptionCryptoService/Decrypt](../asymmetricencryption/api-ref/grpc/AsymmetricEncryptionCrypto/decrypt.md) gRPC API call.

{% endlist %}