---
title: Authentication
slug: authentication
description: Learn how to implement digital signature authentication with the Zide client API. This document provides step-by-step instructions for clients to create the required authentication headers, including generating a nonce, obtaining the current timestamp, cr
docTags: 
createdAt: 2023-10-21T15:23:03.910Z
---

### Digital Signature Authentication

The Zide client API employs digital signature authentication to ensure that the requests are genuine and have not been tampered with during transmission. Clients must use their private keys to sign the requests, the Zide api server verifies these signatures using the corresponding public keys.

Ensure your Zide private key used for signing requests is stored securely and is never shared or transmitted. The Zide client api will never ask for your private key.

### Steps for clients

1. Steps to create the headers needed for Zide client api authentication

- **Create a Nonce**: A nonce is a random string that should be unique for each request to prevent replay attacks.
- **Get the current timestamp**: It helps in ensuring that the request is only valid for a specific time period to prevent replay attacks.
- **Create the data string**: Combine the request’s URL, timestamp, and nonce to form a data string.
- **Sign the data string**: Use your private key to sign the data string. The signing should be done using the RSA-SHA256 algorithm.
- **Encode the Signature:&#x20;**&#x42;ase64 encode the signature.

### Header Information

Include the following headers in the HTTP request:

- **X-CLIENT-ID**: Your client’s ID from the Zide dashboard.
- **X-SIGNATURE**: The base64 encoded signature.
- **X-TIMESTAMP**: The timestamp.
- **X-NONCE**: The nonce.

### Sample Code to Create a Request

:::CodeblockTabs
```go
package main

import (
	“crypto/rand”
	“crypto/rsa”
	“crypto/sha256”
	“crypto/x509"
	“encoding/base64”
	“fmt”
	“strconv”
	“time”
)

type ZideAuthenticationHeaders struct {
    XClientID  string `json:"X-CLIENT-ID"`
    XSignature string `json:"X-SIGNATURE"`
    XTimestamp string `json:"X-TIMESTAMP"`
    XNonce     string `json:"X-NONCE"`
}

func createAuthenticationHeaders(clientID, privateKeyPem, url string) (*ZideAuthenticationHeaders, error) {
	// Parse the private key
	block, _ := pem.Decode([]byte(privateKeyPem))
	if block == nil {
		return nil, fmt.Errorf(“failed to parse private key”)
	}	privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
	
	if err != nil {
		return nil, err
	}	
	
	// Create a nonce
	nonce := “unique-string”	
	
	// Get the current timestamp
	timestamp := strconv.FormatInt(time.Now().Unix(), 10)	
	
	// Create the data string to be signed
	dataToSign := url + timestamp + nonce	
	
	// Hash the data string
	hashedData := sha256.Sum256([]byte(dataToSign))	
	
	// Sign the hashed data with the private key
	signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashedData[:])
	if err != nil {
		return nil, err
	}	
	
	// Base64 encode the signature
	encodedSignature := base64.StdEncoding.EncodeToString(signature)	
	
	// Create a header
	headers := &ZideAuthenticationHeaders{
        XClientID:  clientID,
        XSignature: encodedSignature,
        XTimestamp: timestamp,
        XNonce:     nonce,
    }

	return headers
}
```

```python
import crypto
import rsa
import hashlib
import base64
import time
import json
import pem
import x509
import fmt
import strconv

class ZideAuthenticationHeaders:
    def __init__(self):
        self.XClientID = ""
        self.XSignature = ""
        self.XTimestamp = ""
        self.XNonce = ""

def createAuthenticationHeaders(clientID, privateKeyPem, url):
    block, _ = pem.decode(privateKeyPem.encode())
    if block is None:
        return None, fmt.Errorf("failed to parse private key")
    privateKey = x509.parse_pkcs1_private_key(block.bytes())
    nonce = "unique-string"
    timestamp = str(int(time.time()))
    dataToSign = url + timestamp + nonce
    hashedData = hashlib.sha256(dataToSign.encode()).digest()
    signature = rsa.sign(hashedData, privateKey, crypto.SHA256)
    encodedSignature = base64.b64encode(signature).decode()
    headers = ZideAuthenticationHeaders()
    headers.XClientID = clientID
    headers.XSignature = encodedSignature
    headers.XTimestamp = timestamp
    headers.XNonce = nonce
    return headers
```

