Skip to contentSkip to navigationSkip to topbar
Rate this page:
On this page

Voice Recording Encryption


(warning)

Warning

Twilio is launching a new Console. Some screenshots on this page may show the Legacy Console and therefore may no longer be accurate. We are working to update all screenshots to reflect the new Console experience. Learn more about the new Console(link takes you to an external page).

Voice Recording Encryption is a feature that provides additional security on your Twilio Programmable Voice Recordings. It allows you to encrypt your recordings with a public key.

(warning)

Warning

Once you activate the Voice Recording Encryption feature, only you will be able to decrypt the recordings. There is no one at Twilio, including Twilio support, that will be able to decrypt your recordings. Therefore testing of this feature should only be done on test accounts with non-production recordings.


How Voice Recording Encryption works

how-encryption-works page anchor

Today, by default, all Programmable Voice Recordings are encrypted at rest while stored in Twilio's cloud storage. With Voice Recording Encryption enabled, your recordings are encrypted with your public key as soon as the call ends, while the recording is within the Twilio infrastructure, and before it is in cloud storage. The recording remains in this encrypted state until you retrieve it, ensuring that the recording can only be accessed by you, the holder of the corresponding private key.

The Voice Recording Encryption feature is implemented using hybrid encryption(link takes you to an external page). The following are the summarized set of steps of encryption/decryption for each recording.

Twilio encryption steps

twilio-encryption-steps page anchor
  1. Twilio generates a random Content Encryption Key (CEK) for each recording.
  2. Twilio encrypts the recording content with the generated CEK using the AES256-GCM(link takes you to an external page) cipher.
  3. Twilio encrypts the CEK with the customer's public key using the RSAES-OAEP-SHA256-MGF1 cipher.

Customer decryption steps

customer-decryption-steps page anchor
  1. Customer retrieves the CEK and Initial Vector (IV) encryption values for the recording.
  2. Customer decrypts the CEK using their private key.
  3. Customer decrypts the recording content using the CEK, along with the IV encryption value.

Detailed decryption steps and code samples can be found later in this guide.


Configuring Voice Recording Encryption

configuring-voice-recording-encryption page anchor

Step 1: Generate a RSA key pair

step-1 page anchor

First, generate an RSA public/private key pair. There are many different ways to do this, we recommend using openssl(link takes you to an external page). Once you have openssl installed, you can generate a 2048 length private key with this command:


_10
openssl genrsa -out private_key.pem 2048

The generated file, private_key.pem, contains your private key, which will look something like this:


