Encryption

All LSHTM Open Data Kit forms need to be fully encrypted in order to comply with the GDPR.
The attached documents explain how to implement encryption in your forms.
Any and all data currently stored on LSHTM ODK servers which is not encrypted should be downloaded from the server and the server should then be wiped of all data.

encryption_non_LSHTM_machines

encryption_LSHTM_Network

 

 

Edit 2018-05-25

Some users may find it easier to use our simple R script to pull and decrypt data from your server in a single step. The script can be found here. To use, you will need an installation of R and RStudio.

Simply create and R project file. edit the URL, a couple of other settings and add the form IDs to match your server. Then press ‘source’ on Rstudio and the script should do the rest. After first time, just open project and press source.

Please note that you still need to install the cryptography extensions for this script to work.

######################################################
# SETTINGS
#
# You need to install a version of Java that has the Java Cryptography Extensions – see instructions here https://github.com/chrissyhroberts/ODK_TRAINING/blob/master/User_Guide.md
# URL of aggregate server [must include top level directory]
# This script requires one package dependency from package "getPass". This will be installed automatically if you don't have it.
# i.e. "https://test.odk.lshtm.ac.uk/test"
# USER NAME
# i.e. "chrissy"
# DECRYPTION PEM LOCATION : Please enter the full path to the decryption key
# i.e. "D:/keys/PRIVATE.KEY.pem (PC)
# i.e. "/Volumes/POOKY/PRIVATE.KEY.pem (UNIX/LINUX/MAC)
# OUTPUT DIRECTORY
#
# to send to a specific folder use i.e. "output"
# to send to a timestamped folder use "export.dir.name<-format(Sys.time(), "%y%m%d.%H%M ")"
################################################################################################################
# USER MODIFIABLE SETTINGS
################################################################################################################
#server settings
urllocation<- "https://test.odk.lshtm.ac.uk/test"
user <- "username"
pemlocation<- "~/foo/bar/PRIVATE.KEY.pem"
#directories
export.dir.name <- "~/foo/bar/output"
report.dir.name <- "~/foo/bar/report"
storage.dir.name <- "~/foo/bar/XMLS"
#update software
update.briefcase<-FALSE
# add list of forms to pull in the line below (comma separated in double quotes)
formstopull<-c("FORM1","FORM2")
######################################################
#purge : delete all CSV data prior to run (will remove previous CSV files)
#autodelete : delete data after run (will delete CSV files after report made)
#deletexmlpre : delete previously pulled XML files prior to new pull
#deletexmlpost : delete previously pulled XML files after new pull
purge<-TRUE
autodelete<-FALSE
deletexmlpre<-FALSE
deletexmlpost<-FALSE
####deleteXMLS prior
if(deletexmlpre==T){
unlink(x = "XMLS",recursive = T)
}
################################################################################################################
####ODK Briefcase Call Function
################################################################################################################
#function to pull data from ODK Aggregate Server
################################################################################################################
odk.briefcase.pull<-
function(
aggregate.url=NULL, #arg -url <url>
odk.directory=NULL, #arg <path/to/dir>
odk.username="admin", #arg -u <username>
form.id=NULL, #arg -id <form_id>
export.dir=".", #arg -ed <path/to/dir>
storage.dir=".", #arg -sd <path/to/dir>
export.start.date=NULL, #arg -start <yyyy/MM/dd>
export.end.date=NULL, #arg -end <yyyy/MM/dd>
pem_file=NULL, #arg -pf <path/to/file.pem>
exclude.media.export=FALSE, #flag -em
overwrite.csv.export=TRUE, #flag -oc
update.odk.briefcase=FALSE
){
################################################################################################################
# Purge CSVs and delete XMLS if needed
############################################################################################################
if(deletexmlpre==T){
unlink(x = storage.dir,recursive = T)
}
if(purge==TRUE)
{
unlink(x = export.dir.name,recursive = T)
}
################################################################################################################
# INSTALL REQUIRED PACKAGES
############################################################################################################
message("installing packages if needed")
#check if getPass is installed and install it if not
message("checking for new packages")
list.of.packages <- c("getPass","anytime","tidyverse","plotKML","sp","rgdal","lubridate")
new.packages <- list.of.packages[!(list.of.packages %in% installed.packages()[,"Package"])]
if(length(new.packages))
{
install.packages(new.packages)
message (paste("Installing ",new.packages))
}
################################################################################################################
#check if update.odk.briefcase flag was active (default) and update odk briefcase
################################################################################################################
message("Checking to see if Briefcase should be updated.")
if(update.odk.briefcase==T)
{
message("Updating ODK Briefcase")
#download.file(url = "https://github.com/opendatakit/briefcase/releases/download/v1.10.1/ODK-Briefcase-v1.10.1.jar",
# destfile = paste( "./odkbriefcase.jar",sep = ""), method="curl", mode = "wb",extra="-L")
system("curl -L https://github.com/opendatakit/briefcase/releases/download/v1.10.1/ODK-Briefcase-v1.10.1.jar > ./odkbriefcase.jar")
}
################################################################################################################
#check that only online or offline is being used
############################################################################################################
if (!is.null(aggregate.url) & !is.null(odk.directory))
{
message("Please only specify one of aggregate.url and odk.directory")
}
################################################################################################################
#add flags for command line call
###############################################################################################################
if(!is.null(aggregate.url)){aggregate.url<-paste("-url ", aggregate.url, sep="")} #arg -url <url>
if(!is.null(odk.directory)){odk.directory<-paste("-od ", odk.directory, sep="")}
odk.username<-paste("-u ", odk.username, sep="")
export.dir<-paste("-ed ", export.dir, sep="")
storage.dir<-paste("-sd ", storage.dir, sep="")
if(!is.null(export.start.date)){export.start.date<-paste("-start ", export.start.date, sep="")}
if(!is.null(export.end.date)){export.end.date<-paste("-end ", export.end.date, sep="")}
if(!is.null(pem_file)){pem_file<-paste("-pf ", pem_file, sep="")}
if(exclude.media.export==T){exclude.media.export<-"-em"}else{exclude.media.export<-""}
if(overwrite.csv.export==T){overwrite.csv.export<-"-oc"}else{overwrite.csv.export<-""}
################################################################################################################
#Get Password for current user
################################################################################################################
password<- getPass(msg = "Enter Password for server")
password<- paste("-p ",password,sep="")
################################################################################################################
#Generate command for system call to odk briefcase for each form in form.id
################################################################################################################
for(p in form.id)
{
export.filename<-paste(p,"_",Sys.Date(),".csv",sep="")
if(!is.null(export.filename)){export.filename<-paste("-f ", export.filename, sep="")}
form.id2<-paste("-id ", p, sep="")
command<-paste("java -jar odkbriefcase.jar ",
aggregate.url,
odk.directory,
odk.username,
form.id2,
export.dir,
export.start.date,
export.end.date,
export.filename,
storage.dir,
pem_file,
exclude.media.export,
overwrite.csv.export,
password,
sep=" ")
system(command)
}
if(autodelete==TRUE){
unlink(x = export.dir.name,recursive = T)
}
####deleteXMLS
if(deletexmlpost==TRUE){
unlink(x = "XMLS",recursive = T)
}
}
################################################################################################################
################################################################################################################
# END OF FUNCTION
################################################################################################################
################################################################################################################
################################################################################################################
#create directories if needed
################################################################################################################
if(!file.exists(export.dir.name)){dir.create(export.dir.name)}
if(!file.exists(report.dir.name)){dir.create(report.dir.name)}
if(!file.exists(storage.dir.name)){dir.create(storage.dir.name)}
################################################################################################################
#### Run Call to ODK Briefcase
################################################################################################################
odk.briefcase.pull(aggregate.url = urllocation, odk.username = user,form.id = formstopull,export.dir = export.dir.name,storage.dir = storage.dir.name,exclude.media.export = F,overwrite.csv.export = T,update.odk.briefcase = update.briefcase, pem_file = pemlocation)
################################################################################################################
################################################################################################################
####GET THE LIST OF ALL FILES###
allcsvs<-list.files(path = export.dir.name,pattern = ".csv",full.names = T)
################################################################################################################

Comments are closed.