[Yandex Cloud documentation](../../index.md) > [Yandex Key Management Service](../index.md) > [Step-by-step guides](index.md) > Digital signature > Digital signature and its verification

# Digital signature and its verification based on data hash

In Key Management Service, you can create a [digital signature](../concepts/digital-signature.md) that can be used to validate data authenticity and integrity, as well as to protect signed data from editing.

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

In this tutorial, digital signature verification is performed using the [OpenSSL](https://www.openssl.org/) utility. 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 %}

## Create a digital signature {#create-signature}

Depending on the size of a signed message or file, KMS allows creating a message signature based [on a private key](#message-signing) or a signature [based on data hash](#hash-signing).

### Message signature based on a private key {#message-signing}

{% note info %}

A signature based on a private key is used for messages of up to 32 KB.

{% endnote %}

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

1. Get a public signature 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 digital signature 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 **Signature** 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 the digital signature public 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. View the description of the CLI command to get a signature public key:

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

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

      1. Get the ID of the required digital signature key pair by specifying the folder ID:
         
         ```bash
         yc kms asymmetric-signature-key list \
           --folder-id <folder_ID>
         ```
         
         Result:
         
         ```text
         +----------------------+----------------------+---------------------------+---------------------+--------+
         |          ID          |         NAME         |    SIGNATURE ALGORITHM    |     CREATED AT      | STATUS |
         +----------------------+----------------------+---------------------------+---------------------+--------+
         | abj9g2dil5sj******** | sample-signature-key | RSA_2048_SIGN_PSS_SHA_512 | 2023-08-16 09:06:57 | ACTIVE |
         +----------------------+----------------------+---------------------------+---------------------+--------+
         ```

      1. Get a digital signature public key by specifying the previously obtained key pair ID:
         
         ```bash
         yc kms asymmetric-signature-crypto get-public-key \
           --id <key_pair_ID>
         ```
         
         Result:
         
         ```bash
         key_id: abj9g2dil5sj********
         public_key: |
         -----BEGIN PUBLIC KEY-----
         MIIB...
         ...QAB
         -----END PUBLIC KEY-----
         ```
         
         Save the obtained key to a file, such as `public.key`. Make sure that lines in the file do not start with spaces.

    {% endlist %}

1. Create a file with a `base64`-encoded message:

    1. Create a text file, e.g., `message.txt`:

        ```bash
        cat > message.txt
        My sample message.
        It will be used to verify ECDSA signature.
        ```

        The message size must not exceed 32 KB.

    1. Change the message encoding to `base64` by specifying the path to the created message file in `base64`:

        ```bash
        base64 message.txt > <base64_message_file>
        ```

1. Create a message signature:

    {% list tabs group=instructions %}

    - CLI {#cli}

      1. View the description of the CLI command to get a digital signature:

          ```bash
          yc kms asymmetric-signature-crypto sign --help
          ```

      1. Get the message's digital signature:

          ```bash
          yc kms asymmetric-signature-crypto sign \
            --id <key_pair_ID> \
            --signature-output-file <signature_file_path> \
            --message-file <message_file_path> \
            --inform base64 \
            --outform base64
          ```

          Where:
          * `--id`: ID of the digital signature key pair.
          * `--signature-output-file`: Path to the file to save the digital signature to.
          * `--message-file`: Path to the previously created file with the `base64`-encoded message.
          * `--inform`: Message file format. Possible values: `raw` (default), `base64`, and `hex`.
          * `--outform`: Signature file format. Possible values: `raw` (default), `base64`, and `hex`.

          Result:

          ```text
          key_id: abjcg4mhmdfe********
          signature: MAa7C...imw==
          ```

      1. Change the format of the resulting digital signature to [DER](https://en.wikipedia.org/wiki/X.690#DER_encoding) (this format is required for `OpenSSL`):

          ```bash
          echo -n "$(< <signature_file_path>)" | base64 -d > <signature_file>
          ```

          Where:
          * `<signature_file_path>`: Path to the signature file you got in the previous step.
          * `<signature_file>`: Path to the new signature file in `DER` format.

      The `DER` signature file you get can be used to [verify](#verify-digital-signature) the signature using `OpenSSL`.

    {% endlist %}

## File signature based on data hash {#hash-signing}

{% note info %}

A hash-based signature is used for messages or files over 32 KB in size.

{% endnote %}

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

1. Get a digital signature public 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 digital signature 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 **Signature** 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 the signature public 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. View the description of the CLI command to get a signature public key:

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

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

      1. Get the ID of the required digital signature key pair by specifying the folder ID:
         
         ```bash
         yc kms asymmetric-signature-key list \
           --folder-id <folder_ID>
         ```
         
         Result:
         
         ```text
         +----------------------+----------------------+---------------------------+---------------------+--------+
         |          ID          |         NAME         |    SIGNATURE ALGORITHM    |     CREATED AT      | STATUS |
         +----------------------+----------------------+---------------------------+---------------------+--------+
         | abj9g2dil5sj******** | sample-signature-key | RSA_2048_SIGN_PSS_SHA_512 | 2023-08-16 09:06:57 | ACTIVE |
         +----------------------+----------------------+---------------------------+---------------------+--------+
         ```
      
      1. Get a digital signature public key by specifying the previously obtained key pair ID:
         
         ```bash
         yc kms asymmetric-signature-crypto get-public-key \
           --id <key_pair_ID>
         ```
         
         Result:
         
         ```bash
         key_id: abj9g2dil5sj********
         public_key: |
         -----BEGIN PUBLIC KEY-----
         MIIB...
         ...QAB
         -----END PUBLIC KEY-----
         ```
         
         Save the obtained key to a file, such as `public.key`. Make sure that lines in the file do not start with spaces.

    {% endlist %}

1. Get a file's hash:

    {% list tabs group=programming_language %}

    - Bash {#bash}

      Run this command:

      ```bash
      echo -n \
        $(<hashing_algorithm> <source_file_path> | cut -d " " -f 1) > \
        <hash_file_path>
      ```

      Where:
      * `<hashing_algorithm>`: Hashing algorithm used when creating a digital signature key pair. The hashing algorithm is specified above in the `SIGNATURE ALGORITHM` field of the results you get with the list of key pairs. The possible values are:
          * `sha256sum`: For SHA-256 algorithms.
          * `sha384sum`: For SHA-384 algorithms.
          * `sha512sum`: For SHA-512 algorithms.
      * `<path_to_source_file>`: Path to the file for hashing.
      * `<path_to_hash_file>`: Path to the file to save the hash to.

    - PowerShell {#powershell}

      Run this command:

      ```powershell
      (Get-FileHash -Path <source_file_path> -Algorithm <hashing_algorithm>).Hash.ToLower() | `
        Out-File -FilePath <hash_file_path> `
        -encoding ASCII `
        -NoNewline
      ```

      Where:
      * `<hashing_algorithm>`: Hashing algorithm used when creating a signature key pair. The hashing algorithm is specified above in the `SIGNATURE ALGORITHM` field of the results you get with the list of key pairs. The possible values are:
          * `SHA256`: For SHA-256 algorithms.
          * `SHA384`: For SHA-384 algorithms.
          * `SHA512`: For SHA-512 algorithms.
      * `<path_to_source_file>`: Path to the file for hashing.
      * `<path_to_hash_file>`: Path to the file to save the hash to.

    This will create a text file containing the hash of the source file.

    {% endlist %}

1. Create a hash-based file signature:

    {% list tabs group=instructions %}

    - CLI {#cli}

      1. View the description of the CLI command to get a hash-based digital signature:

          ```bash
          yc kms asymmetric-signature-crypto sign-hash --help
          ```

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

      1. Get the ID of the required digital signature key pair by specifying the folder ID:
         
         ```bash
         yc kms asymmetric-signature-key list \
           --folder-id <folder_ID>
         ```
         
         Result:
         
         ```text
         +----------------------+----------------------+---------------------------+---------------------+--------+
         |          ID          |         NAME         |    SIGNATURE ALGORITHM    |     CREATED AT      | STATUS |
         +----------------------+----------------------+---------------------------+---------------------+--------+
         | abj9g2dil5sj******** | sample-signature-key | RSA_2048_SIGN_PSS_SHA_512 | 2023-08-16 09:06:57 | ACTIVE |
         +----------------------+----------------------+---------------------------+---------------------+--------+
         ```

      1. Get a hash-based digital signature:

          ```bash
          yc kms asymmetric-signature-crypto sign-hash \
            --id <key_pair_ID> \
            --signature-output-file <signature_file_path> \
            --message-hash-file <hash_file_path> \
            --inform hex
          ```

          Where:
          * `--id`: ID of the digital signature key pair.
          * `--signature-output-file`: Path to the file to save the digital signature to.
          * `--message-hash-file`: Path to the previously created hash file.
          * `--inform`: Hash file format. The example uses the common `hex` format that is supported by all platforms. Possible values: `raw` (default), `base64`, and `hex`.

          Result:

          ```text
          signature: W7V8A...22g==
          ```

    {% endlist %}

## Verify the digital signature {#verify-digital-signature}

### ECDSA signature {#ecdsa-verification}

{% list tabs group=programming_language %}

- Bash {#bash}

   Verify the digital signature using [OpenSSL](https://www.openssl.org/):

   ```(bash)
   openssl dgst \
     -<hashing_algorithm> \
     -verify <path_to_public_key_file> \
     -signature <path_to_signature_file> \
     <path_to_signed_file>
   ```

   Where:
   * `<hashing_algorithm>`: Hashing algorithm used when creating a signature key pair. The possible values include:
      * `sha256` for SHA-256 algorithms
      * `sha384` for SHA-384 algorithms
      * `sha512` for SHA-512 algorithms
   * `-verify`: Path to the file with a public signature key.
   * `-signature`: Path to the digital signature file.
   * `<path_to_signed_file>`: Path to the file whose digital signature is being verified.

   If the signature is correct, the OpenSSL utility returns the `Verified OK` status.

- Java {#java}

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

   import javax.crypto.BadPaddingException;
   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;

   import org.bouncycastle.jce.provider.BouncyCastleProvider;

   public class VerifyEcdsaSign {

       public static void main(String[] args) throws Exception {
           String publicKeyPem =
           """
           -- -- - BEGIN PUBLIC KEY-- -- -
           <public_key_contents>
               -- -- - END PUBLIC KEY-- -- -
           """;
           String signatureStr = "<signature_string>";
           byte[] signatureDer = Base64.getDecoder().decode(signatureStr);
           System.out.println(verifyEcdsaSignature(publicKeyPem, signatureDer, "<message_string>", "<algorithm_type>"));
       }

       public static boolean verifyEcdsaSignature(String publicKeyPem, byte[] signatureDer, String message, String hash_algorithm)
       throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException,
       SignatureException, IOException {

           // Public key and subscription decoding
           PemReader pemReader = new PemReader(new StringReader(publicKeyPem));
           PemObject pemObject = pemReader.readPemObject();
           byte[] publicKeyBytes = pemObject.getContent();

           // Creating a PublicKey object from the decoded public key
           KeyFactory keyFactory = KeyFactory.getInstance("EC", new BouncyCastleProvider());
           EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes);
           PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);

           // Creating a Signature object and initializing it with a public key
           Signature signature = Signature.getInstance(hash_algorithm + "withECDSA", new BouncyCastleProvider());
           signature.initVerify(publicKey);

           // Updating a Signature Object with Message Data
           byte[] messageBytes = message.getBytes();
           signature.update(messageBytes);

           // Signature verification using original message and decoded signature
           return signature.verify(signatureDer);
       }
   }
   ```

   Where:
   * `<public_key_contents>`: Contents of the public signature key.
   * `<signature_string>`: Contents of the digital signature in `base64` encoding.
   * `<message_string>`: String with the source message signed with the digital signature or the hash of the file signed with the digital signature.
   * `<algorithm_type>`: Hash function used for the signature. The possible values are `SHA256`, `SHA384`, and `SHA512`.

   The code verifies the ECDSA signature. It returns `true` if the signature is correct and `false` if it is not.

- Go {#go}

   ```golang
   import (
       "crypto/ecdsa"
       "crypto/sha256"
       "crypto/x509"
       "encoding/asn1"
       "encoding/base64"
       "encoding/pem"
       "fmt"
       "hash"
       "log"
       "math/big"
   )

   func runEcdsaSignTest() {
       publicKeyPem := `-----BEGIN PUBLIC KEY-----
       <public_key_contents>
       -----END PUBLIC KEY-----`
       signatureB64 := "<signature_string>"
       signatureDER, _ := base64.StdEncoding.DecodeString(signatureB64)
       message := "<message_string>"

           fmt.Println(verifyEcdsa(publicKeyPem, signatureDER, message, <algorithm_type>))
   }

   type ECDSASignature struct {
       R, S *big.Int
   }

   func verifyEcdsa(publicKeyPem string, signatureDER []byte, message string, hashFunc hash.Hash) bool {

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

       // Parse the public key
       pub, err := x509.ParsePKIXPublicKey(block.Bytes)
       if err != nil {
   	    log.Fatal(err)
       }

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

       // Parse the signature
       var signature ECDSASignature
       _, err = asn1.Unmarshal(signatureDER, &signature)
       if err != nil {
   	    log.Fatal(err)
       }

       // Compute the hash of the message
       hashFunc.Write([]byte(message))
       hashed := hashFunc.Sum(nil)

       // Verify the signature
       return ecdsa.Verify(publicKey, hashed, signature.R, signature.S)
   }
   ```

   Where:
   * `<public_key_contents>`: Contents of the public signature key in `base64` encoding.
   * `<signature_string>`: Contents of the digital signature in `base64` encoding.
   * `<message_string>`: String with the source message signed with the digital signature or the hash of the file signed with the digital signature.
   * `<algorithm_type>`: Hash function used for the signature. The possible values are `sha256.New()`, `sha512.New384()`, and `sha512.New()`.

   The code verifies the ECDSA signature. It returns `true` if the signature is correct and `false` if it is not.

- Python {#python}

   ```python
   import base64
   from cryptography.hazmat.primitives import serialization
   from cryptography.hazmat.primitives.asymmetric import ec
   from cryptography.hazmat.primitives import hashes
   from cryptography.exceptions import InvalidSignature
   from cryptography.hazmat.backends import default_backend

   # Define hash algorithms
   def verify_ecdsa_signature(public_key_b64, signature_der, message, 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_b64.encode(),
           backend = default_backend()
       )

       # Create Signature object and initialize it with the public key
       signature = ec.ECDSA(hash_algorithms[hash_algorithm]())

       # Update the Signature object with the message data
       message_bytes = message.encode()

       # Verify the signature using the original message and the decoded signature
       try:
           public_key.verify(signature_der, message_bytes, signature)
           return True
       except InvalidSignature:
           return False

   def test_verify_signature():
       public_key_b64 = """
       -----BEGIN PUBLIC KEY-----
       <public_key_content>
       -----END PUBLIC KEY-----"""
       signature_b64 = "<signature>"
       signature_der = base64.b64decode(signature_b64)
       message = '<message>'
       print(verify_ecdsa_signature(public_key_b64, signature_der, message, "<algorithm_type>"))
   ```

   Where:
   * `<public_key_contents>`: Contents of the public signature key.
   * `<signature_string>`: Contents of the digital signature in `base64` encoding.
   * `<message_string>`: String with the source message signed with the digital signature or the hash of the file signed with the digital signature.
   * `<algorithm_type>`: Hash function used for the signature. The possible values are `SHA256`, `SHA384`, and `SHA512`.

   The code verifies the ECDSA signature. It returns `true` if the signature is correct and `false` if it is not.

{% endlist %}

### RSA signature {#rca-verification}

{% list tabs group=programming_language %}

- Bash {#bash}

   Verify the digital signature using [OpenSSL](https://www.openssl.org/):

   ```(bash)
   openssl dgst \
     -<hashing_algorithm> \
     -sigopt rsa_padding_mode:pss \
     -sigopt rsa_pss_saltlen:-1 \
     -verify <path_to_public_key_file> \
     -signature <path_to_signature_file> \
     <path_to_signed_file>
   ```

   Where:
   * `<hashing_algorithm>`: Hashing algorithm used when creating a signature key pair. The possible values include:
       * `sha256` for SHA-256 algorithms
       * `sha384` for SHA-384 algorithms
       * `sha512` for SHA-512 algorithms
   * `-verify`: Path to the file with a public signature key.
   * `-signature`: Path to the digital signature file.
   * `<path_to_signed_file>`: Path to the file whose digital signature is being verified.

   If the signature is correct, the OpenSSL utility returns the `Verified OK` status.

- Java {#java}

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

   import javax.crypto.BadPaddingException;
   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 VerifyRsaSign {

       public static void main(String[] args) throws Exception {
           String publicKeyPem = """
           -----BEGIN PUBLIC KEY-----
           <public_key_contents>
           -----END PUBLIC KEY-----""";
           String signatureStr = "<signature_string>";
           byte[] signatureBytes = Base64.getDecoder().decode(signatureStr);
           String message = "<message_string>";
           System.out.println(verifyRsaSignature(publicKeyPem, signatureBytes, message, "<algorithm_type>"));
       }

       private static boolean verifyRsaSignature(String publicKeyPem, byte[] signatureBytes, String message, String hashAlgorithm)
       throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException,
       SignatureException, InvalidAlgorithmParameterException, IOException {

           // Get the public key
           PemReader pemReader = new PemReader(new StringReader(publicKeyPem));
           PemObject pemObject = pemReader.readPemObject();
           byte[] publicKeyBytes = pemObject.getContent();

           // Create a PublicKey object using the decoded public key
           KeyFactory keyFactory = KeyFactory.getInstance("RSA", new BouncyCastleProvider());
           EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes);
           PublicKey pubKey = keyFactory.generatePublic(publicKeySpec);

           MessageDigest messageDigest = MessageDigest.getInstance(hashAlgorithm);
           int saltLength = messageDigest.getDigestLength();

           // Initialize the PSS signer
           PSSParameterSpec pssSpec = new PSSParameterSpec(hashAlgorithm, "MGF1", new MGF1ParameterSpec(hashAlgorithm), saltLength, 1);
           Signature signer = Signature.getInstance("RSASSA-PSS");
           signer.setParameter(pssSpec);
           signer.initVerify(pubKey);

           // Update the signature with the hash of the message
           byte[] messageBytes = message.getBytes();
           signer.update(messageBytes);

           // Verify the signature
           return signer.verify(signatureBytes);
       }
   }
   ```

   Where:
   * `<public_key_contents>`: Contents of the public signature key.
   * `<signature_string>`: Contents of the digital signature in `base64` encoding.
   * `<message_string>`: String with the source message signed with the digital signature or the hash of the file signed with the digital signature.
   * `<algorithm_type>`: Hash function used for the signature. The possible values are `SHA256`, `SHA384`, and `SHA512`.

   The code verifies the RSA digital signature. It returns `true` if the signature is correct and `false` if it is not.

- Go {#go}

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

   func runRsaSignTest() {
       publicKeyB64 := "<public_key_contents>"
       signatureB64 := "<signature_string>"
       signatureBytes, _ := base64.StdEncoding.DecodeString(signatureB64)
       message := "<message_string>"

           fmt.Println(verifyRsa(publicKeyB64, signatureBytes, message, <algorithm_type>))
   }

   func verifyRsa(publicKeyPem string, signatureBytes []byte, message string, hash crypto.Hash) bool {

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

       // Parse the 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")
       }

       // Calculate the hash of the message
       hasher := hash.New()
       hasher.Write([]byte(message))
       hashed := hasher.Sum(nil)

       // Set the PSS options: salt length auto, and the hash function
       pssOptions := &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthAuto, Hash: hash}

       // Verify the signature
       err = rsa.VerifyPSS(publicKey, hash, hashed, signatureBytes, pssOptions)
       if err != nil {
   	    fmt.Println("Verification failed:", err)
   	    return false
       } else {
   	    return true
       }
   }
   ```

   Where:
   * `<public_key_contents>`: Contents of the public signature key in `base64` encoding.
   * `<signature_string>`: Contents of the digital signature in `base64` encoding.
   * `<message_string>`: String with the source message signed with the digital signature or the hash of the file signed with the digital signature.
   * `<algorithm_type>`: Hash function used for the signature. The possible values are `crypto.SHA256`, `crypto.SHA384`, and `crypto.SHA512`.

   The code verifies the RSA digital signature. It returns `true` if the signature is correct and `false` if it is not.

- Python {#python}

   ```python
   import base64
   from cryptography.hazmat.primitives import hashes
   from cryptography.hazmat.primitives.asymmetric import padding
   from cryptography.hazmat.primitives import serialization
   from cryptography.exceptions import InvalidSignature
   from cryptography.hazmat.backends import default_backend

   # Define hash algorithms and corresponding salt lengths
   def verify_rsa_signature(public_key_b64, signature_bytes, message, 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_b64.encode(),
           backend=default_backend()
       )

       # Update the Signature object with the message data
       message_bytes = message.encode()

       # Automatically calculate salt length based on hash digest size
       salt_length = hash_algorithms[hash_algorithm]().digest_size

       # Verify the signature using the original message and the decoded signature
       try:
           public_key.verify(
               signature_bytes,
               message_bytes,
               padding.PSS(
                   mgf = padding.MGF1(hash_algorithms[hash_algorithm]()),
                   salt_length = salt_length
               ),
               hash_algorithms[hash_algorithm]()
           )
           return True
       except InvalidSignature:
           return False

   def test_verify_signature():
       public_key_b64 = """
       -----BEGIN PUBLIC KEY-----
       <public_key_contents>
       -----END PUBLIC KEY-----"""
       signature_b64 = '<signature>'
       signature_bytes = base64.b64decode(signature_b64)
       message = '<message>'
       print(verify_rsa_signature(public_key_b64, signature_bytes, message, '<algorithm_type>'))
   ```

   Where:
   * `<public_key_contents>`: Contents of the public signature key in `base64` encoding.
   * `<signature_string>`: Contents of the digital signature in `base64` encoding.
   * `<message_string>`: String with the source message signed with the digital signature or the hash of the file signed with the digital signature.
   * `<algorithm_type>`: Hash function used for the signature. The possible values are `SHA256`, `SHA384`, and `SHA512`.

   The code verifies the RSA digital signature. It returns `true` if the signature is correct and `false` if it is not.

{% endlist %}