Hello,
i know i can encrypt the data on the logger myself by implementing some kind of custom algorithm.
Nonetheless i would like to know, if campbell has future plans to bring the ability of data-encryption (especially for the data written to CF-card) into the OS.
greets,
cunningham
We have added an option in recent operating systems to allow you to encrypt communications between a datalogger and PC but there are no plans in the near future encrypt data files written to a card.
We have added some new features to the operating system that might make this more doable especially for files that are written with our Tablefile instruction so I will put this request in to the development team to consider.
This is an important topic! I would appreciate if this could be implemented very soon.
CRBasic should include a parameter for encrypted writing to CF and CardConvert should be updated,
that in case of CRBasic write function is enabled, the user need to enter a password for decrypting the ASC file(s).
Hello Andrew,
thanks for the quick answer!
I am sure many users would appreciate a mechanism to have data on the CF-card secured.
greets,
cunningham
I would like to underline the necessity of an built-in capability to encrypt (and decrypt data on the Server) the data from our measurements. I would also prefer a solution implemented by CS rather than something built in-house as you are definitely better in that then us!
I hope the features of data encryption of Campbell has released. I have lots of data and files that need to be storage and protect better. Now I can only encrypty all my files( excel or word) with passwords, I can not remember and think out a password that long enough at the fist time till the Password Manager App that suitable for me showed up. Clouds and browser are not a Secure Password Storage for me actually, because Cloud could be hacked and the browser is not stable. I choose Campbell for my data files storage but waiting for the encrytion features.
Me too! That is a topic that pops up al the times. Would really be good to have an integrated solution, which allows to encrypt data on the datalogger and decrypt with LoggerNet. I would also pay for if there is an upgrade in LoggerNet with this feature.
The instruction does exist in the datalogger. There is not an integrated solution in Loggernet for decrypting the data files. If you just need to encrypt data during transmission and limit access to the datalogger, look into Pakbus Encryption Key. Here is a draft help document for encrypting data files on the datalogger:
An Implementation of Sending Data as Encrypted Email Attachments from a Campbell Scientific Datalogger
Several models of Campbell Scientific Dataloggers support standard AES 128 bit encryption. Hereafter CR6 will be used to represent any encryption capable datalogger. This document describes a method of programming the datalogger to place data in an encrypted file. The datalogger then sends the encrypted file as an email attachment. On a PC, several programming languages allow creation of a simple program to use for decrypting the data from the email attachment.
Placing Unencrypted Data Into a File
First an unencrypted data file must be created. This file may be stored in a data partition called the USR drive. Though the data is unencrypted, it is safe on the USR drive. It can only be accessed externally with proper security credentials.
Data is placed into a file using the TableFile instruction. Any of the available options and formats in the TableFile instruction are compatible with encryption. There just needs to be a discrete data file created.
Encoded File Format
An encrypted file format was chosen that follows common practice. Campbell Scientific uses AES 128 bit encoding with Cipher Block Chaining (CBC) and Zero Padding. All major programming languages support these modes in their AES implementations.
16 bytes Initialization Vector
4 bytes Source Length
N bytes Encrypted Contents
CBC requires the use of a shared Initialization Vector (IV). The first 16 bytes of the encrypted file will be the IV used. The IV should be a unique random number for each encrypted message. The CR6 includes a pseudo-random number generator that can be used for generating the IV. The pseudo-random number generator should be initialized when the datalogger powers up. One method that meets the security needs of many is using the datalogger clock before the first scan. The example below shows how to use the Randomize() instruction in this manner.
BeginProg
'Initialize random number generator using seconds since 1990 + microseconds in datalogger clock
Randomize(Status.Timestamp(1,1) + Status.Timestamp(7,1))
Scan (1,Sec,0,0)
Each time you create a new encrypted file, a new IV should be created in an array of 4 variables of type Long. Using the RND() function serves to fill the array as shown below.
InitVector(1) = RND * &h7FFFFFFF
InitVector(2) = RND * &h7FFFFFFF
InitVector(3) = RND * &h7FFFFFFF
InitVector(4) = RND * &h7FFFFFFF
AES 128 bit encryption requires the source data to be an even multiple of 16 bytes in length. Zero padding is used to fill in the last block of data. The 4 bytes after the IV will be the source length before padding. The length is stored as a 32 bit signed integer in big endian byte order.
All the remaining bytes after the legth field will be the encrypted file contents. The padded length can be calculated as the length of the file minus 20 bytes. A MD5 checksum of the initialization vector from the start of the file is used as the initialization vector for the encryption algorithm. The private password/key is also put through a MD5 hash by the datalogger before use in the AES algorithm.
Example Datalogger Program
Creating the unencrypted source data file is not any different than other existing examples for the TableFile() instruction. It is recommended to place the file on the USR drive, being more secure than on a data card. The data file created to hold the encrypted data must be opened in the binary write mode, regardless of whether the source was ASCII or binary data.
The initialization vector is generated using the method shown earlier.
The encryption instruction, when successful, will return the number of source bytes encrypted. The destination will contain encrypted data of the padded length. The padded length can be calculated by utilizing an implied if and a modulo divide as shown below.
PaddedLength = EncryptResult + IIF(EncryptResult MOD 16, 16 - (EncryptResult MOD 16), 0)
When using file manipulation instructions, it is very important to remember to close the file when done with it. The input file is closed after reading the contents into a variable array. The output file is closed after writing the encrypted contents to it.
Note that the encryption process and sending the email are both in a 1 second slow scan. The entire process will likely take more than 1 second. The short scan rate will cause skipped slow scans, but decreases the delay for transmitting the data.
'Example program to encrypt files that are being placed on a removeable card Const MaxFileSize = 10000 'Maximum number of bytes that a file will be 'Email Server Configuration 'Theses values must be changed for use with your email server Dim EmailServerAddr As String = "0.0.0.0" Dim EmailToAddr As String = "me@mailserver.com" Dim EmailFromAddr As String = "datalogger@mailserver.com" Dim EmailUserName As String = "UserName" Dim EmailPassword As String = "Password" Public PTemp, batt_volt Public FileCounter As Long Dim OutStat As Boolean, ProcessFile As Boolean Dim LastFileName As String * 32 'Unencrypted file on the USR drive Public EncFileName As String * 32 'Variable, name of encrypted file on the CRD Const Key = "SuperSecret" 'Preshared key used in the encryption, should use a strong password Dim FileHandle As Long 'Used as a file access handle. Only one file accessed at a time, so is reused Const BufferArrayDimension = Ceiling(MaxFileSize/4) + 4 Dim BinaryContents(BufferArrayDimension) As Long 'Temporary storage. It is 16 bytes longer than the maximum source length to accomodate padding Dim EncContents(BufferArrayDimension) As Long 'Temporary storage for encrypted data. It is 16 bytes longer than the maximum source length to accomodate padding Public SourceLength As Long Public InitVector(4) As Long Public EncryptResult As Long Public PaddedLength As Long Dim EmailSubj As String Dim EmailMsg As String Public EmailResponse As String * 64 'Define Data Tables. DataTable (OneMin,1,-1) 'Set table size to # of records, or -1 to autoallocate. TableFile ("USR:DataFile",8,1,5,0,Min,OutStat,LastFileName) DataInterval (0,60,Sec,10) Minimum (1,batt_volt,FP2,0,False) Sample (1,PTemp,FP2) EndTable 'Main Program BeginProg 'Initialize random number generator using seconds since 1990 + microseconds in datalogger clock Randomize(Status.Timestamp(1,1) + Status.Timestamp(7,1)) SetSetting ("USRDriveSize",100000) 'Sets apart space for the USR drive. This could be set instead with DevConfig. Scan (1,Sec,0,0) PanelTemp (PTemp,15000) Battery (batt_volt) CallTable OneMin If OutStat Then ProcessFile = True EndIf NextScan SlowSequence Scan (1,Sec,3,0) 'The slow scan If ProcessFile Then FileCounter += 1 '##Read source contents from internal USR drive## FileHandle = FileOpen (LastFileName,"rb",0) Erase(EncContents) SourceLength = FileRead (FileHandle,BinaryContents(),MaxFileSize) FileClose (FileHandle) '##Encrypt the data## ' Initialization vector is a 16 byte random value InitVector(1) = RND * &h7FFFFFFF InitVector(2) = RND * &h7FFFFFFF InitVector(3) = RND * &h7FFFFFFF InitVector(4) = RND * &h7FFFFFFF EncryptResult = Encryption(EncContents(),BinaryContents(),SourceLength,Key,InitVector,16,0) '##If successful, place encrypted data in a file and attach to an email.## If EncryptResult > 0 Then 'The encrypted file could be written to the USR drive if no card will be used EncFileName = "USR:EncData.aes" FileManage (EncFileName,8) 'Delete previous file FileHandle = FileOpen (EncFileName,"wb",0) 'Create new open file 'For some types of source content, you would want to add a data length value onto the front of the file. TOA5 and TOB1 should be fine without. FileWrite (FileHandle,InitVector,16) 'Initialization vector is written at the beginning of the encrypted file FileWrite (FileHandle,SourceLength,4) 'Next four bytes is the length of the source data PaddedLength = EncryptResult + IIF(EncryptResult MOD 16, 16 - (EncryptResult MOD 16), 0) 'Round up to nearest multiple of 16 to get padded length FileWrite (FileHandle,EncContents(),PaddedLength) 'The encrypted data follows FileClose (FileHandle) 'Closing files is important EmailSubj = Status.StationName & " " & Public.Timestamp(4,1) 'Station name and station time EmailMsg = EmailSubj 'The same in the message body EmailSend (EmailServerAddr,EmailToAddr,EmailFromAddr,EmailSubj,EmailMsg,EncFileName,EmailUserName,EmailPassword,EmailResponse) EndIf ProcessFile = False EndIf 'end processing file for encryption NextScan EndProg
Example PC Program for Decoding Data
Custom applications for decoding the encrypted data file could be created with many different programming languages for many different computing platforms. This example code is a simple command line program written in VB.Net. It takes three command line arguments; the source file, a file containing the key, and a destination file name.
Imports System.Security.Cryptography Imports System.Text Imports System.IO Module Module1 Sub Main() 'Command line arguments ' s=FileName FileName is the fully qualified file name of the encrypted source ' k=FileName FileName is the fully qualified file name of the encryption key ' key is an ASCII string up to 63 characters in length stored in a file with no padding ' d=FileName FileName is the fully qualified file name of the destination file ‘ for the unencrypted data Const MaxFileSize As ULong = 4000000 'Sets the buffer size 'Read command line arguments Dim args As String() = My.Application.CommandLineArgs.ToArray Dim SourceFile As String = "" Dim KeyFile As String = "" Dim DestinationFile As String = "" Dim Datalength As Integer = 0 Try For Each s As String In args Dim beginning As String = Left(s, 2).ToLower 'grabs first two characters and makes lower case If beginning = "s=" Then SourceFile = Mid(s, 3) ElseIf beginning = "k=" Then KeyFile = Mid(s, 3) ElseIf beginning = "d=" Then DestinationFile = Mid(s, 3) End If Next Dim Key As String = File.ReadAllText(KeyFile) 'Pulls key from file Dim Unencrypted(MaxFileSize) As Byte 'Create a byte buffer to hold the unencrypted data Try ' Open the specified encrypted file. Dim fStream As FileStream = File.Open(SourceFile, FileMode.Open) 'Read first 16 bytes off front of file to use as the initialization vector Dim IV(15) As Byte For i As UShort = 0 To 15 IV(i) = fStream.ReadByte Next 'Compute MD5 hashes of Key and IV Dim md5hash As MD5 = MD5.Create Dim IVhash = md5hash.ComputeHash(IV) Dim Keyhash = md5hash.ComputeHash(Encoding.ASCII.GetBytes(Key)) Dim tempBytes(3) As Byte For i As UShort = 0 To 3 tempBytes(i) = fStream.ReadByte Next Array.Reverse(tempBytes) 'Endian correction Datalength = BitConverter.ToInt32(tempBytes, 0) 'Datalength is now the unpadded length of the data ' Create a new Rijndael(AES) object. Dim AES_Alg As Aes = Aes.Create AES_Alg.BlockSize = 128 AES_Alg.KeySize = 128 AES_Alg.Mode = CipherMode.CBC AES_Alg.Padding = PaddingMode.Zeros AES_Alg.IV = IVhash 'MD5 hash of IV AES_Alg.Key = Keyhash 'MD5 hash of Key ' Create a CryptoStream using the FileStream Dim cStream As New CryptoStream(fStream, _ AES_Alg.CreateDecryptor, _ CryptoStreamMode.Read) Try Dim srDecrypt As New StreamReader(cStream) ' Read the decrypted bytes from the decrypting stream ' and place them in the byte array buffer. For i As UShort = 0 To Datalength Unencrypted(i) = srDecrypt.Read Next Catch e As Exception Console.WriteLine("An Cerror occurred: {0}", e.Message) Finally ' Close the cryptostream and ' close the file. cStream.Close() fStream.Close() End Try Catch e As CryptographicException Console.WriteLine("A Cryptographic error occurred: {0}", e.Message) Catch e As UnauthorizedAccessException Console.WriteLine("A file error occurred: {0}", e.Message) End Try 'Write the unencrypted data to the destination file Dim oStream As FileStream = File.Open(DestinationFile, FileMode.OpenOrCreate) oStream.Write(Unencrypted, 0, Datalength) oStream.Close() Catch e As Exception Console.WriteLine("An error occurred: {0}", e.Message) End Try End Sub End Module