Most of the present technologies that record the video are unreliable. The videos themselves or their metadata can be tampered with. Hence it is not possible to prove the authenticity of the videos. Modifying the metadata of the videos like date and time of video, also makes it unreliable and not a valid proof of evidence for any purpose. The Trusted Timestamping Authorities (TSA) do provide the timestamping services to timestamp any data (videos in our case). But these TSAs are generally paid or if they are free, several limitations exist (Ex. Limited number of timestamping per day, etc.). And if these TSAs are compromised, all user data are compromised.
To solve this problem, we made use of the Decentralized Trusted Timestamping[1] concept. To learn more about the Decentralized Trusted Timestamping concept, please refer the research paper stated below. This concept is implemented by www.Originstamp.org.
What is Originstamp?
OriginStamp is a non-commercial free of charge trusted timestamping server that can be used to prove that a person was the originator of a piece of information at a certain point in time. The advantage of OriginStamp compared to other trusted timestamping methods is that it is free of charge and allows the user to create anonymous timestamps in a secure and valid manner that uses the cryptographic block chain of virtual bitcoins.
The main idea is to timestamp the video just after an incident has been recorded. Thus, not giving any chance for the user to modify the video. The concept works based on a SHA-256 hash generated from the video files recorded. This hash will change even if a single ‘bit’ of the data has been changed. Hence, if the user modifies the files later at any point in time, the hash will not match with the hash that was sent to Originstamp server. This restricts the user to modify the video file in any way. The authenticity of the video files can be verified by regenerating the hash and matching it with the once that is already on the Originstamp server along with its timestamp.
As a proof-of-concept, we created an Android application for using it as a dash cam. The user needs to put their smartphone on the dash cam holder and turn on the application. The application will continuously record the video unless the user stops the application manually or any collision has been detected. Once the collision has been detected, the relevant part of the video will be extracted and a hash will be generated. This hash will then be sent to the Originstamp server for timestamping. The videos and the hash is made available to the user for future reference and verifying it on the server. This concept can be used by the judicial system or by an insurance company to verify the authenticity of the video evidences submitted by the user.
During the workshop session multiple design solutions were proposed like PhoneGap, Cordova, Xamarin, etc. These cross-platform mobile application development framework have limitations when it comes to interacting with hardware. Either the developer needs to switch to native App development (like we did) or be prepared to develop the plugins. We switched to Android by which we can access all the features of a phone that are needed by the application and offers the possibility to run the application in the background.
The application can be used by any person that owns an Android device with internet connection to access the application and send the hash of the evidence video, a camera that records the video and an accelerometer which detects the collision. The user turns on the application and locks the application in Task Manager and the application does the rest of the work. Video will be continuously and only the important length of the video will be hashed and sent for timestamping. In this case the user will be notified about the process and he will be able to access his events in a history panel along with verification details, so he can use the system for legal purposes.
Only the important part of the code is listed here.
For more detailed and complete code please visit this github page.
For continuous video recording
while(!accidentStatus){ int i =1; while(i < 3) { if (!accidentStatus && !manualStopStatus) { accidentOnVideoIndex = i; startRecording("dashit" + i); try { Thread.sleep(10000); if(recordingStatus) stopRecording(); } catch (InterruptedException e) { e.printStackTrace(); } i++; }else{ break; } } } if(!manualStopStatus) { startRecording("dashit3"); try { Thread.sleep(10000); stopRecording(); generateHash(); } catch (InterruptedException e) { e.printStackTrace(); } }
@Override public void onSensorChanged(SensorEvent event) { float x = event.values[0]; float y = event.values[1]; float z = event.values[2]; long curTime = System.currentTimeMillis(); if ((curTime - lastUpdate) > 100) { long diffTime = (curTime - lastUpdate); lastUpdate = curTime; float speed = Math.abs(x + y + z - last_x - last_y - last_z)/ diffTime * 10000; if(Math.abs(x-last_x) > 8 || Math.abs(y-last_y) > 8 || Math.abs(z-last_z) > 8){ System.out.println("Sensor collision!!!"); Intent intent = new Intent(); intent.setAction("com.example.Broadcast"); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); sendBroadcast(intent); } last_x = x; last_y = y; last_z = z; } new SensorEventLoggerTask().execute(event); stopSelf(); }
public void generateHash(){ int[] orderOfVideo = new int[3]; ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); if(accidentOnVideoIndex == 2){ orderOfVideo[0] = 1; orderOfVideo[1] = 2; }else{ orderOfVideo[0] = 2; orderOfVideo[1] = 1; } orderOfVideo[2] = 3; File dir = new File("/sdcard/dashitHistory/"+ DateFormat.format("dd-MM-yyyy HH:mm", new Date().getTime())); if(!dir.isDirectory()) dir.mkdirs(); File saveFile; for(int i=0;i<3;i++){ File file = new File("/sdcard/dashit"+orderOfVideo[i]+".mp4"); if(file.exists() && !file.isDirectory()){ byte[] byteArray = new byte[(int)file.length()]; InputStream fileInputStream; try { fileInputStream = new FileInputStream(file); fileInputStream.read(byteArray); System.out.println("File length::" + byteArray.length); outputStream.write(byteArray); fileInputStream.close(); fileInputStream = new FileInputStream(file); saveFile = new File(dir.getPath()+"/"+(i+1)+"accVideo"+orderOfVideo[i]+".mp4"); OutputStream out = new FileOutputStream(saveFile); byte[] buf = new byte[1024]; int len; while ((len = fileInputStream.read(buf)) > 0) { out.write(buf, 0, len); } fileInputStream.close(); out.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } byte[] finalByte = outputStream.toByteArray(); System.out.println("Final Byte Array Length::" + finalByte.length); try { MessageDigest md = MessageDigest.getInstance("SHA-256"); md.update(finalByte); byte[] mdBytes = md.digest(); StringBuffer hexString = new StringBuffer(); for (int i=0;i<mdBytes.length;i++) { hexString.append(Integer.toHexString(0xFF & mdBytes[i])); } System.out.println("Hex format : " + hexString.toString()); //Create a hash.txt file File hash = new File(dir.getPath()+"/hash.txt"); FileWriter writer = new FileWriter(hash); writer.append(hexString.toString()); writer.flush(); writer.close(); sendHashToServer(hexString.toString()); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
OriginStamp access
OriginStamp is called by a HTTP request to the API. For the API to authorize access a parameter
Token token=”{YOUR_API_KEY}” needs to be provided in the Authorization field.
Example request:
POST http://www.originstamp.org/api/stamps Authorization: Token token="{YOUR_API_KEY}" Content-Type: application/json {"hash_sha256":"6b4a1673b225e8bf5f093b91be8c864427df32ca41b17cc0b82112b8f0185e41"}
public void sendHashToServer(String hashString){ String url = "http://www.originstamp.org/api/stamps"; String postData = "{\"hash_sha256\" : \""+hashString+"\"}"; try { URL obj = new URL(url); HttpURLConnection con = (HttpURLConnection) obj.openConnection(); con.setRequestMethod("POST"); con.setRequestProperty("Content-Type", "application/json"); con.setRequestProperty("Authorization", "Token token=\"a876e0bbb8894e8c8eadc5b3a19adff7\""); con.setRequestProperty("User-Agent","Mozilla/5.0 ( compatible ) "); con.setRequestProperty("Accept","*/*"); DataOutputStream dos = new DataOutputStream(con.getOutputStream()); dos.writeBytes(postData); dos.flush(); dos.close(); String line; BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream())); while ((line = reader.readLine()) != null) { System.out.println(line); } reader.close(); handler.post(new Runnable() { @Override public void run() { Toast.makeText(BackgroundService.this, "Hash sent successfully!", Toast.LENGTH_LONG).show(); } }); } catch (MalformedURLException e) { e.printStackTrace(); handler.post(new Runnable() { @Override public void run() { Toast.makeText(BackgroundService.this, "Problems while sending hash. Please check you internet connection.", Toast.LENGTH_LONG).show(); } }); } catch (IOException e) { e.printStackTrace(); handler.post(new Runnable() { @Override public void run() { Toast.makeText(BackgroundService.this, "Problems while sending hash. Please check you internet connection.", Toast.LENGTH_LONG).show(); } }); } }
[1] B. Gipp, N. Meuschke, and A. Gernandt. Decentralized Trusted Timestamping using the Crypto Currency Bitcoin. In Proceedings of the iConference 2015 (to appear), Newport Beach, CA, USA, Mar. 24 -27, 2015.
[2] N. Feigenson. Visual Evidence. Psychonomic Bulletin & Review, 2010, 17 (2), 149-154