_27
-----BEGIN RSA PRIVATE KEY-----
_27
MIIEpAIBAAKCAQEAtePBUk3IM45Jj8eFFrmwzjr/2seEtMknl5OD7VDBipazsq5v
_27
MBnIYcE+EuzDiFC5XXww9rncFRZC0I3hLUejUTkJNZjMDQzVFkGXo9+A4MsXRZqK
_27
OOYhCNAr2C1acpHKK6bEqGhRW2F2R0dSndbEKOCpPKD70ZF2aZyQdb//9104ROdh
_27
bvsycQD7ZGQ8V5SoUo6kPBjQv1sbi99LN6uQm+trUDHkBhbpeKU836YPpIH1ZAqG
_27
h2sSzRHN0eXdOPYNdu649ZuOSz0kIUN22e8R39suRhu6VbrC2kvVz2Su+tSPMWlp
_27
gKjMboVKrsWUH9B1fQM9ajixc8fc892ZoGBqaQIDAQABAoIBAQCd5BlbEr4pUui0
_27
cOQs+ABs5XZYOj4OmVdPEvTAuwtm/K78+sL2JEt34EG8N978o+ZlKntukaRkgbB6
_27
Tc8ceUViKnq+Fed7pJoM+d9il4/Okz2eZCp8ffhLKDoHLEeJkNjIz7mC3xtQkegU
_27
s+sZrOcW/P6r7KrsHrOFti0IqiTOWps1M6gIUKFWcIRIh/6SyN0gmdDxmfGD9o4W
_27
CePswAS0fmwMZPCwQ9GazC8iVL+CvrF92UNfmNQSUiuR0GynOlsMnDu2GvSim3yO
_27
9lqWAo1yyEBVU8x6pS1wFTdsXQ7Ch2Ei9ZU+XE6SL5lq3jSc8WqIGmLvZ+zw5eAR
_27
8J73+fkBAoGBAO12zPHKgvN5nHRTrO3gNVcl92201umLHllf2elOjlE98/qtNsuX
_27
R96LILDv4rgSjwH0+eVQW2g2B5o3D6KPvXdEvUmaRIXDValqr1UzED1DFWLs1MQK
_27
HO30rJSpfWpTD3B56zvMb620avIBv3+Oe6kmjImn7Db/nyuEZrs49sE5AoGBAMQW
_27
bAXgbG5GDUMVvJfrWwiXz3Ip7yv2j6xz5MtU58gytVV2ZnesLSCfpKrUpalPDWsX
_27
04ZBuZ7bqZR4UpGQnGlYePtttKMdI4Vbo+tPK8gNN8ELu+8Fgmr0UNv3BWmcSRzo
_27
AfiWWIHZS6iAkPoaYWQtCtf3WU0wnt/beiP/NWKxAoGAafCUYlLMtT7OE/+4qK9c
_27
XLLtfh4tuyd7tLfUigen6orPLEjWp2GoiJpdTVLYPPLapi7axflhrk5ceeqSqR2j
_27
k3AxWoLeiyaoMtsLueD8H7ir8+Rgz80LNwXvcKtk7mh7/NwHnDgKot5Yz/sDqi6w
_27
8Lfn/wnRkn/cTRfWlTRGsdECgYEAuXjP4lsdlMyT3MFhqnzGlYEqibyaaoYD7cWN
_27
Qrpjplw4YsbkMwvbf4EhOyh6LYQFmCdoPxRJ47W4WCPbTa5wE8DIZmGlO6fjIk/E
_27
41z2d3nxI5rav0IB0vKWzQiAyR03lqzouF5VBzUmuBIrjzWGqz9jg1WF1VpI3Er3
_27
47aQo3ECgYBQ7UZ3IP1+unprNsvVDT4CbjsoAypstmQhfgxYiNPY0wB7rvTOWT3q
_27
3vwOBwVBjfvkG8yYglYgHc0xGOrqL6DxhMUFTxBe0iDvBX0QM1tpp4apsKdHvuuQ
_27
h1icaQZp8WKxBOzVilj3DLoHJEyIrsWWMnDHazV4fxbxijpj4uwJCw==
_27
-----END RSA PRIVATE KEY-----

(information)

Info

If your particular project/cryptography library requires PKCS8 syntax,(link takes you to an external page) you can convert your private key to PKCS #8 format by executing the following:


_10
openssl pkcs8 -in private_key.pem -topk8 -nocrypt -out private_key_pkcs8.pem

You will need to do this for our Java Decryption Tool(link takes you to an external page) and our JavaScript Decryption(link takes you to an external page) Tool.

(warning)

Warning

It is your responsibility to keep your private key safe. Losing your private key means that you will not be able to decrypt any of the files that were encrypted with the corresponding public key.

You can obtain the public key by executing the following command:


_10
openssl rsa -in private_key.pem -pubout -out public_key.pem

The file public_key.pem contains the public key. It should look something like this:


_10
-----BEGIN PUBLIC KEY-----
_10
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtePBUk3IM45Jj8eFFrmw
_10
zjr/2seEtMknl5OD7VDBipazsq5vMBnIYcE+EuzDiFC5XXww9rncFRZC0I3hLUej
_10
UTkJNZjMDQzVFkGXo9+A4MsXRZqKOOYhCNAr2C1acpHKK6bEqGhRW2F2R0dSndbE
_10
KOCpPKD70ZF2aZyQdb//9104ROdhbvsycQD7ZGQ8V5SoUo6kPBjQv1sbi99LN6uQ
_10
m+trUDHkBhbpeKU836YPpIH1ZAqGh2sSzRHN0eXdOPYNdu649ZuOSz0kIUN22e8R
_10
39suRhu6VbrC2kvVz2Su+tSPMWlpgKjMboVKrsWUH9B1fQM9ajixc8fc892ZoGBq
_10
aQIDAQAB
_10
-----END PUBLIC KEY-----

