Encryption and decryption

When using Indeed Apply through email, you must encrypt the email to which Indeed sends the applications. Indeed expects the email to be encrypted using the AES algorithm with your 128-bit secret key. The cipher mode is CBC with PKCS5 padding. The initialization vector is 16 bytes of 00.

Note: Please do not include more than one email address in the data-indeed-apply-email attribute for any given job in your XML feed. This will result in errors that will remove Indeed Apply from this job.

To encrypt your emails:

  1. Using your secret key, generate a 128-bit secret key using the first 16 bytes.
  2. Read the bytes of the plain-text email encoded in “UTF-8”.
  3. Encrypt the email using the AES algorithm and your 128-bit key. Be sure to use CBC mode and PKCS5 padding.
  4. Convert the encrypted bytes to hex string.
  5. Use this hex string as your data-indeed-apply-email attribute.

You then use the encrypted email in place of the plain-text email. Indeed Apply will recognize you are using an encrypted email.

Encrypted email example

<span class="indeed-apply-widget"
	data-indeed-apply-apiToken="8e94c9959e5021fc7f70ad5828d5ace1"
	data-indeed-apply-jobLocation="Austin TX"
	data-indeed-apply-jobCompanyName="Your Company"
	data-indeed-apply-jobTitle="Engineer"
	data-indeed-apply-email="b18d0be4c173dfa2b7cb7856e7c7b6f02a563867a9df67ca208c8b9654966299">
</span>

Encryption and decryption examples

Using C# (version 4.0)

using System.Text;
using System.IO;
using System;
using System.Security.Cryptography;

public class IA_email_encryption_test {

  public static void Main(string[] args) {
    
    string email = "john.doe@example.com";
    string key = "your api secret key";
    
    // only use first 16 bytes of the key
    byte[] keybytes = Encoding.UTF8.GetBytes(key);
    byte[] truncatedkeybytes = new byte[16];
    Array.Copy(keybytes , truncatedkeybytes , 16);
    // initialization vector is all 0's; no additonal initilization required
    byte[] iv = new byte[16];
    
    byte[] ciphertext = Encrypt(email, truncatedkeybytes, iv);
    
    string hexciphertext = ByteArrayToHexString(ciphertext);
    
    if(!hexciphertext.Equals( "eaaacff9df2e4c2a63083a303d4521f0bd41e375232a2895310179bc030addfb")) {
      Console.WriteLine("invalid encrypted value!");
    } else {
      Console.WriteLine("hex encoded encrypted email: "+hexciphertext);
      // we decrypt merely as an exercise
      string decrypted = Decrypt(ciphertext, truncatedkeybytes, iv);
      Console.WriteLine("Decrypted E-mail: "+decrypted);
    }
  }  
  
  public static byte[] Encrypt(string plainText, byte[] key, byte[] iv ) {
   
    var cypher = new AesManaged();
    cypher.Mode = CipherMode.CBC;
    cypher.Padding = PaddingMode.PKCS7;
    cypher.KeySize = 128;
    cypher.BlockSize = 128;
    cypher.Key = key;
    cypher.IV = iv;

    var icTransformer = cypher.CreateEncryptor();
    var msTemp = new MemoryStream();

    var csEncrypt = new CryptoStream(msTemp, icTransformer, CryptoStreamMode.Write);
    var sw = new StreamWriter(csEncrypt);
    sw.Write(plainText);
    sw.Close();
    sw.Dispose();

    csEncrypt.Clear();
    csEncrypt.Dispose();

    byte[] bResult = msTemp.ToArray();
    
    return bResult;
  }
  
  public static string Decrypt(byte[] ciphertext, byte[] key, byte[] iv ) {
    
    var cypher = new AesManaged();
    cypher.Mode = CipherMode.CBC;
    cypher.Padding = PaddingMode.PKCS7;
    cypher.KeySize = 128;
    cypher.BlockSize = 128;
    cypher.Key = key;
    cypher.IV = iv;

    var icTransformer = cypher.CreateDecryptor();
    var msTemp = new MemoryStream(ciphertext);

    var csDecrypt = new CryptoStream(msTemp, icTransformer, CryptoStreamMode.Read);
    var sr = new StreamReader(csDecrypt);
    
    string plaintext = sr.ReadToEnd();

    csDecrypt.Clear();
    csDecrypt.Dispose();

    return plaintext;
  }
  

  private static string ByteArrayToHexString(byte[] bytes)
  {
      StringBuilder sbHex = new StringBuilder();
      foreach (byte b in bytes)
          sbHex.AppendFormat("{0:x2}", b);
      return sbHex.ToString();
  }
  
}

Using Java (version 1.8)

import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.lang.RuntimeException;
import javax.crypto.Cipher;
import javax.crypto.spec.*;
import javax.crypto.spec.SecretKeySpec;

public class Main {

