Params Encryption¶
For additional security, it is possible to encrypt Advocate, Friend, and Loyalty member email, as well as Custom User Data on back-end. This can be done by using 2048-bit key generated by Talkable for your site. So, instead of sending params in plain text, you can send them encrypted.
Site public encryption key¶
To get your unique site public encryption key, go to All Site Settings → Integrations → API integration → Public encryption key for email addresses.
Passing email as a GET parameter to Standalone Campaign¶
Also it’s possible to pass encrypted email as a GET parameter (e.g. for CTA links that point to standalone invite page). But to do that encrypted email should be URL-encoded.
Note
It’s recommended to use Optimal Asymmetric Encryption Padding (OAEP) padding scheme together with RSA encryption.
Ruby Example¶
require 'openssl'
require 'base64'
def key
@key ||= begin
key_content = File.read('talkable_your_site_slug_public_key.pem')
OpenSSL::PKey::RSA.new(key_content)
end
end
def encode_param_for_talkable(param)
encrypted_param = key.public_encrypt(param, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING)
Base64.strict_encode64(encrypted_param)
end
puts encode_param_for_talkable("email_to_encrypt@example.com")
Java Example¶
This example uses Bouncy Castle library and has been tested on:
bcprov-jdk18on-1.78.1.jar (Provider)
bcpkix-jdk18on-1.78.1.jar (PKIX/CMS/EAC/PKCS/OCSP/TSP/OPENSSL)
that can be downloaded from Bouncy Castle Latest Releases.
Note
Please note that loading a Security Provider and a key into memory takes more time than encrypting. So it is recommended to store the key in memory instead of loading it each time to avoid performance overhead.
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import java.io.FileReader;
import java.io.IOException;
import java.security.*;
import java.util.Base64;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
public class EncryptionDemo {
static class ParamEncryptor {
private Cipher cipher;
private Key publicKey;
private void initPublicKey() throws IOException {
PEMParser pemParser = new PEMParser(new FileReader("talkable_your_site_slug_public_key.pem"));
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
SubjectPublicKeyInfo publicKeyInfo = (SubjectPublicKeyInfo) pemParser.readObject();
publicKey = converter.getPublicKey(publicKeyInfo);
}
private void initCipher() throws GeneralSecurityException {
cipher = Cipher.getInstance("RSA/ECB/OAEPPadding", "BC");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
}
public ParamEncryptor() throws IOException, GeneralSecurityException {
initPublicKey();
initCipher();
}
public String encryptParam(String param) throws BadPaddingException, IllegalBlockSizeException {
byte[] input = param.getBytes();
byte[] cipherText = cipher.doFinal(input);
byte[] encodedBytes = Base64.getEncoder().encode(cipherText);
return new String(encodedBytes);
}
}
static ParamEncryptor paramEncryptor;
static {
Security.addProvider(new BouncyCastleProvider());
try {
paramEncryptor = new ParamEncryptor();
} catch (IOException | GeneralSecurityException e) {
e.printStackTrace();
}
}
public static String encryptParam(String param) throws BadPaddingException, IllegalBlockSizeException {
return paramEncryptor.encryptParam(param);
}
public static void main(String[] args) throws Exception {
String email = "email_to_encrypt@example.com";
System.out.println(encryptParam(email));
}
}
Node.js Example¶
const fs = require('fs');
const crypto = require('crypto');
// Read the public key from file
const publicKey = fs.readFileSync('talkable_your_site_slug_public_key.pem', 'utf8');
const encryptData = (data) => {
const encryptedData = crypto.publicEncrypt(
{
key: publicKey,
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
oaepHash: 'sha1',
},
Buffer.from(data)
);
return encryptedData.toString('base64');
};
// Example usage
const encryptedEmail = encryptData('email_to_encrypt@example.com');
console.log('Encrypted email:', encryptedEmail);
Front-end Part¶
Please modify the front-end using this pseudo code example:
<script>
_talkableq.push(['authenticate_customer', {
email: '<%= to_json(TalkableEncryptionService.encrypt(current_user.email)) %>',
phone_number: '<%= to_json(TalkableEncryptionService.encrypt(current_user.phone_number)) %>',
first_name: '<%= to_json(current_user.first_name) %>',
last_name: '<%= to_json(current_user.last_name) %>',
person_custom_properties: {
secret: '<%= to_json(TalkableEncryptionService.encrypt(current_user.secret)) %>'
}
}]);
</script>