Generate Digital Signature for Hash

This API allows users to compute the digital signature for a given hash using a specified signing policy and key details.

Before you begin

  • Configure the signing policy with relevant details, ensuring mapping to the enrolled certificate (also identified as the signing key on the signing policy page).
  • Input payload formation.

    The byte lengths for various hashing algorithms and the additional bytes appended when sent from a Cryptographic Service Provider (CSP) or PKCS#11. It also includes the initial bytes for ASN.1 encoding for each algorithm and a script change to handle these for API based signing from the tools apart from CSP/PKCS#11.

    As the API-based signing solution requires the input payload to be pre-processed, rather than relying on CSP/PKCS#11. To handle hashing and ASN.1 encoding, it is necessary to generate the file hash using the required hash algorithm and then apply the appropriate ASN.1 encoding in accordance with the selected algorithm. The resulting ASN.1-encoded hash must be provided as the input to the API. This approach ensures that the data sent to the API is in the correct format for signature generation and remains compatible with standard cryptographic verification processes.

Hashing Algorithms: ASN.1 Encoding & Forming Payload

Hashing Algorithm Byte Lengths:

The file's hash is computed using the specified hashing algorithm.

  • SHA1: 20 bytes
  • SHA256: 32 bytes
  • SHA384: 48 bytes
  • SHA512: 64 bytes

ASN.1 Encoding Initial Bytes:

Below are the initial bytes for ASN.1 encoding, corresponding to each hashing algorithm.
  • SHA1: {0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04}
  • SHA256: {0x30,0x31,0x30,0x0D,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04}
  • SHA384: {0x30,0x41,0x30,0x0D,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04}
  • SHA512: {0x30,0x51,0x30,0x0D,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04}
Final Payload Formation:

The input of the API follows the below format for the field "fileHashContent".

ASN.1 Bytes of the Chosen Algorithm + (Length of the Used Hashing Algorithm in Hex Format) + Actual File Input Bytes
  • SHA1: 14 + 1 + 20 bytes
  • SHA256: 18 + 1 + 32 bytes
  • SHA384: 18 + 1 + 48 bytes
  • SHA512: 18 + 1 + 64 bytes