```typescript
import * as crypto from 'crypto';
import * as fs from 'fs';
import * as util from 'util';
import * as base64 from 'base64-js';
import * as sha256 from 'sha256';
import * as rsa from 'node-rsa';
import * as moment from 'moment';

interface ZideAuthenticationHeaders {
    'X-CLIENT-ID': string;
    'X-SIGNATURE': string;
    'X-TIMESTAMP': string;
    'X-NONCE': string;
}

async function createAuthenticationHeaders(clientID: string, privateKeyPem: string, url: string): Promise<ZideAuthenticationHeaders> {
    const privateKey = new rsa(privateKeyPem);
    const nonce = 'unique-string';
    const timestamp = moment().unix().toString();
    const dataToSign = url + timestamp + nonce;
    const hashedData = sha256(dataToSign);
    const signature = privateKey.sign(hashedData, 'buffer');
    const encodedSignature = base64.fromByteArray(signature);
    const headers: ZideAuthenticationHeaders = {
        'X-CLIENT-ID': clientID,
        'X-SIGNATURE': encodedSignature,
        'X-TIMESTAMP': timestamp,
        'X-NONCE': nonce,
    };
    return headers;
}
```

```java
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;

class ZideAuthenticationHeaders {
    private String xClientID;
    private String xSignature;
    private String xTimestamp;
    private String xNonce;

    public ZideAuthenticationHeaders(String xClientID, String xSignature, String xTimestamp, String xNonce) {
        this.xClientID = xClientID;
        this.xSignature = xSignature;
        this.xTimestamp = xTimestamp;
        this.xNonce = xNonce;
    }

    public String getXClientID() {
        return xClientID;
    }

    public String getXSignature() {
        return xSignature;
    }

    public String getXTimestamp() {
        return xTimestamp;
    }

    public String getXNonce() {
        return xNonce;
    }
}

public class Main {
    public static ZideAuthenticationHeaders createAuthenticationHeaders(String clientID, String privateKeyPem, String url) throws Exception {
        byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyPem);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

        String nonce = "unique-string";

        String timestamp = String.valueOf(new Date().getTime() / 1000);

        String dataToSign = url + timestamp + nonce;

        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hashedData = digest.digest(dataToSign.getBytes(StandardCharsets.UTF_8));

        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        signature.update(hashedData);
        byte[] signedData = signature.sign();

        String encodedSignature = Base64.getEncoder().encodeToString(signedData);

        ZideAuthenticationHeaders headers = new ZideAuthenticationHeaders(clientID, encodedSignature, timestamp, nonce);
        return headers;
    }

    public static void main(String[] args) {
        try {
            ZideAuthenticationHeaders headers = createAuthenticationHeaders("clientID", "privateKeyPem", "url");
            System.out.println(headers.getXClientID());
            System.out.println(headers.getXSignature());
            System.out.println(headers.getXTimestamp());
            System.out.println(headers.getXNonce());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
```
:::

### Sample code usage example

Here is a sample code snippet that demonstrates how a client can create such a request. This is just an example, and you should adapt it according to your actual needs and environment.

:::CodeblockTabs
```go
func makeRequest() {
	headers, err := createAuthenticationHeaders(“your-client-id”, “your-private-key-in-pem-format”, “/client/v1/transfer”)
}
```

```python
import requests

def make_request():
    headers, err = create_authentication_headers("your-client-id", "your-private-key-in-pem-format", "http://example.com/api/data")

    # Use the 'headers' dictionary to make your HTTP request
    response = requests.get("http://example.com/api/data", headers=headers)
```

```typescript
import axios, { AxiosRequestConfig } from 'axios';

async function makeRequest(): Promise<void> {
    const headers = createAuthenticationHeaders("your-client-id", "your-private-key-in-pem-format", "http://example.com/api/data");

    const config: AxiosRequestConfig = {
        method: 'get',
        url: 'http://example.com/api/data',
        headers,
    };

    try {
        const response = await axios(config);
        // Use the response data
    } catch (error) {
        console.error('Error making the request:', error);
    }
}
```

```java
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;

public void makeRequest() throws IOException {
    Map<String, String> headers = createAuthenticationHeaders("your-client-id", "your-private-key-in-pem-format", "http://example.com/api/data");
    
    URL url = new URL("http://example.com/api/data");
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    
    for (Map.Entry<String, String> entry : headers.entrySet()) {
        connection.setRequestProperty(entry.getKey(), entry.getValue());
    }
    
    // Use the connection to make your HTTP request
    // ...
}
```
:::

Replace “your-client-id” with the actual client ID, “your-private-key-in-pem-format” with the actual private key gotten from your Zide dashboard in PEM format, and “/client/v1/transfer” with the actual URL path the client wants to access.



