facebooklinkedinrsstwitterBlogAsset 1PRDatasheetDatasheetAsset 1DownloadForumGuideLinkWebinarPRPresentationRoad MapVideofacebooklinkedinrsstwitterBlogAsset 1PRDatasheetDatasheetAsset 1DownloadForumGuideLinkWebinarPRPresentationRoad MapVideo

Data Security: Why Actian Zen is a Better Data Store than Flat Files

Flat files are quick to set up for data storage. Because of their ease of use, they are a frequently selected solution for data storage needs. But safe data storage often requires more than simply persisting information to a drive.

The securing of information requires protection from unauthorized parties reading it, adding undesired data to it, or deleting it. Custom implementations to meet these needs add complexity. That complexity is multiplied when a solution must work in a multilevel distributed data environment, such as IoT.

Actian Zen provides a solution for data security at different levels and ways that flat files cannot.

This page covers the topics listed at right.

Data Security

What do we mean when we talk about data security? Data security includes concepts such as authorization, authentication, and providing layers of protection to information to prevent access from parties that haven’t been granted permission to the data.

Authentication tells us who a user is.

Authorization determines what a user is allowed to do.

Together these help decide who a user is and whether they have access to files and data within those files.

And the data doesn’t live only within these files. The data may also move between systems, either through a network connection or by moving physical storage. If someone intercepts the data, we might not want them to be able to read it. Encryption is used to make the data unintelligible to parties that are not authorized to read it.

Securing Flat File Data Stores

What does security look like for flat files?

Typically, you rely on file permissions enabled by the operating system on a per-machine basis. Since file permissions grant or deny access to the file as a whole, there is no way to apply permissions to specific data within the file.

Imagine devices within a hospital collecting and storing vitals on a patient. If someone needed to perform analysis on the vitals, but not see identifying information of the patients with a flat file-based solution, file permissions don’t allow granting access to only some of the data within the file.

In addition, by default the file itself is unencrypted. Any solution to encrypt and decrypt the file on a per-user basis would have to be implemented by the developer.

The following code sample writes data to a file, reads the data back from the file, and displays it. If you open the file with a text editor, the data is clearly visible.

void writeToFile(string fileName, string text)
{
     fstream targetStream(fileName, std::fstream::out|std::ios::binary);
     targetStream.write(text.c_str(), text.size() * sizeof(char));
     targetStream.close();
}

string readFromFile(string fileName)
{
     fstream sourceStream(fileName, fstream::in | fstream::binary);
     sourceStream.seekg(0, ios::end);
     size_t size = sourceStream.tellg();
     sourceStream.seekg(0, ios::beg);
     char* c = new char[size];
     sourceStream.read(c, size);
     string data = string(c, size);
     return data;
}

int main(int argc, char* argv[]) {
     string plainText = "This is the plain text message that will be stored in the file";

     writeToFile("plainText.txt", plainText);
     string textFromFile = readFromFile("plainText.txt");
     cout << textFromFile
}

If the data must be encrypted, it is up to the developer to ensure this happens.

The first thought of a developer might be, “I’ll just write a quick little routine to encrypt our data. It can’t be that difficult.”

It actually may not be that difficult to handle the encryption itself, but it is a huge challenge to engineer as an application solution because so many decisions must be made:

  • Which encryption algorithm should you use?
  • Which library implements the algorithm and where do you obtain that library?

Suppose you decide to encrypt your data using AES256. That’s a reasonable choice. Now you need to pick a library that provides AES encryption functionality. That’ll take a bit of research (since there are a number of choices but no clear leader), but we’ll assume you decide to use the Open Source Crypto++ library since it is validated  by the Federal Information Processing Standard (FIPS).

Next, you’ll need to familiarize yourself with the Crypto++ library. You’ll need to get the latest source and build it into a usable DLL.

After that, you’ll need to work through some samples to learn how to encrypt data. You are now ready to use the encryption library in your code.

The following sample performs the same function as the previous sample but differs in that it encrypts the data before saving it to a file and decrypts it after reading it:

int main(int argc, char* argv[])
{
     string plainText = "This is the plain text message that will be stored in the file";
     string encryptedText;
     string decryptedText;

     //The text will be encrypted and written to a file
     AES::Encryption aesEncryption(key, AES::DEFAULT_KEYLENGTH);
     CBC_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption, iv);
     StreamTransformationFilter stfEncryptor(cbcEncryption, new StringSink(encryptedText));
     stfEncryptor.Put(reinterpret_cast<const unsigned char*>(plainText.c_str()), plainText.length());
     stfEncryptor.MessageEnd();

     writeToFile("encrypted.txt", encryptedText);

     // Reading encrypted text from the file and decrypting it.
     std::string dataToDecryot = readFromFile("encrypted.txt");
     AES::Decryption aesDecryption(key, AES::DEFAULT_KEYLENGTH);
     CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, iv);
     StreamTransformationFilter stfDecryptor(cbcDecryption, new StringSink(decryptedText));
     stfDecryptor.Put(reinterpret_cast<const unsigned char*>(dataToDecryot.c_str()), 
            dataToDecryot.size());
     stfDecryptor.MessageEnd();

     cout << "Decrypted Text ( " << decryptedText.size() << ")" <<  endl;
      cout << decryptedText;
     cout << endl << endl;
     return 0;
}

If someone tries to view the file made by this program, it will be unreadable.