    public static void main(String[] args) {

        String email = "john.doe@example.com";
        String apiSecret = "your api secret key";
        String encrypted_email = encrypt(email, apiSecret);
        String decrypted_email = decrypt(encrypted_email, apiSecret);
        if(encrypted_email.equals("eaaacff9df2e4c2a63083a303d4521f0bd41e375232a2895310179bc030addfb")) {
            System.out.println("B64 encoded encrypted email: "+encrypted_email);
            System.out.println("decrypted email: "+decrypted_email);
        } else {
            System.out.println("invalid encrypted value!");
        }

    }

    static String encrypt(String message, String apiSecret) {
        try {
            // get api secret bytes
            byte[] keyBytes = apiSecret.getBytes(Charset.forName("UTF-8"));
            // get message bytes
            byte[] message_bytes = message.getBytes("UTF-8");
            // note that we only use the first 16 bytes of the the key
            SecretKeySpec key = new SecretKeySpec(keyBytes, 0, 16, "AES");
            // get appropriate cipher using PKCS5 padding
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec ivspec = new IvParameterSpec(new byte[]{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });
            cipher.init(Cipher.ENCRYPT_MODE, key, ivspec);
            // encrypt the message
            byte[] email_encrypted = cipher.doFinal(message_bytes);
            // this is the value that should be sent to Indeed
            return bytesToHexString(email_encrypted);
        } catch (Exception e) {
            System.out.println(e.getMessage());
            throw new RuntimeException(e);
        }
    }

    static String decrypt(String message, String apiSecret) {
        try {
            // get api secret bytes
            byte[] keyBytes = apiSecret.getBytes(Charset.forName("UTF-8"));
            // get message bytes
            byte[] message_bytes = message.getBytes(Charset.forName("UTF-8"));
            // convert from b64 encoding
            message_bytes = decodeHex(message_bytes);
            // Create a SecretKeySpec using api secret
            // note that we only use the first 16 bytes of the the key
            SecretKeySpec key = new SecretKeySpec(keyBytes, 0, 16, "AES");
            // get appropriate cipher using PKCS5 padding
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec ivspec = new IvParameterSpec(new byte[]{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });
            cipher.init(Cipher.DECRYPT_MODE, key, ivspec);
            // decrypt the message
            byte[] email_decrypted = cipher.doFinal(message_bytes);
            return new String(email_decrypted, "UTF-8");
        } catch (Exception e) {
            System.out.println(e.getMessage());
            throw new RuntimeException(e);
        }
    }

    static String bytesToHexString(byte[] in) {
        final StringBuilder builder = new StringBuilder();
        for(byte b : in) {
            builder.append(String.format("%02x", b));
        }
        return builder.toString();
    }

    static byte[] decodeHex(byte[] data) throws Exception {
        String text = new String(data, "UTF-8");
        char[] chars = text.toCharArray();

        int len = chars.length;
        byte[] out = new byte[len >> 1];
        int i = 0;

        for(int j = 0; j < len; ++i) {
            int f = toDigit(chars[j], j) << 4;
            ++j;
            f |= toDigit(chars[j], j);
            ++j;
            out[i] = (byte)(f & 255);
        }
        return out;
    }

    static int toDigit(char ch, int index) throws Exception {
        int digit = Character.digit(ch, 16);
        if (digit == -1) {
            throw new Exception("Illegal hexadecimal character " + ch + " at index " + index);
        } else {
            return digit;
        }
    }

}

Using Perl (version 5.0)

use Crypt::CBC;
use Encode;

# your secret key
my $secret = encode('UTF-8', 'your api secret key');
# truncate key to 16 bytes
my $key = substr($secret, 0, 16);
# initialization vector of zeros
my $iv = "\0" x 16;
# create cipher
my $cipher = Crypt::CBC->new( -literal_key => 1,
 -header => 'none',
 -key => $key,
 -keysize => 16,
 -iv => $iv,
 -cipher => "Crypt::OpenSSL::AES"
 );
# Encrypt the UTF-8 encoded string into a hex version of the data
my $email_encrypted = $cipher->encrypt_hex(encode('UTF-8', 'john.doe@example.com'));

if($email_encrypted eq 'eaaacff9df2e4c2a63083a303d4521f0bd41e375232a2895310179bc030addfb') {
	print "Hex value of encrypted: $email_encryptedn";
	# Decrypt the hex string to see if it's still intact
	my $email_decrypted = $cipher->decrypt_hex($email_encrypted);
	print "Decrypted: $email_decryptedn";
} else {
	print "invalild encrypted value! $email_encryptedn";
}

Using PHP (version 7.0)

function pkcs5_pad ($text) {
    $blocksize = 16;
    $pad = $blocksize - (strlen($text) % $blocksize);
    $text .= str_repeat(chr($pad), $pad);
    return $text;
}

function pkcs5_unpad($text) {
    $pad = ord($text{strlen($text)-1});
    if ($pad > strlen($text)) return false;
    if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) return false;
    return substr($text, 0, -1 * $pad);
}

