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')