It works, but it adds complexity to the solution. Keep in mind that later when you move the project into production, you’ll have to routinely check to see if there have been any critical bugs exposed that make the library and your data vulnerable.

It’s a lot of time and effort.

Even after you answer all of the technical questions and do all the procurement work, there is still the biggest question of all: How do you test your code to ensure your security layer has no holes?

Even though flat file data storage is often the easiest solution for a developer to implement, it actually carries a lot of technical baggage.

However, by implementing an Actian Zen solution, you can easily achieve data security that has been rigorously tested and has ongoing support.

Levels of Security

Of course, data security occurs at many levels and you may need protection only at one level or another, so you need a system that provides the ability to set the appropriate level. Actian Zen provides both a relational engine, giving access to data through SQL calls, and a transactional microkernel for a lightweight and fast solution to manage data within files. Both options provide several levels of security.

We can think of these as tiers:

The first tier is directory and file access. The administrator can use the operating system to lock down file access per user or user group. Zen even provides a mechanism for configuring access to data files residing in a location where the user does not have operating system access. This allows the Zen application full access to the file even though the user cannot browse to, copy, delete, or modify the file directly.

The second tier is where we require the developer to provide an owner name, which serves as a password that locks down the data so that:

  • Connecting software must supply the owner name for any access, or read-only access can be allowed without supplying the owner name.
  • Encryption of data can be specified at different encryption levels.

When using the relational engine, additional security options are available. Users with access to Zen can be assigned to groups either by Zen or by Windows Active Directory. Permission options can also be more granular through the relational engine, down to the specific columns.

Another tier is wire encryption, which ensures that data sent on the database connection is encrypted. This network-level encryption has settings for low, medium, and high encryption levels, letting you make decisions about trade-offs between encryption level and performance. Zen allows encryption to be turned on for all connections or enabling it only for certain clients or servers.

Data Security with Zen

Actian Zen supports a wide range of platforms and development environments. Developers using different programming languages can take advantage of Zen as a solution for data protection needs.

For data at rest (stored on a drive) and data in transit on machines communicating with Zen, AES-256-bit encryption is provided to protect your data. By default, security is turned off, and you enable security features for your solution as needed.

As a developer, you can encrypt a data file with one simple call:

Btrieve::StatusCode BtrieveFile::SetOwner (
    Btrieve::OwnerMode ownerMode,
    const char * ownerName,
    const char * ownerNameAgain,
    bool  useLongOwnerName = true
)

This call needs to be performed only once per data file, and then all subsequent access to the file is controlled according to the ownerMode specified:

  • OWNER_MODE_ENCRYPTION_NO_READ_ALLOWED
  • OWNER_MODE_ENCRYPTION_READ_ALLOWED
  • OWNER_MODE_NO_ENCRYPTION_NO_READ_ALLOWED
  • OWNER_MODE_NO_ENCRYPTION_READ_ALLOWED

No Read Allowed options require the owner name for all access, whereas Read Allowed options permit applications to open the file and read data without providing the owner name. For the latter, errors are returned on any attempt to insert, update, or delete data.

Notice that useLongOwnerName defaults to true to encourage you to use an owner name that is more than 8 characters, up to 24 max.

When this method is called, the Zen engine encrypts all of the data currently in the file. Once the owner name is set, all subsequent operations against the file automatically handle encrypting and decrypting. The only difference to the application is providing the owner name during the file open call:

BtrieveClient btrieveClient;
Btrieve::StatusCode status;
BtrieveFile btrieveFile;
char* File_Name = "PatientInfo.MKD";
char* ownerName = "myOwnerName";
status = btrieveClient.FileOpen(&btrieveFile, FILE_NAME, ownerName, Btrieve::OPEN_MODE_NORMAL);

When you use the relational engine, permissions are more granular. Once security is enabled for a database, standard SQL statements such as CREATE USER, CREATE GROUP, GRANT, and REVOKE can be used to set access permissions. A user or group may have permissions to access a complete database, only certain tables within the database, only specific columns within a table, or only specific stored procedures.

The security options at these different levels can be combined in different ways. A solution could be configured to deny a user direct access to a database file, but still allow that user to read the data through a relational connection to the database.

By default all security options are turned off. Your security plan determines which ones need to be turned on.

Using Zen built-in encryption is far easier than the work you might do yourself to encrypt the data. Plus, you have the benefit of knowing that the encryption is based on sound security development techniques that use algorithms according to standard.

Several regulations encourage or require encryption:

  • The Payment Card Industry Data Security Standard (PCI) defines standards for handling credit card and customer data and requires that stored and transmitted data be encrypted.
  • The General Data Protection Regulation 2016/679 (GDPR) EU law says that data processors should consider the risk of accidental loss or disclosure of data and encourages storing it in a format that makes it unintelligible to unauthorized users.
  • For Health Insurance Portability and Accountability Act (HIPAA) compliance, the Department of Health and Human Services (HHS) recommends the use of encryption to protect patient data.

Next Steps

While flat files are an easy solution for storing data, they come with technical baggage. Using them puts more burden on developers to satisfy data protection needs.

Actian Zen provides an easy-to-use data storage solution that handles many data protection requirements. It has compatibility across a wide range of operating systems and development environments.

You can start exploring Actian Zen today by downloading a trial from the Actian Electronic Software Distribution site.

You can learn more about Actian Zen at its home page.

Learn more about Actian Zen security options from Zen Security Concepts and Tasks Related to Security for the Database Engine.