#Setu Encrypted APIs
#Overview
Our secure data add-on is designed to be integrated with any KYC API to enhance the protection of sensitive data during transmission.
With this add-on, non-sensitive fields (such as id and traceId) remain visible for tracking and logging, while all sensitive information is securely packaged inside the encrypted_data field.
Setu’s public key, fetched dynamically, is used to secure the sensitive data in your request. The response from Setu will also be secured, and you must decrypt it to reconstruct the complete message.
#Integration Steps
#1. Public Key Exchange
Before transmitting any secured data, you must retrieve Setu's latest public key dynamically.
This ensures that all secured requests use the current key, as keys are rotated periodically.
GET /v2/public-key
Sample Response:
{"public-key": {"ECIES": "03d…","RSA": "MIIBI…"},"traceId": "1-67dbb.."}
Note: The public key may be updated over time.
#2. Securing Sensitive Data (Request)
Use Setu's public key (obtained from the previous step) to secure your request payload. Below are the two available methods for securing the sensitive data in your request.
#Method 1: ECIES
- Process:
The sensitive payload is directly secured using the ECIES mechanism and Setu’s public key. - Request Message Structure:
{"id": "unique-request-id-123","encrypted_data": "Encrypted_Payload"}
#Method 2: AES-RSA (Hybrid)
- Process:
- A temporary AES key is generated.
- The sensitive payload is encrypted using this AES key.
- The AES key is then encrypted using Setu’s RSA public key.
- Request Message Structure:
{"id": "unique-request-id-123","encrypted_data": "Base64_Encrypted_Payload","encrypted_key": "Base64_Encrypted_AES_Key"}
Note: In your secured request, use Setu's public key (from section 1) to secure the data.
#3. Response Handling
Setu's response will include unprotected fields (like id and traceId) along with the secured sensitive data. Depending on the method used:
- For ECIES:
The response will include anencrypted_datafield.
To recover the sensitive payload, decrypt theencrypted_datausing your ECIES private key.
{"id": "unique-request-id-123","traceId": "trace-id-456","encrypted_data": "Encrypted_Payload"}
- For AES-RSA (Hybrid):
The response will include bothencrypted_dataandencrypted_keyfields.
First, unwrap the AES key by decryptingencrypted_keyusing your RSA private key.
Then, use the recovered AES key to decrypt theencrypted_dataand retrieve the sensitive payload.
{"id": "unique-request-id-123","traceId": "trace-id-456","encrypted_data": "Base64_Encrypted_Payload","encrypted_key": "Base64_Encrypted_AES_Key"}
After decryption, merge the recovered sensitive data with the unprotected fields to reconstruct the complete response.
Note: Store your private keys securely and share your public key to setu
#Code Examples
import base64import osfrom Crypto.Cipher import AES, PKCS1_v1_5from Crypto.Util.Padding import pad, unpadfrom Crypto.PublicKey import RSAimport jsondef generate_aes_key() -> str:key = os.urandom(32) # 256-bit keyreturn base64.b64encode(key).decode('utf-8')def aes_encrypt(message: str, key_base64: str) -> str:key = base64.b64decode(key_base64)iv = os.urandom(16)cipher = AES.new(key, AES.MODE_CBC, iv)ciphertext = cipher.encrypt(pad(message.encode(), AES.block_size))return base64.b64encode(iv + ciphertext).decode('utf-8')def aes_decrypt(message: str, key_base64: str) -> str:key = base64.b64decode(key_base64)encrypted_data = base64.b64decode(message)iv = encrypted_data[:16]ciphertext = encrypted_data[16:]cipher = AES.new(key, AES.MODE_CBC, iv)return unpad(cipher.decrypt(ciphertext), AES.block_size).decode('utf-8')def rsa_encrypt(message, public_key_b64):public_key_der = base64.b64decode(public_key_b64)public_key = RSA.import_key(public_key_der)cipher = PKCS1_v1_5.new(public_key)encrypted = cipher.encrypt(message.encode())return base64.b64encode(encrypted).decode('utf-8')def rsa_decrypt(encrypted_message_b64, private_key_b64):private_key = RSA.import_key(base64.b64decode(private_key_b64))encrypted_message = base64.b64decode(encrypted_message_b64)cipher = PKCS1_v1_5.new(private_key)decrypted_message = cipher.decrypt(encrypted_message, None).decode('utf-8')return decrypted_messagedef encrypt(rsa_public_key: str, data_str: str) -> dict:aes_key = generate_aes_key()secured_data = aes_encrypt(message=data_str, key_base64=aes_key)wrapped_key = rsa_encrypt(message=aes_key, public_key_b64=rsa_public_key)return {"encrypted_data": secured_data, "encrypted_key": wrapped_key}def decrypt(rsa_private_key: str, encrypted_key: str, encrypted_data: str) -> dict:aes_key = rsa_decrypt(encrypted_message_b64=encrypted_key, private_key_b64=rsa_private_key)data = aes_decrypt(message=encrypted_data, key_base64=aes_key)return json.loads(data)# Example usage:private_key = "<YOUR_RSA_PRIVATE_KEY>"public_key = "<YOUR_RSA_PUBLIC_KEY>"data = '{"ifsc":"ABCD0123456","accountNumber":"1234567890","narration":"test transaction","matchKey":"gaurav"}'secured_response = encrypt(rsa_public_key=public_key, data_str=data)print("Secured Request:", secured_response)recovered_data = decrypt(rsa_private_key=private_key, encrypted_key=secured_response['encrypted_key'], encrypted_data=secured_response['encrypted_data'])print("Recovered Data:", recovered_data)
Was this page helpful?
