> ## Documentation Index
> Fetch the complete documentation index at: https://www.cashfree.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 2FA - IP Whitelisting and Public Keys

> Secure Cashfree Payouts API access with two-factor authentication by whitelisting IPs and uploading public keys so only verified servers can initiate transfers.

export const posthog_0 = undefined

## IP whitelist

The IP of the system from which you make your request has to be whitelisted to connect with the Cashfree production server. If the IP is not whitelisted, Cashfree will reject all incoming requests.

To whitelist your IP,

1. Log in to the [Merchant Dashboard](https://merchant.cashfree.com/auth/login).
2. Go to **Payouts Dashboard** > **Developers** section on the left-side navigation > **Payouts** > **Two-Factor Authentication** > **IP Whitelist**.
3. Click **Add IP Address**.
4. Enter the IP Address you want to whitelist and save the details. All the IP's you have whitelisted will be displayed as shown below. You can whitelist a maximum of 10 IPs.

<img src="https://mintcdn.com/cashfreepayments-d00050e9/_iQwC827ZHOkrGFs/static/payouts/payouts/integrations/Screenshot_2022-02-21_at_5.40.54_PM.png?fit=max&auto=format&n=_iQwC827ZHOkrGFs&q=85&s=bcc031df9cbc1339519a48feaee57c69" alt="" width="1434" height="781" data-path="static/payouts/payouts/integrations/Screenshot_2022-02-21_at_5.40.54_PM.png" />

You might encounter an IP whitelisting error even after whitelisting your IP address. This error typically occurs when you have multiple Payout accounts and the IP address is whitelisted on one account, but the API keys you're using belong to a different account.

To resolve this issue, whitelist the IP address on all your Payout accounts. Also, verify that you're using the correct API keys for the intended account. Switching to the appropriate account usually resolves the issue and prevents further authentication errors.

<Note>
  Depending on your operating system, you can retrieve the IP of the system via
  multiple methods. You can also find your IP using helper sites such as
  [https://whatismyipaddress.com/](https://whatismyipaddress.com/) <br />
  Please note that the IPv4 has to be whitelisted, not IPv6.
</Note>

## Public key

If you do not have a static IP, you can generate a public key and pass it with the API request.

<Note>
  **Note**: A password is not required to access the public key in the test environment.
</Note>

To generate a public key:

1. Log in to the [Merchant Dashboard](https://merchant.cashfree.com/auth/login).
2. Go to **Payouts Dashboard** > **Developers** section on the left-side navigation > **Payouts** > **Two-Factor Authentication** > **Public Key**.
3. Click **Generate Public Key**. The public key downloads to your computer, and the access password is sent to your registered email.

<Warning>
  You can generate only one public key at a time.
</Warning>

<img src="https://mintcdn.com/cashfreepayments-d00050e9/_iQwC827ZHOkrGFs/static/payouts/payouts/integrations/Screenshot_2023-11-27_at_4.58.38_PM.png?fit=max&auto=format&n=_iQwC827ZHOkrGFs&q=85&s=6ac0c94b1248c50ed9ac1219cf961bee" alt="" width="3334" height="1342" data-path="static/payouts/payouts/integrations/Screenshot_2023-11-27_at_4.58.38_PM.png" />

Below are the steps to generate your signature:

1. Retrieve your clientId (one which you are passing through the header X-Client-Id )
2. Append this with CURRENT UNIX timestamp separated by a period (.)
3. Encrypt this data using RSA encrypt with Public key you received – this is the signature.
4. Pass this signature through the header X-Cf-Signature.

In the case of using our library, go through the libraries section. During the initialization process, you need to pass the key as a parameter.

<Warning>When using 2FA Public Keys, merchants must include the 'X-Cf-Signature' header in their API requests. Failure to do so will result in a 'Signature missing in the request' error.</Warning>

<CodeGroup>
  ```php PHP theme={"dark"}
  <?php
  public static function getSignature() {
      $clientId = "<your clientId here>";
      $publicKey =
  openssl_pkey_get_public(file_get_contents("/path/to/certificate/public
  _key.pem"));
      $encodedData = $clientId.".".strtotime("now");
      return static::encrypt_RSA($encodedData, $publicKey);
    }
  private static function encrypt_RSA($plainData, $publicKey) { if (openssl_public_encrypt($plainData, $encrypted, $publicKey,
  OPENSSL_PKCS1_OAEP_PADDING))
        $encryptedData = base64_encode($encrypted);
      else return NULL;
      return $encryptedData;
    }
  ?>
  ```

  ```java Java theme={"dark"}
  private static String generateEncryptedSignature(String clientIdWithEpochTimestamp) {
      // String clientIdWithEpochTimeStamp = clientId+"."+Instant.now().getEpochSecond();
      String encrytedSignature = "";
      try {
          byte[] keyBytes = Files
              .readAllBytes(new File("/Users/sameera/Downloads/payout_test_public_key.pem").toPath()); // Absolute Path to be replaced
          String publicKeyContent = new String(keyBytes);
          System.out.println(publicKeyContent);
          publicKeyContent = publicKeyContent.replaceAll("[\\t\\n\\r]", "")
              .replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "");
          KeyFactory kf = KeyFactory.getInstance("RSA");
          System.out.println(publicKeyContent);
          X509EncodedKeySpec keySpecX509 = new X509EncodedKeySpec(
              Base64.getDecoder().decode(publicKeyContent));
          RSAPublicKey pubKey = (RSAPublicKey) kf.generatePublic(keySpecX509);
          final Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
          cipher.init(Cipher.ENCRYPT_MODE, pubKey);
          encrytedSignature = Base64.getEncoder().encodeToString(cipher.doFinal(clientIdWithEpochTimestamp.getBytes()));
          System.out.println(encrytedSignature);
      } catch (Exception e) {
          e.printStackTrace();
      }
      return encrytedSignature;
  }
  ```

  ```python Python theme={"dark"}
  from cashfree_sdk.payouts import Payouts
  // Initialise the SDK, pass public key for dynamic IP
  Payouts.init("<client_id>", "<client_secret>", "PROD", public_key= b'public key')
  ```

  ```javascript Node theme={"dark"}
  //require CashfreeSDK
  const cfSdk = require("cashfree-sdk");

  //access the PayoutsSdk from CashfreeSDK
  const { Payouts } = cfSdk;

  // Instantiate Cashfree Payouts
  const payoutsInstance = new Payouts({
  	env: "TEST",
  	clientId: "<CLIENT_ID>",
  	clientSecret: "<CLIENT_SECRET>",
  	pathToPublicKey: "/path/to/your/public/key/file.pem",
  	//"publicKey": "ALTERNATIVE TO SPECIFYING PATH (DIRECTLY PASTE PublicKey)"
  });
  ```
</CodeGroup>

<Note>
  **Note**: The generated signature expires after 10 minutes. A new signature must be generated every 10 minutes.
</Note>

## FAQs

<AccordionGroup>
  <Accordion title="Why do I have to whitelist the IP address or generate a public key?" onClick={() => posthog_0.capture('Accordion Clicked', { title: "Why do I have to whitelist the IP address or generate a public key?" })}>
    Whitelisting the IP address or generating a public key provides a layer of authentication. These cybersecurity techniques prevent anonymous or unknown disbursement requests and allow only verified requests.
  </Accordion>

  <Accordion title="What is an IP address?" onClick={() => posthog_0.capture('Accordion Clicked', { title: "What is an IP address?" })}>
    A string of characters that identifies each computer using the Internet Protocol to communicate over a network. Computers use IP addresses to communicate with each other over the internet.
  </Accordion>

  <Accordion title="What does it mean to whitelist an IP?" onClick={() => posthog_0.capture('Accordion Clicked', { title: "What does it mean to whitelist an IP?" })}>
    Whitelisted IPs are an index of approved entities. A whitelist approves a list of email addresses, IP addresses for communication.
  </Accordion>

  <Accordion title="What happens after I whitelist my IP address?" onClick={() => posthog_0.capture('Accordion Clicked', { title: "What happens after I whitelist my IP address?" })}>
    The Cashfree production server allows your API requests.
  </Accordion>

  <Accordion title="How many IP addresses can I whitelist?" onClick={() => posthog_0.capture('Accordion Clicked', { title: "How many IP addresses can I whitelist?" })}>
    You can whitelist a maximum of 25 IP addresses.
  </Accordion>

  <Accordion title="Does Cashfree support IPv6?" onClick={() => posthog_0.capture('Accordion Clicked', { title: "Does Cashfree support IPv6?" })}>
    No, we only support API requests from IPv4 at the moment.
  </Accordion>

  <Accordion title="Why does an IP whitelisting error occur even after whitelisting an IP, and how can it be resolved?" onClick={() => posthog_0.capture('Accordion Clicked', { title: "Why does an IP whitelisting error occur even after whitelisting an IP, and how can it be resolved?" })}>
    An IP whitelisting error can occur if multiple Payout accounts exist and the IP address is whitelisted only on one account, but the API keys in use belong to a different account. To resolve this, whitelist the IP address on all Payout accounts and ensure the correct set of API keys is used for the intended account. Switching to the appropriate account usually fixes the issue and prevents further authentication errors.
  </Accordion>

  <Accordion title="When do I use a public key?" onClick={() => posthog_0.capture('Accordion Clicked', { title: "When do I use a public key?" })}>
    If your IP address is not static, generate a public key in the Cashfree portal.
  </Accordion>

  <Accordion title="How to generate a public key from the Cashfree portal?" onClick={() => posthog_0.capture('Accordion Clicked', { title: "How to generate a public key from the Cashfree portal?" })}>
    1. In the Cashfree dashboard, select **Developers** from the navigation panel on the left.
    2. Click **Two-Factor Authentication** from the **Payouts** card.
    3. Select **Public Key** from the **Select 2FA Method** dropdown menu.
    4. Click **Generate Public Key**.
    5. The public key is downloaded to your computer. Use your registered email ID to access the key.

           <img src="https://mintcdn.com/cashfreepayments-d00050e9/rpH767oy7-0Ptnam/static/payouts/payouts/Public_Key.gif?s=e91da17df1288886ea7a441af2db4899" alt="" width="1920" height="972" data-path="static/payouts/payouts/Public_Key.gif" />
  </Accordion>

  <Accordion title="How many public keys can I generate at a time?" onClick={() => posthog_0.capture('Accordion Clicked', { title: "How many public keys can I generate at a time?" })}>
    One. You can generate only 1 public key at a time.
  </Accordion>

  <Accordion title="How to use the public key to send API requests?" onClick={() => posthog_0.capture('Accordion Clicked', { title: "How to use the public key to send API requests?" })}>
    You need to generate a signature and proceed with the API requests.

    Below are the steps to generate the signature:

    1. Retrieve your client ID.
    2. Append this with CURRENT UNIX timestamp separated by a period (.).
    3. Encrypt this data with the generated public key using RSA encryption - this is the signature.
    4. Pass this signature in the header X-CF-Signature.
  </Accordion>

  <Accordion title="Which Cashfree IP addresses should I whitelist in my server firewall?" onClick={() => posthog_0.capture('Accordion Clicked', { title: "Which Cashfree IP addresses should I whitelist in my server firewall?" })}>
    To receive Payouts webhooks, whitelist Cashfree's IP addresses on your server. See the list in [IPs to whitelist](/docs/api-reference/payouts/v2/webhooks/webhooks-v2#ips-to-whitelist).
  </Accordion>
</AccordionGroup>

<div class="hidden" data-table-of-contents="bottom">
  <p class="mt-4 font-medium flex items-center gap-2 related-docs-heading">
    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="w-4 h-4">
      <path d="M3 4h7a2 2 0 0 1 2 2v13a2 2 0 0 0-2-2H3z" />

      <path d="M21 4h-7a2 2 0 0 0-2 2v13a2 2 0 0 1 2-2h7z" />
    </svg>

    <span>Related topics</span>
  </p>

  <ul>
    <li><a href="/docs/payouts/payouts/integrations/payouts-go-live">Go-live Checklist</a></li>
    <li><a href="/docs/help/payouts/ip-whitelist">IP Whitelisting FAQs</a></li>
    <li><a href="/docs/payouts/payouts/integrations/standard-transfer">Standard Transfer Integration</a></li>
    <li><a href="/docs/payouts/payouts/integrations/batch-transfer">Batch Transfer Integration</a></li>
    <li><a href="/docs/help/payouts/general-faqs">Payouts FAQs</a></li>
  </ul>
</div>
