Guides
Encrypt Data

Encrypt Data

Polybase DB can be publicly accessible (if @public directive used). In the case of public data, sensitive data should be encrypted before being written to the database. To make this process easier, Polybase DB has created a helper library to handle common encryption tasks: @polybase/util (opens in a new tab)

Install Polybase DB Util

npm install @polybase/util

Encrypt data using symmetric encryption

Symmetric encryption is a form of encryption which has only one key. You use the same key to perform both encrypt and decrypt functions.

There are a number of different algorithms, but we recommend using aes-cbc:

import { aescbc, decodeFromString, encodeToString, EncryptedDataAesCbc256 } from '@polybase/util'
 
export async function symmmetricEncryptString (str: string): Promise<EncryptedDataAesCbc256> {
  // This returns symmetric key as Uint8Array
  const key = aescbc.generateSecretKey()
 
  // Convert string value to Uint8Array so it can be encrypted
  const strDataToBeEncrypted = decodeFromString(str, 'utf8')
 
  // Encrypt the data, as EncryptedDataAesCbc256
  const encryptedData = await aescbc.symmetricEncrypt(key, strDataToBeEncrypted)
 
  // Store this data for later access
  return {
    version: encryptedData.version, // aes-cbc-256/symmetric
    nonce: encryptedData.nonce, // Uint8array
    ciphertext: encryptedData.ciphertext, // Uint8array
  }
}
 
export async function symmetricDecryptString (key: Uint8Array, encryptedData: EncryptedDataAesCbc256): Promise<string> {
  // Encrypt the data (as EncryptedDataAesCbc256)
  const strData = await aescbc.symmetricDecrypt(key, encryptedData)
 
  // Convert back from Uint8Array to string
  const str = encodeToString(strData, 'utf8')
 
  return str
}

Encrypt data using asymmetric encryption

Asymmetric encryption allows you to encrypt with one key (the public key) and decrypt with another key (the private key). The public key can be shared with anyone, as only the private key can be used to decrypt the data. The advantage of this approach, is that you do not have to find a way to securely send a sensitive key from one user to another (as you would with symmetric encryption).

There are a number of different algorithms, but we recommend using secp256k1 (the algorithm used by Ethereum):

import { secp256k1, decodeFromString, encodeToString, EncryptedDataSecp256k1 } from '@polybase/util'
 
// Public and private key as UInt8Array
const privateKey = generatePrivateKey()
const publicKey = secp256k1.getPublicKey64()
 
export async function asymmmetricEncryptString (publicKey: Uint8Array, str: string): Promise<EncryptedDataSecp256k1> {
 
 
  // Convert string value to UInt8Array so it can be encrypted
  const strDataToBeEncrypted = decodeFromString(str, 'utf8')
 
  // Encrypt the data (as EncryptedDataAesCbc256)
  const encryptedData = await secp256k1.asymmetricEncrypt(publicKey, strDataToBeEncrypted)
 
  // Store this data for later access
  return {
    version: encryptedData.version, // secp256k1/asymmetric
    nonce: encryptedData.nonce, // Uint8array
    ciphertext: encryptedData.ciphertext, // Uint8array
    ephemPublicKey: encryptedData.ephemPublicKey, // Uint8array
    mac: encryptedData.mac // Uint8array
  }
}
 
export async function asymmetricDecryptString (privateKey: Uint8Array, encryptedData: EncryptedDataSecp256k1): Promise<string> {
  // Encrypt the data (as EncryptedDataSecp256k1)
  const strData = await secp256k1.asymmetricDecrypt(privateKey, encryptedData)
 
  // Convert back from UInt8Array to string
  const str = encodeToString(strData, 'utf8')
 
  return str
}

Uint8Array

Most of our encryption utilities return Uint8Array values. Uint8Array is similar to node's Buffer type, but is natively compatible with both node and the browser, meaning no complex setup or polyfill is required to use it.

Converting Uint8Array to string

To convert from string to Uint8Array:

import { decodeFromString } from '@polybase/util' 
 
const strDataAsUint8Array = decodeFromString(str, 'utf8')

To convert from Uint8Array to string:

import { encodeToString } from '@polybase/util' 
 
const str = encodeToString(strDataAsUint8Array, 'utf8')

Converting Uint8Array to Buffer

To convert from Uint8Array to Buffer:

Buffer.from(uintarray_value)

To convert from Buffer to Uint8Array:

// UIntArray can be assessed using the .buffer property of Buffer
buf.buffer

Encoding Uint8Array to Hex

To convert from Uint8Array to a hexadecimal encoded string:

import { encodeToString } from '@polybase/util' 
 
const str = encodeToString(strDataAsUint8Array, 'hex')

To convert from hexadecimal encoded string to Uint8Array:

import { decodeFromString } from '@polybase/util' 
 
const uint8Array = decodeFromString(str, 'hex')

Encoding Uint8Array to Base64

To convert from Uint8Array to a base64 encoded string:

import { encodeToString } from '@polybase/util' 
 
const str = encodeToString(strDataAsUint8Array, 'base64')

To convert from base64 encoded string to Uint8Array:

import { decodeFromString } from '@polybase/util' 
 
const uint8Array = decodeFromString(str, 'base64')

Polybase DB Docs