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