function encrypt($str, $key) {
    $iv = str_repeat("\0", 16);
    $str = pkcs5_pad($str);
    $opts =  OPENSSL_RAW_DATA;
    $encrypted = openssl_encrypt($str, 'AES-128-CBC', $key, $opts, $iv);
    return $encrypted;
}

function decrypt($str, $key) {
    $iv = str_repeat(""\0", 16);
    $opts =  OPENSSL_RAW_DATA;
    $decrypted = openssl_decrypt($str, 'AES-128-CBC', $key, $opts, $iv);
    return pkcs5_unpad($decrypted);
}

$api_secret = "your api secret key";
$email_address = "john.doe@example.com";

// truncate api-secret to first 16 bytes
$newkey = mb_strcut($api_secret, 0, 16, "UTF8");
// encrypt
$encrypted = encrypt($email_address, $newkey);
// we decrypt merely as an exercise
$decrypted = decrypt($encrypted, $newkey);
// this is the value to send to Indeed
$encryptedhex = bin2hex($encrypted);
if($encryptedhex != "eaaacff9df2e4c2a63083a303d4521f0bd41e375232a2895310179bc030addfba655e21c3309d9343206ae55866764e8")
    print("invalid encrypted hex value!");
print("Hex value of encrypted: " . $encryptedhex . "n");
print("Decrypted: " . $decrypted . "n");

Using Python (version 2.7)

# https://pypi.python.org/pypi/pycryptodome/3.5.1
from Crypto.Cipher import AES
# https://pypi.python.org/pypi/pkcs7/0.1.2
from pkcs7 import PKCS7Encoder
# your secret key
secret = 'your api secret key'.encode('utf-8')
# truncate key to 16 bytes
key_bytes = secret[0:16]
# initialization vector of zeros
iv = '\0' * 16
# the email address to encrypt
message_plaintext = 'john.doe@example.com'
# pad the plaintext to 16 byte boundary
PKCS7encoder = PKCS7Encoder()
message_plaintext_padded = PKCS7encoder.encode(message_plaintext);
# encrypt the message bytes
cipher = AES.new(key_bytes, AES.MODE_CBC, iv)
message_encrypted_raw = cipher.encrypt(message_plaintext_padded)
# this is the value that should be sent to Indeed
message_encrypted_hex = message_encrypted_raw.encode('hex')
# we need a new instance for decrypt because the ciphers are stateful
decipher = AES.new(key_bytes, AES.MODE_CBC, iv)
# we decrypt here simply as an exercise
message_decrypted_raw = decipher.decrypt(message_encrypted_raw)
# strip padding
message_decrypted = PKCS7encoder.decode(message_decrypted_raw)
# confirm encrypted value
if message_encrypted_hex == "eaaacff9df2e4c2a63083a303d4521f0bd41e375232a2895310179bc030addfb":
  print 'Hex value of encrypted: ' + message_encrypted_hex
  print 'Decrypted: '+message_decrypted
else: 
  print 'invalild encrypted value! ' + message_encrypted_hex

Using Python (version 3.6)

# https://pypi.python.org/pypi/pycryptodome/3.5.1
from Crypto.Cipher import AES
# https://pypi.python.org/pypi/pkcs7/0.1.2
from pkcs7 import PKCS7Encoder
# your secret key
secret = 'your api secret key'.encode('utf-8')
# truncate key to 16 bytes
key_bytes = secret[0:16]
# initialization vector of zeros
iv = bytes('\0' * 16, encoding='UTF-8')
# the email address to encrypt
message_plaintext = 'john.doe@example.com'
# pad the plaintext to 16 byte boundary
PKCS7encoder = PKCS7Encoder()
message_plaintext_padded = PKCS7encoder.encode(message_plaintext)
# encrypt the message bytes
message_bytes = message_plaintext_padded.encode('UTF-8')
cipher = AES.new(key_bytes, AES.MODE_CBC, iv)
message_encrypted_raw = cipher.encrypt(message_bytes)
# this is the value that should be sent to Indeed
message_encrypted_hex = message_encrypted_raw.hex()
# we decrypt here simply as an exercise
decipher = AES.new(key_bytes, AES.MODE_CBC, iv)
message_decrypted_raw = decipher.decrypt(message_encrypted_raw).decode('UTF-8')
# strip padding
message_decrypted = PKCS7encoder.decode(message_decrypted_raw)
# confirm encrypted value
if message_encrypted_hex == "eaaacff9df2e4c2a63083a303d4521f0bd41e375232a2895310179bc030addfb":
  print('Hex value of encrypted: ' + message_encrypted_hex)
  print('Decrypted: ' + message_decrypted)
else: 
  print('invalild encrypted value! ' + message_encrypted_hex)

Using SSL

Please see the List of Trusted Root SSL Certificates for supported certificates.

Next steps