In the next step, you will configure Twilio with this public key.

Step 2: Create a Twilio Public Key resource

step-2 page anchor

Once you have the RSA public key, you should create a Twilio Public Key resource that contains your public key. You can do this with the Public Key Resource REST API or, in the Console(link takes you to an external page).

To configure the public key in the Console, navigate to Runtime > Credentials(link takes you to an external page) in the Console and click the Create new Credential button:

Provide a friendly name for your public key. Then, copy the full contents of the public_key.pem file generated in step 1 — including the BEGIN PUBLIC KEY and END PUBLIC KEY lines — and paste it into the PUBLIC KEY field. Click Create to create the Twilio Public Key:

(warning)

Warning

Once you submit the Twilio Public Key resource, the public key itself will no longer be retrievable from Twilio. All future references to this particular public key will be the via an associated unique SID identifier, with the form CRxx.

Step 3: Enable Voice Recording Encryption in the Console

step-3 page anchor

You can enable Voice Recording Encryption at a project or subaccount level via the Console:

Voice Recording Encryption - Console Enablement.

Decrypting Your Recordings

decrypting-your-recordings page anchor

Step 4: Retrieve recording specific encryption details

step-4 page anchor

Obtain the public_key_sid, encrypted_cek, and iv parameters within EncryptionDetails JSON object, which you can retrieved by making an HTTP GET request to the Recordings resource. The EncryptionDetails data will also be posted to your RecordingStatusCallback.

EncryptionDetails includes relevant encryption details if the recording was encrypted with the Voice Recording Encryption feature. It will be null if the recording was not encrypted. The parameters within EncryptionDetails include :

ParametersDescription
typeThe type of encryption. Currently, the only value supported is rsa-aes.
public_key_sidA 34-character string that uniquely identifies the public key resource used as by the recording encryption.
encrypted_cekBase64-encoded Content Encryption Key (CEK) used as part of recording encryption.
ivBase64-encoded randomly generated Initial Vector (IV) used as part of recording encryption.

Any recording encrypted with Voice Recording Encryption will contain additional encryption properties on the recording resource. See the request/response example below to query the recording resource metadata.

The request:


_10
curl -X GET 'https://api.twilio.com/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Recordings/REXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.json'

The response:


_28
{
_28
"account_sid": "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
_28
"api_version": "2010-04-01",
_28
"call_sid": "CAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
_28
"conference_sid": "CFXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
_28
"channels": 1,
_28
"date_created": "Fri, 14 Oct 2016 21:56:34 +0000",
_28
"date_updated": "Fri, 14 Oct 2016 21:56:38 +0000",
_28
"start_time": "Fri, 14 Oct 2016 21:56:34 +0000",
_28
"price": "-0.0025",
_28
"price_unit": "USD",
_28
"duration": "4",
_28
"sid": "REXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
_28
"source": "StartConferenceRecordingAPI",
_28
"status": "completed",
_28
"error_code": null,
_28
"uri": "/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Recordings/REXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.json",
_28
"subresource_uris": {
_28
"add_on_results": "/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Recordings/REXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/AddOnResults.json",
_28
"transcriptions": "/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Recordings/REXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Transcriptions.json"
_28
},
_28
"encryption_details": {
_28
"type": "rsa-aes",
_28
"encryption_public_key_sid": "CRXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
_28
"encryption_cek": "OV4h6zrsxMIW7h0Zfqwfn6TI2GCNl54KALlg8wn8YB8KYZhXt6HlgvBWAmQTlfYVeLWydMiCewY0YkDDT1xmNe5huEo9vjuKBS5OmYK4CZkSx1NVv3XOGrZHpd2Pl/5WJHVhUK//AUO87uh5qnUP2E0KoLh1nyCLeGcEkXU0RfpPn/6nxjof/n6m6OzZOyeIRK4Oed5+rEtjqFDfqT0EVKjs6JAxv+f0DCc1xYRHl2yV8bahUPVKs+bHYdy4PVszFKa76M/Uae4jFA9Lv233JqWcxj+K2UoghuGhAFbV/JQIIswY2CBYI8JlVSifSqNEl9vvsTJ8bkVMm3MKbG2P7Q==",
_28
"iv": "8I2hhNIYNTrwxfHk"
_28
}
_28
}