Script Command to Append ASN.1-Encoding to Input File Hash Content:
The ASN.1-encoded hash algorithm identifier can be appended to the file bytes using any of the following scripts, depending on the execution environment:
  • Python:

    python3 APIBasedEncodingPythonFile.py /path/to/your/file SHA256

    For Example:
    import hashlib
    import base64
    import sys
    import os
    
    # ASN.1 padded bytes per hash algorithm
    PADDING_BYTES = {
        'SHA1': bytes([0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04]),
        'SHA256': bytes([0x30,0x31,0x30,0x0D,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04]),
        'SHA384': bytes([0x30,0x41,0x30,0x0D,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04]),
        'SHA512': bytes([0x30,0x51,0x30,0x0D,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04]),
    }
    
    def compute_file_hash(filepath, algorithm):
        algo_map = {
            'SHA1': 'sha1',
            'SHA256': 'sha256',
            'SHA384': 'sha384',
            'SHA512': 'sha512',
        }
        if algorithm.upper() not in algo_map:
            raise ValueError(f"Unsupported algorithm: {algorithm}")
    
        hash_func = hashlib.new(algo_map[algorithm.upper()])
        with open(filepath, 'rb') as file:
            while chunk := file.read(8192):
                hash_func.update(chunk)
        return hash_func.digest()
    
    def create_asn1_hash_encoded(hash_bytes, algorithm):
        padding = PADDING_BYTES[algorithm.upper()]
        length_byte = bytes([len(hash_bytes)])  # One byte denoting the length
        full_bytes = padding + length_byte + hash_bytes
        return base64.b64encode(full_bytes)
    
    if __name__ == "__main__":
        if len(sys.argv) < 3:
            print("Usage: python script.py <file_path> <hash_algorithm>")
            print("Hash Algorithm: SHA1 | SHA256 | SHA384 | SHA512")
            sys.exit(1)
    
        file_path = sys.argv[1]
        hash_algo = sys.argv[2]
    
        if not os.path.isfile(file_path):
            print("Error: File not found:", file_path)
            sys.exit(1)
    
        try:
            hash_bytes = compute_file_hash(file_path, hash_algo)
            fileHashContent = create_asn1_hash_encoded(hash_bytes, hash_algo)
            print("fileHashContent (Base64):", fileHashContent.decode())
        except Exception as e:
            print("Error:", str(e))
            sys.exit(1)
  • Bash:
    ./APIBasedASN1EncodingBashFile.sh /path/to/your/file SHA256
    #!/bin/bash
    
    set -e
    
    # Check args
    if [[ $# -ne 2 ]]; then
      echo "Usage: $0 <file_path> <SHA1|SHA256|SHA384|SHA512>"
      exit 1
    fi
    
    FILE="$1"
    ALG="${2^^}"
    
    # Validate file
    if [[ ! -f "$FILE" ]]; then
      echo "File not found: $FILE"
      exit 1
    fi
    
    # ASN.1 Padding Hex Map
    declare -A PAD_MAP
    PAD_MAP["SHA1"]="3021300906052b0e03021a050004"
    PAD_MAP["SHA256"]="3031300d0609608648016503040201050004"
    PAD_MAP["SHA384"]="3041300d0609608648016503040202050004"
    PAD_MAP["SHA512"]="3051300d0609608648016503040203050004"
    
    if [[ -z "${PAD_MAP[$ALG]}" ]]; then
      echo "Unsupported algorithm. Use SHA1, SHA256, SHA384, or SHA512."
      exit 1
    fi
    
    # Temp working directory
    TMP_DIR=$(mktemp -d)
    trap "rm -rf $TMP_DIR" EXIT
    
    ASN1_FILE="$TMP_DIR/asn1.bin"
    LEN_FILE="$TMP_DIR/len.bin"
    HASH_FILE="$TMP_DIR/hash.bin"
    FINAL_FILE="$TMP_DIR/final.bin"
    
    # 1. Write ASN.1 padding to binary file
    echo "${PAD_MAP[$ALG]}" | xxd -r -p > "$ASN1_FILE"
    
    # 2. Compute hash bytes and save to file
    openssl dgst "-$ALG" -binary "$FILE" > "$HASH_FILE"
    
    # 3. Calculate hash length in bytes and write as a single byte
    HASH_LEN=$(stat -c %s "$HASH_FILE")
    printf "%02x\n" "$HASH_LEN" | xxd -r -p > "$LEN_FILE"
    
    # 4. Concatenate all to final binary file
    cat "$ASN1_FILE" "$LEN_FILE" "$HASH_FILE" > "$FINAL_FILE"
    
    # 5. Base64 encode final bytes
    fileHashContent=$(base64 "$FINAL_FILE")
    
    # 6. Output
    echo "fileHashContent (Base64):"
    echo "$fileHashContent"
  • PowerShell:
    ./APIBasedASN1EncodingPSFile.ps1 -FilePath /path/to/your/file -HashAlgorithm SHA256
    param (
        [Parameter(Mandatory=$true)][string]$FilePath,
        [Parameter(Mandatory=$true)][ValidateSet("SHA1", "SHA256", "SHA384", "SHA512")][string]$HashAlgorithm
    )
    
    # Define ASN.1 Padded Bytes for each algorithm
    $paddingBytesMap = @{
        "SHA1"   = @(0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04)
        "SHA256" = @(0x30,0x31,0x30,0x0D,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04)
        "SHA384" = @(0x30,0x41,0x30,0x0D,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04)
        "SHA512" = @(0x30,0x51,0x30,0x0D,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04)
    }
    
    if (-not (Test-Path $FilePath)) {
        Write-Error "File not found: $FilePath"
        exit 1
    }
    
    # Compute file hash
    $hashBytes = Get-FileHash -Path $FilePath -Algorithm $HashAlgorithm | Select-Object -ExpandProperty Hash
    $hashBinary = [byte[]]::new($hashBytes.Length / 2)
    for ($i = 0; $i -lt $hashBinary.Length; $i++) {
        $hashBinary[$i] = [Convert]::ToByte($hashBytes.Substring($i * 2, 2), 16)
    }
    
    # Get ASN.1 padding
    $paddingBytes = [byte[]]$paddingBytesMap[$HashAlgorithm]
    
    # Length byte for the hash
    $lengthByte = [byte[]]@($hashBinary.Length)
    
    # Final Byte Array = padding + lengthByte + hash
    $finalBytes = $paddingBytes + $lengthByte + $hashBinary
    
    # Base64 encode the final bytes
    $fileHashContent = [Convert]::ToBase64String($finalBytes)
    
    # Output
    Write-Host "fileHashContent (Base64):"
    Write-Output $fileHashContent
All three approaches provide equivalent functionality and may be used interchangeably based on platform or scripting preference.

Request Structure

Endpoint: /code-signing-generate-hash
Type: POST
Sample URL: https://<IP/HostName/TenantName>:<GWPORT>/avxapi/code-signing-generate-hash?gwsource=external

To understand the elements of the sample URL, click here.

Content-Type: application/json
Table 1. Input Parameter
Name Description
sessionId

Header

(Mandatory) After successfully logging in, a unique identifier assigned to a user's session after successful authentication. The session ID remains valid until it expires. The session ID is a string value.

Example: "ce7f1a14-2bf9-4e4a-89a8-bc780a255813"

username

Header

(Mandatory) AppViewX login username, represented as a string value.

Example: "User"

password

Header

(Mandatory) AppViewX login username, represented as a string value.

Example: "AppViewX@123"

Payload (Mandatory) Input data for request body in application/json format. For payload details, see Payload section.

Payload

Name Description
signingPolicy

String

(Mandatory) Enter the signing policy for code signing which is a string value.

Example: "Test_Policy_01"

signingKey

String

(Mandatory) Enter the signing key for code signing which is a string value.

Example: "Google CA Code Signing Certificate_Demo=A5:09:C1:6C:3F:72: 81:61:59:3A:58:EA:ED:33:11:ED:64:91:DC"

versionNumber

String

(Mandatory) Enter the version number for code signing, which should be a string value.

Example: "v1"

description

String

(Mandatory) Description of the hash generation, provided as a string value.

Example: "Hash Signing"

signedType

String

(Mandatory) Select the code signed type, a string that specifies Hash Based sign.

Example: "Hash Based Signing"

fileHashContent

String

(Mandatory) Enter the hash file content as a string value.

Example: "MDEwDQYJYIZIAWUDBAIBBQAEIPw9hz6RJNKrng4tnsFCUGKXA6qAyxRe2kFVOjdpfTMw"

signatureType

String

(Optional) This ensures compliance with a designated signature format while also allowing for potential support of additional signing types in the future.

Example: "RAW"

addOnFields

List<Map<String, String>>

(Optional) Specify additional fields needed for code signing.

Example: "addOnFields": [{"Version":"V1"},{"Build":"1"}]

Response Structure

  • Status Code: 200 OK
  • Message: Successful
  • Headers:
    • Content-Type: application/json
Table 2. Response Parameters
Name Description
response Contains the response attributes for generating the signature for the code signing request.
message Success message or failure description in case of error.
appStatusCode Application specific status code for the response. Will be non-null for failure response.
tags More info in case of failure response.

Status Codes

HTTP Code appStatusCode Response Message
200 OK null Successful
403 Forbidden CODE_SIGNING_0032 Permissions are not there to sign the hash of a file
500 Internal Server Error CODE_SIGNING_0062 IP provided is invalid
500 Internal Server Error CODE_SIGNING_0083 The retrieved IP address is not valid. The selected policy does not support the obtained IP address.
500 Internal Server Error CODE_SIGNING_0063 Your chosen signing type is not supported by the selected policy
500 Internal Server Error CODE_SIGNING_0056 Signing Policy Info is not present in the Database for the given input
500 Internal Server Error CODE_SIGNING_0070 Signing Key is not mapped to the given policy.
500 Internal Server Error CODE_SIGNING_0073 Certificate is not present in the cert inventory
500 Internal Server Error CODE_SIGNING_0021 Error in updating the signed data
500 Internal Server Error CODE_SIGNING_0066 Failed to convert to json string
500 Internal Server Error CODE_SIGNING_0067 Failed to encrypt
500 Internal Server Error CODE_SIGNING_0020 Error in generating the signed file
400 Bad Request CODE_SIGNING_00222 Add-on fields are not configured for the given policy.
400 Bad Request CODE_SIGNING_0082 Mandatory fields are missing in the Add-ons Section.
400 Bad Request CODE_SIGNING_00225 Multiple Add-on fields within a single key-value pair is not allowed.
400 Bad Request CODE_SIGNING_00223 Provided Add-on fields are not configured for the given policy.
400 Bad Request CODE_SIGNING_0080 Wrong Input Payload for the text fields in the text block.
400 Bad Request CODE_SIGNING_0081 Invalid Number added in the Add-ons section.
500 Internal Server Error CODE_SIGNING_00220 Your chosen signature type is currently not supported.

Sample Request/Response

Use Case

To generate a hash for code signing using code-signing-generate-hash API.

Request URL
https://<IP/HostName/TenantName>:<GWPORT>/avxapi/code-signing-generate-hash?gwsource=external
Request Payload
{
  "payload": {
    "signingPolicy": "Hash_Policy",
    "signingKey": "AppViewX Private Ltd=56:37:33:0E:B1:7D:E4:69:E7:8E:CF:83:56:59:43:93:DD:18:B4",
    "description": "Hash Signing",
    "signedType": "Hash Based Signing",
    "fileHashContent": "MDEwDQYJYIZIAWUDBAIBBQAEIPw9hz6RJNKrng4tnsFCUGKXA6qAyxRe2kFVOjdpfTMw",
    "signatureType": "RAW",
    "addOnFields": [
      {
        "Version": "V1"
      },
      {
        "Build_No": "1"
      }
    ]
  }
}
Sample Response
{
    "response": "gutIcFnlzbTT7slB1wrOAbMPzhgFszs8nA1DpMLE/7BcAP39vbgIOCIj1rlmM6bSnBl1bJ3U3CMSWqphEu8KzN9gcCknGTyAOJxEiIXOmi0P9ernL4knxoGnDe//89/rC3drt4XqLahHF7mMKrXLCLGqg0UTpOzUM0ZxQTucz4Z2iWipH3R3wNq4gYB4EijPXkp+7D0Q2PGaIiy9/1LhGzwvappbqU9QBFu3Nkr40jepEs7dGcEFYlw4E1spH+gcJsFEAN1H3UToP6zDiBSEq0ZiwXj0mU+pJGxIG49x7jOaDJgAS+p6/ll9eulwRk7Ft4NXoXwWkvYZTx2HAMz0mg==",
    "message": null,
    "appStatusCode": null,
    "tags": null,
    "headers": null
}

Reference

Understanding the sample URL:
  • IP/HostName/TenantName: Replace with the actual IP address, hostname, or tenant name based on the specific configuration in AppViewX.
    • IP: A unique identifier assigned to each device connected to a computer network that uses the Internet Protocol for communication

      The IP address will be included in the endpoint URL for an on-prem deployment.

    • HostName: A human-readable label assigned to a device (host) on a network

      The hostname will be included in the endpoint URL for an on-prem deployment.

    • TenantName: An identifier label for a tenant given to indicate which tenant's data the API request will access/modify

      The tenant name will be included in the endpoint URL for a SaaS deployment.

  • GWPORT: AppViewX gateway port

    A gateway port refers to a network port through which data is sent and received to communicate with a gateway in an on-prem deployment.

    Example: 31443

  • avxapi: Path parameter value (static) that is part of the endpoint's URL
  • Endpoint: Endpoint of the API, for example: execute-hook
  • gwsource: Source or origin of a gateway, for example: external.