RecordingStatusCallback is the reliable way to receive webhooks for completed or failed recordings. Please see this RecordingStatusCallback support article(link takes you to an external page) for more details.

Subscribe to 'failed' RecordingStatusCallbackEvent to receive callbacks in recording encryption failure scenarios; these are described later in this article.

Here is an example of a RecordingStatusCallback webhook with encryption parameters:


_11
"RecordingSource": "OutboundAPI"
_11
"EncryptionDetails": "{"type":"rsa-aes","public_key_sid":"CR201607f4ca45a533cdca8d9a828c2a87","encrypted_cek":"ZriXxBEXSywEohXQZV53KGvyzAO1HpKRxCuMo/pcKiT7C+bWKfelZuX0eW1jb7iGcESrOqwvLo4v4GVRPDdJKsaO6R/AVTDcA+he5syPDBgg20ECilAhC/9/CNxfbIuQD+rRKmx0O7SOJJyazbc4zlv+4ClWwDm6g/8z0ekpYs/tNrlQenbxU/Un9uLeeBaJtFKeK5YSUea5n3Kce22iaPZMy3WUGBg+JfOHrccvCjDjX5QQ21I3rcdpgb5nwpzf3MQwmExhW8SJtmQ1cL4jDeKojM255HhhcgOYDwcyrTfY7svUkqNrEKei1q5ZFdBl+SjjKfSdE0BgEvTceZZYrQ==","iv":"7MiadYE7QDgVSRm9"}"
_11
"RecordingSid": "REb719a56ceca43b2d06967983570e658a"
_11
"RecordingUrl": "https://api.twilio.com/2010-04-01/Accounts/AC18d5c6f2003e8710de63b2f9c412b145/Recordings/REb719a56ceca43b2d06967983570e658a"
_11
"RecordingStatus": "completed"
_11
"RecordingChannels": "1"
_11
"ErrorCode": "0"
_11
"CallSid": "CA5987df4d600665d67f53e1bd4cec76d6"
_11
"RecordingStartTime": "Tue, 28 May 2019 02:18:02 +0000"
_11
"AccountSid": "AC18d5c6f2003e8710de63b2f9c412b145"
_11
"RecordingDuration": "5"

Step 5: Decrypt using private key and encryption parameters

step-5 page anchor
  1. Retrieve customer private key corresponding to public_key_sid and use it to decrypt the base64-encoded encrypted_cek from your retrieved EncryptionDetails object.
  2. Use the decrypted CEK and the base 64-encoded iv from your retrieved EncryptionDetails object to initialize an AES256-GCM SecretKey object.
  3. Decrypt the encrypted recording using the SecretKey.
(information)

Info

If you are using a decryption tool that requires the authentication tag, this tag is returned in the last 16 bytes of the ciphertext.

To help you with your own code, here are some decryption code samples in key languages:


Voice Recording Encryption is enabled but Twilio is unable to determine or retrieve the public key configured for recording encryption

  • The account's most recently added retrievable public key, if one exists, will be used for encryption.
  • The public_key_sid within EncryptionDetails will represent the SID of the public key used for encryption, which is not necessarily the one added to the account.
  • A notification will be sent to the account. The notification is viewable from the Debugger in the Console(link takes you to an external page) . It indicates that an alternative public key was used.

Twilio is unable to encrypt the recording because there aren't any public keys on the account or an intermittent system issue occurred.

  • The recording file is deleted and will not be available for access.
  • Recording resource metadata will have a Status of failed , an ErrorCode of 16104 , and an EncryptionDetails that is null .
  • A RecordingStatusCallback will be sent, if configured via RecordingStatusCallbackEvent, with a Status of failed , and an ErrorCode of 16104 . EncryptionDetails is not included in the callback.
  • A notification will be sent to the account. The notification is viewable from the Debugger in the Console(link takes you to an external page) . It indicates a failure was due to inaccessibility of public keys or an internal system error.


Rate this page: